本文转载自:http://blog.csdn.net/kmesg/article/details/6531577
本文只关注JNI和HAL的接口部分
在jni的android_location_GpsLocationProvider.cpp中,作者定义了一些callback函数和结构体
- tatic void location_callback(GpsLocation* location)
- {
- pthread_mutex_lock(&sEventMutex);
- sPendingCallbacks |= kLocation;
- memcpy(&sGpsLocation, location, sizeof(sGpsLocation));
- pthread_cond_signal(&sEventCond);
- pthread_mutex_unlock(&sEventMutex);
- }
- static void status_callback(GpsStatus* status)
- ....
- }
- static void sv_status_callback(GpsSvStatus* sv_status)
- {
- ....
- }
- static void nmea_callback(GpsUtcTime timestamp, const char* nmea, int length)
- {
- ...
- }
- GpsCallbacks sGpsCallbacks = {
- location_callback,
- status_callback,
- sv_status_callback,
- nmea_callback
- };
这个sGpsCallbacks结构体其实就是一个函数指针的结构体,,太bt了。。它在android_location_GpsLocationProvider_init中被传到底层。
- if (!sGpsInterface)
- sGpsInterface = gps_get_interface();
- if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
- return false;
那么你可能很奇怪,这么bt的函数指针用法是为了什么?,再看android_location_GpsLocationProvider_wait_for_event里一段就明白了。
- static void android_location_GpsLocationProvider_wait_for_event(JNIEnv* env, jobject obj)
- {
- pthread_mutex_lock(&sEventMutex);
- while (sPendingCallbacks == 0) {
- pthread_cond_wait(&sEventCond, &sEventMutex);
- }
- ...
这里pthread_cond_wait一直阻塞等待一个状态(数据传输过来),而location_callback里的pthread_cond_signal(&sEventCond)就是来唤醒它的。。再看pthread_cond_signal的前一句 memcpy(&sGpsLocation, location, sizeof(sGpsLocation));你估计就幡然醒悟了。。。在jni一层阻塞一事件,然后定义一函数来唤醒,而唤醒这个动作必须在底层(数据传输),所以就定义一个函数指针传下去,让底层调用这个函数来唤醒阻塞的进程。。。
下面是底层调用callback函数,这个callback函数在底层传了无数遍后终于在nmea函数里被调用了
- static void
- nmea_reader_set_callback( NmeaReader* r, gps_location_callback cb )
- {
- r->callback = cb;
- if (cb != NULL && r->fix.flags != 0) {
- D("%s: sending latest fix to new callback", __FUNCTION__);
- r->callback( &r->fix );
- r->fix.flags = 0;
- }
- }
其实gps数据在底层被读到了NmeaReader这个类里面,fix就是Gps的数据结构体,然后r->callback( &r->fix );就完成了调用。
typedef struct {
int pos;
int overflow;
int utc_year;
int utc_mon;
int utc_day;
GpsLocation fix;
gps_location_callback callback;
char in[ NMEA_MAX_SIZE+1 ];
} NmeaReader;