android 2.3 GPS 移植實(shí)戰(zhàn)
研究了一個(gè)月,終于把 android 2.3 GPS 驅(qū)動(dòng)個(gè)弄出來了。由于開發(fā)板提供的 GPS HAL 代碼為 SO 文件,
項(xiàng)目把 GPS 模塊給換了一個(gè) UART 口,導(dǎo)致 HAL 層代碼需要重新寫。
剛剛開始接觸 ANDROID GPS 的時(shí)候一頭霧水,只好在網(wǎng)上找了很多關(guān)于GPS流程的說明。大致了解了GPS于哪幾個(gè)文件有關(guān)
/framework/base/services/jni/com_android_server_location_GpsLocationProvider.cpp
hardware/libhardware_legacy/gps
hardware/libhardware_legacy/include/hardware_legacy/gps.h
通過查看文件,發(fā)現(xiàn)我的源碼包里面?hardware/libhardware_legacy 目錄里面沒 GPS 文件夾。
咋整呢?
沒辦法,自己創(chuàng)建一個(gè)?
hardware/libhardware/modules/ ?下創(chuàng)建一個(gè) 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 到 剛剛創(chuàng)建的 GPS 文件夾內(nèi)。
這樣文件有了,就差一個(gè) Android.mk 文件了。?
本人對這個(gè)文件并不熟悉,沒辦法,還是 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 打開串口設(shè)備
state->fd = open(GPS_Serial_Name, O_RDONLY );
這里打開串口,GPS_Serial_Name?這根據(jù)自己的設(shè)備查找對應(yīng)串口的設(shè)備節(jié)點(diǎn)。
設(shè)置串口事件
// 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 線程里面不會(huì)接收串口數(shù)據(jù)。
這樣 Android 的 HAL 層于串口就接通了。
接下來就是解析串口數(shù)據(jù),由于模擬器里面已經(jīng)有解析 RMC 的GPS結(jié)構(gòu)。
所以直接測試就可以了。
直接測試后發(fā)現(xiàn)當(dāng)有 GPS 數(shù)據(jù)調(diào)用 CALLBACK 函數(shù)
?if (r->callback)?
{
? ? ? ? ? ? r->callback( &r->fix );
? ? ? ? ? ? r->fix.flags = 0;
}
后 ANDROID 重啟了,查詢網(wǎng)上資料,發(fā)現(xiàn)很多同志在 2.3 也碰到這問題,主要是創(chuàng)建線程的問題。
把創(chuàng)建線程的函數(shù)換一下就好了。
/*
? ? 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);
這樣系統(tǒng)就能正常啟動(dòng)并接收經(jīng)緯度了。
接收經(jīng)緯度后 關(guān)閉 GPS 再打開,發(fā)現(xiàn) GPS 沒有經(jīng)緯度了,奇怪
通過跟蹤,發(fā)現(xiàn)在 GPS 關(guān)閉后會(huì)調(diào)用 HAL 層 ?qemu_gps_cleanup?把串口關(guān)閉,
當(dāng)重新開啟的時(shí)候 調(diào)用 JNI?
/framework/base/services/jni/com_android_server_location_GpsLocationProvider.cpp
里面的?android_location_GpsLocationProvider_init,發(fā)現(xiàn)里面的?sGpsInterface 指針已經(jīng)存在,
就不會(huì)調(diào)用?sGpsInterface->init 函數(shù)。
所以在 JNI 層的 cleanup 函數(shù)里面把這個(gè)指針清除。
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 移植已經(jīng) OK 現(xiàn)在還有一個(gè) BUG 就是狀態(tài)欄那個(gè) GPS 圖標(biāo),
關(guān)閉 GPS 后不知道為什么不會(huì)消失,還需要進(jìn)一步研究。
下面是我的?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