近期任務是把產品的gps適配到android2.3源碼中,一般的移植做法是:從串口中讀取gps nema資料,在gps硬體適配層(HAL)對資料進行解析並上報到Framework層。我的工作需求不同,對串口的讀寫操作統一由一個串口代理負責,gps只需與串口代理通訊,擷取nema資料。
概括來說,gps移植有以下幾個工作:
(1)在串口代理中實現socket進程通訊服務端,負責把串口代理從串口讀到的資料發送到socket用戶端,並把socket用戶端發來的資料交由串口代理寫入串口。
(2)在gps適配層實現socket進程通訊用戶端,負責與串口代理中的socket伺服器通訊。
(3)gps適配層把由socket用戶端讀取的nema資料解析並上報。
socket通訊在本篇中就不詳談了,主要說gps適配。
(1)首先在android 2.3源碼建立目錄hardware/libhardware/modules/gps,把sdk/emulator/gps/gps_qemu.c複製到建立的目錄
(2)建立Android.mk檔案,內容為:
LOCAL_PATH := $(call my-dir)ifneq ($(TARGET_PRODUCT),sim)# HAL module implemenation, not prelinked and stored in# hw/<GPS_HARDWARE_MODULE_ID>.<ro.hardware>.soinclude $(CLEAR_VARS)LOCAL_PRELINK_MODULE := falseLOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hwLOCAL_CFLAGS += -DQEMU_HARDWARELOCAL_SHARED_LIBRARIES := liblog libcutils libhardwareLOCAL_SRC_FILES := gps_qemu.c socket_msg.cLOCAL_MODULE := gps.defaultLOCAL_MODULE_TAGS := debuginclude $(BUILD_SHARED_LIBRARY)
切記:LOCAL_MODULE最好為:gps.default,否則很有可能導致上層調用不到so動態庫。
(3)修改gps_qemu.c,主要包括以下幾個方面:
1.修改gps_state_init函數,刪除與qemu通訊的初始化代碼,改為與我的socket服務端進行通訊。
static voidgps_state_init( GpsState* state, GpsCallbacks* callbacks ){ state->init = 1; state->control[0] = -1; state->control[1] = -1; state->fd = -1; /*state->fd = qemud_channel_open(QEMU_CHANNEL_NAME); if (state->fd < 0) { D("no gps emulation detected"); return; } D("gps emulation will read from '%s' qemud channel", QEMU_CHANNEL_NAME );*///initialize cache,and register callback function to handle messagesocket_cache_init(&state->cache,gps_msg_handle); //Connect to socket server if(gps_socket_connect(state) == 0){goto Fail; } if ( socketpair( AF_LOCAL, SOCK_STREAM, 0, state->control ) < 0 ) { LOGE("could not create thread control socket pair: %s", strerror(errno)); goto Fail; } state->thread = callbacks->create_thread_cb( "gps_state_thread", gps_state_thread, state ); if ( !state->thread ) { LOGE("could not create gps thread: %s", strerror(errno)); goto Fail; } state->callbacks = *callbacks; D("gps initialized success!");//start gpsgps_state_start(state); return;Fail: gps_state_done( state );}
2.修改gps_state_thread函數,當socket服務端有資料來的時候,調用我的處理函數進行處理(主要包括對socket訊息的解析)。
else if (fd == gps_fd) { //char buff[32]; unsigned char buff[32 + SOCKET_MSG_FORMAT_SIZE]; D("gps fd event"); for (;;) { int nn, ret; ret = read( fd, buff, sizeof(buff) ); if (ret < 0) { if (errno == EINTR) continue; if (errno != EWOULDBLOCK) LOGE("error while reading from gps daemon socket: %s:", strerror(errno)); break; } //D("received %d bytes: %.*s", ret, ret, buff);gps_msg_recv(state,buff,ret,(void *)reader);/* for (nn = 0; nn < ret; nn++) nmea_reader_addc( reader, buff[nn] );*/ } D("gps fd event end"); }
(3)然後對模組進行編譯,並打包sysem.img鏡像檔案
mmm hardware/libhardware/modules/gps make snod
提示:產生的gps.default.so最終會在out/target/product/generic/system/lib/hw目錄下,如果該目錄下同時還有gps.goldfish.so檔案,必須先把gps.goldfish.so檔案刪除,然後再打包鏡像檔案。
(4)剩下的就是測試了...