天天看點

android gps 序列槽,Android GPS資料上報(基于gps_qemu.c)

Android GPS資料上報(基于gps_qemu.c)

在網上找了好久關于這方面的東西,可都是介紹啟動的,現在我把我了解的其資料上報的流程寫下來,以作記錄:

(主要基于gps_qemu.c的資料上報)

hardware/libhardware_legacy/gps/gps_qemu.c(HAL層)

相關閱讀:Android GPS資料上報線程的開啟流程

資料從序列槽傳上來主要是通過函數static void* gps_state_thread( void*  arg )接收,并解析上報給

android_location_GpsLocationProvider.cpp(JNI層)的,下面首先來看gps_state_thread中資料抓取及資料解析:

else if (fd == gps_fd)

{

char  buff[32];

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);

for (nn = 0; nn < ret; nn++)

nmea_reader_addc( reader, buff[nn] );//解析資料并上報)

}

D("gps fd event end");

}

接下來看nmea_reader_addc函數(在gps_qemu.c中):

if (c == '/n') {

nmea_reader_parse( r ); //解析資料并上報

r->pos = 0;

}

函數nmea_reader_parse( NmeaReader*  r )(在gps_qemu.c中)

if (r->callback) {

r->callback( &r->fix ); //這句就是上報資料了

r->fix.flags = 0;

}

else {

D("no callback, keeping data until needed !");

}

=====================================注釋一===================================

這裡有個回調函數r->callback,這個回調函數是在gps_state_thread函數中通過nmea_reader_set_callback函數設定的,nmea_reader_set_callback中有這樣的語句:

r->callback = cb;//這就是設定了

而在gps_state_thread中傳給nmea_reader_set_callback的state->callbacks.location_cb參數是在這裡設定的

static int qemu_gps_init(GpsCallbacks* callbacks)

{

GpsState*  s = _gps_state;

if (!s->init)

gps_state_init(s);

if (s->fd < 0)

return -1;

s->callbacks = *callbacks;

return 0;

}

而函數qemu_gps_init是在qemuGpsInterface結構體中被JNI(c/c++部分)層調用的,在JNI(c/c++部分)層怎樣調用,這将在注釋二中解釋

============================================================================

在這裡,資料在HAL層的路已經走完,下面就進入到JNI(c/c++部分)層android_location_GpsLocationProvider.cpp中了

在這層中首先接收到資料的是函數location_callback:

memcpy(&sGpsLocation, location, sizeof(sGpsLocation));//這裡把接收到的資料傳給sGpsLocation結構體

接着再在android_location_GpsLocationProvider_wait_for_event中:

if (pendingCallbacks & kLocation)

memcpy(&sGpsLocationCopy, &sGpsLocation, sizeof(sGpsLocationCopy));//把資料傳給sGpsLocationCopy結構體

。。。。。。。這裡省略了幾行。。。。。。

if (pendingCallbacks & kLocation) {

env->CallVoidMethod(obj, method_reportLocation, sGpsLocationCopy.flags,           //把資料上報給上層(注釋二中解釋相關函數)

(jdouble)sGpsLocationCopy.latitude, (jdouble)sGpsLocationCopy.longitude,

(jdouble)sGpsLocationCopy.altitude,

(jfloat)sGpsLocationCopy.speed, (jfloat)sGpsLocationCopy.bearing,

(jfloat)sGpsLocationCopy.accuracy, (jlong)sGpsLocationCopy.timestamp);

}

=====================================注釋二===================================

在這一層裡location_callback,是怎樣接收到資料呢?

其實這個函數是作為一個回調函數,在HAL層中調用的,其是通過調用qemu_gps_init函數把location_callback注冊到HAL層中的

我沒看下調用qemu_gps_init,在函數android_location_GpsLocationProvider_init(JNI層):

if (!sGpsInterface)

sGpsInterface = gps_get_interface();//這句是獲得在HAN層定義的GpsInterface指針,gps_get_interface

//定義在hardware/libhardware_legacy/gps/gps.cpp

if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)      //這裡調用的init就是調用qemu_gps_init了

return false;                                                            //參數sGpsCallbacks就是包含location_callback指針的結構體了

sGpsCallbacks定義如下:

GpsCallbacks sGpsCallbacks = {

location_callback,

status_callback,

sv_status_callback,

nmea_callback

};

***********************我是分隔線************************

android_location_GpsLocationProvider_wait_for_event函數就注冊成了java層中的接口了,env是由上層傳下來的參數,具體請參考JNI的相關知識

下面的代碼,完成了這個函數的注冊:

static JNINativeMethod sMethods[] = {

。。。省略。。。

{"native_wait_for_event", "()V", (void*)android_location_GpsLocationProvider_wait_for_event},

。。。省略。。。

};

int register_android_location_GpsLocationProvider(JNIEnv* env)

{

return jniRegisterNativeMethods(env, "com/android/internal/location/GpsLocationProvider", sMethods, NELEM(sMethods));

}

****************我是分隔線********************

env->CallVoidMethod(obj, method_reportLocation, sGpsLocationCopy.flags,           //把資料上報給上層

(jdouble)sGpsLocationCopy.latitude, (jdouble)sGpsLocationCopy.longitude,

(jdouble)sGpsLocationCopy.altitude,

(jfloat)sGpsLocationCopy.speed, (jfloat)sGpsLocationCopy.bearing,

(jfloat)sGpsLocationCopy.accuracy, (jlong)sGpsLocationCopy.timestamp);

參數method_reportLocation,是在下面的函數(android_location_GpsLocationProvider)中被映射為java的reportLocation(在GpsLocationProvider.java中)方法:

static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {

method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");

。。。省略。。。

}

在java層中GpsLocationProvider.java的reportLocation:

private void reportLocation(int flags, double latitude, double longitude, double altitude,

float speed, float bearing, float accuracy, long timestamp) {

if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude +

" timestamp: " + timestamp);

mLastFixTime = System.currentTimeMillis();

。。。省略。。。

}

這個函數是(JNI Java部分)java注冊到JNI(c/C++部分)中的一個回調,我了解為隻用來傳遞資料。

1

2

3

4

下一頁