Android GPS架构分析
Daniel Wood 20101224
转载时请注明出处和作者
文章出处:http://danielwood.cublog.cn
作者:Daniel Wood
--------------------------------------------------------------------------------
分析完了enable函数以后就轮到 enableLocationTracking 函数了。
GpsLocationProvider.java
public void enableLocationTracking( boolean enable ) { synchronized ( mHandler) { mHandler. removeMessages( ENABLE_TRACKING) ; Message m = Message. obtain( mHandler, ENABLE_TRACKING) ; m. arg1 = ( enable ? 1 : 0) ; mHandler. sendMessage( m) ; } }
同样地,也采取Handler的方式。调用的是handleEnableLocationTracking函数。
private void handleEnableLocationTracking( boolean enable ) { if ( enable ) { mTTFF = 0; mLastFixTime = 0; startNavigating ( ) ; } else { mAlarmManager. cancel ( mWakeupIntent) ; mAlarmManager. cancel ( mTimeoutIntent) ; stopNavigating( ) ; } }
调用startNavigating函数。
private void startNavigating( ) { if ( ! mStarted) { if ( DEBUG) Log . d( TAG, "startNavigating" ) ; mStarted = true; int positionMode; if ( Settings. Secure. getInt ( mContext. getContentResolver( ) , Settings. Secure. ASSISTED_GPS_ENABLED, 1) ! = 0) { positionMode = GPS_POSITION_MODE_MS_BASED; } else { positionMode = GPS_POSITION_MODE_STANDALONE; } if ( ! native_start ( positionMode, false, 1) ) { mStarted = false; Log . e( TAG, "native_start failed in startNavigating()" ) ; return ; }
...
在startNavigating函数中,最有作用的语句就是调用native方法native_start 。调用到了JNI层的android_location_GpsLocationProvider_start函数。
android_location_GpsLocationProvider.cpp
static jboolean android_location_GpsLocationProvider_start( JNIEnv* env, jobject obj, jint positionMode, jboolean singleFix, jint fixFrequency) { int result = sGpsInterface- > set_position_mode( positionMode, ( singleFix ? 0 : fixFrequency) ) ; if ( result) { return false ; } return ( sGpsInterface- > start ( ) = = 0) ; }
接下去就会调用 sGpsInterface 接口的实现gps_qemu.c中具体实现的函数。
static int qemu_gps_start( ) { GpsState* s = _gps_state; if ( ! s- > init) { D( "%s: called with uninitialized state !!" , __FUNCTION__ ) ; return - 1; } D( "%s: called" , __FUNCTION__ ) ; gps_state_start( s) ; return 0; }
通过向底层发送命令,CMD_START来启动gps。其实这个所谓的底层就是在enable/init函数中启动的等待数据的线程。
static void gps_state_start( GpsState* s ) { char cmd = CMD_START; int ret; do { ret= write ( s- > control[ 0] , & cmd, 1 ) ; } while ( ret < 0 & & errno = = EINTR) ; if ( ret ! = 1) D( "%s: could not send CMD_START command: ret=%d: %s" , __FUNCTION__ , ret, strerror ( errno ) ) ; }
数据监听线程
static void * gps_state_thread( void * arg ) { . . . // now loop for ( ; ; ) { . . . if ( cmd = = CMD_QUIT) { D( "gps thread quitting on demand" ) ; goto Exit ; } else
if ( cmd = = CMD_START) {
if (!started) { D("gps thread starting location_cb=%p", state>callbacks.location_cb); started = 1; nmea_reader_set_callback ( reader, state->callbacks.location_cb ); } } else if (cmd == CMD_STOP) {
...
}
其实就是注册了一个回调函数,location_cb 这个回调函数就是对底层location数据上报的回调函数。
在enableLocationTracking函数调用完成以后,基本上gps服务已经启动完成了,也就是 LocationManagerService中的updateProvidersLocked函数的完成,也就是loadProviders函数的完 成,也就是initialize函数的完成,也就是run函数的完成,也就是2.2中反馈机制systemReady 的完成。
void systemReady( ) { // we defer starting up the service until the system is ready Thread thread = new Thread ( null , this , "LocationManagerService" ) ; thread . start ( ) ; }