android 2.3 GPS 移植实战
扫描二维码
随时随地手机看文章
研究了一个月,终于把 android 2.3 GPS 驱动个弄出来了。由于开发板提供的 GPS HAL 代码为 SO 文件,
项目把 GPS 模块给换了一个 UART 口,导致 HAL 层代码需要重新写。
刚刚开始接触 ANDROID GPS 的时候一头雾水,只好在网上找了很多关于GPS流程的说明。大致了解了GPS于哪几个文件有关
/framework/base/services/jni/com_android_server_location_GpsLocationProvider.cpp
hardware/libhardware_legacy/gps
hardware/libhardware_legacy/include/hardware_legacy/gps.h
通过查看文件,发现我的源码包里面 hardware/libhardware_legacy 目录里面没 GPS 文件夹。
咋整呢?
没办法,自己创建一个
hardware/libhardware/modules/ 下创建一个 GPS 文件夹, 在 hardware/libhardware_legacy/ 这下面也一样的,
记得修改 Android.mk 就可以了。
修改 hardware/libhardware/ 下的 Android.mk 文件
include $(addsuffix /Android.mk, $(addprefix $(LOCAL_PATH)/,
modules/gralloc
modules/gps
tests
))
把GPS文件夹包含的编译文件里面。
由于 android 模拟器有模拟 GPS 的源码,依葫芦画瓢呗。
把 gps_qemu.c 文件 COPY 到 刚刚创建的 GPS 文件夹内。
这样文件有了,就差一个 Android.mk 文件了。
本人对这个文件并不熟悉,没办法,还是 COPY 把,把类似的 文件夹里面的 Android.mk 文件 COPY 过来做一些修改。
修改里面包含的文件啊,路径之类的。
我的 Android.mk 文件如下:
LOCAL_PATH := $(call my-dir)
# HAL module implemenation, not prelinked and stored in
# hw/
下一步就是 gps_qemu.c 的修改了
首先是 gps_state_init 打开串口设备
state->fd = open(GPS_Serial_Name, O_RDONLY );
这里打开串口,GPS_Serial_Name 这根据自己的设备查找对应串口的设备节点。
设置串口事件
// disable echo on serial lines
if ( isatty( state->fd ) ) {
struct termios ios;
tcgetattr( state->fd, &ios );
ios.c_lflag = 0; /* disable ECHO, ICANON, etc... */
ios.c_oflag &= (~ONLCR); /* Stop n -> rn translation on output */
ios.c_iflag &= (~(ICRNL | INLCR)); /* Stop r -> n & n -> r translation on input */
ios.c_iflag |= (IGNCR | IXOFF); /* Ignore r & XON/XOFF on input */
cfsetispeed(&ios, B38400);
cfsetospeed(&ios, B38400);
tcsetattr( state->fd, TCSANOW, &ios );
}
这一步非常重要,如果没有这一步,那么在 GPS HAL 线程里面不会接收串口数据。
这样 Android 的 HAL 层于串口就接通了。
接下来就是解析串口数据,由于模拟器里面已经有解析 RMC 的GPS结构。
所以直接测试就可以了。
直接测试后发现当有 GPS 数据调用 CALLBACK 函数
if (r->callback)
{
r->callback( &r->fix );
r->fix.flags = 0;
}
后 ANDROID 重启了,查询网上资料,发现很多同志在 2.3 也碰到这问题,主要是创建线程的问题。
把创建线程的函数换一下就好了。
/*
if ( pthread_create( &state->thread, NULL, gps_state_thread, state ) != 0 ) {
LOGE("could not create gps thread: %s", strerror(errno));
goto Fail;
}
*/
state->thread = state->callbacks.create_thread_cb("qemu_gps", gps_state_thread, state);
这样系统就能正常启动并接收经纬度了。
接收经纬度后 关闭 GPS 再打开,发现 GPS 没有经纬度了,奇怪
通过跟踪,发现在 GPS 关闭后会调用 HAL 层 qemu_gps_cleanup 把串口关闭,
当重新开启的时候 调用 JNI
/framework/base/services/jni/com_android_server_location_GpsLocationProvider.cpp
里面的 android_location_GpsLocationProvider_init,发现里面的 sGpsInterface 指针已经存在,
就不会调用 sGpsInterface->init 函数。
所以在 JNI 层的 cleanup 函数里面把这个指针清除。
static void android_location_GpsLocationProvider_cleanup(JNIEnv*
env, jobject obj)
{
const GpsInterface* interface = GetGpsInterface(env, obj);
LOGE("%s n", __FUNCTION__);
if (interface)
interface->cleanup();
sGpsInterface = NULL ;
}
这样就可以啦, GPS 移植已经 OK 现在还有一个 BUG 就是状态栏那个 GPS 图标,
关闭 GPS 后不知道为什么不会消失,还需要进一步研究。
下面是我的 gps_qemu.c 文件。
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* this implements a GPS hardware library for the Android emulator.
* the following code should be built as a shared library that will be
* placed into /system/lib/hw/gps.goldfish.so
*
* it will be loaded by the code in hardware/libhardware/hardware.c
* which is itself called from android_location_GpsLocationProvider.cpp
*/
#include