Android GPS架构分析(四)

Android GPS架构分析
Daniel Wood 20101224
转载时请注明出处和作者
文章出处:http://danielwood.cublog.cn
作者:Daniel Wood
--------------------------------------------------------------------------------
通过调用GpsLocationProvider类的enable和 enableLocationTracking函 数就把GPS的LocationManager服务启动起来了。下面对这两个函数进行分析。

首先是enable函数。

GpsLocationProvider.java

public void enable ( ) {
        synchronized ( mHandler) {
            mHandler. removeMessages( ENABLE ) ;
            Message m = Message. obtain( mHandler, ENABLE ) ;
            m. arg1 = 1;
            mHandler. sendMessage( m) ;
        }
    }

对了,这个要提一点,在2.2中加入了一个ProviderHandler类(extends Handler),这个在2.1中是没有的,其实是换汤不换药的,对于函数调用的过程来说没有本质的改变。对于Handler的机制我还没有研究过。

public void handleMessage( Message msg)
        {
            switch ( msg. what) {
                case ENABLE :
                    if ( msg. arg1 = = 1) {
                        handleEnable( ) ;
                    } else {
                        handleDisable( ) ;
                    }
                    break ;
                case ENABLE_TRACKING:
                    handleEnableLocationTracking( msg. arg1 = = 1) ;
                    break ;

                 ...

handleMessage函数中,定义了各种message对应的处理函数。对于ENABLE消息还带有一个参数,enable函数里面带的参数值为1,所以调用handleEnable函数。

private void handleEnable( ) {
        if ( DEBUG) Log . d( TAG, "handleEnable" ) ;
        if ( mEnabled) return ;
        mEnabled = native_init( ) ;
        if ( mEnabled) {
            if ( mSuplServerHost ! = null ) {
                native_set_agps_server( AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort) ;
            }
            if ( mC2KServerHost ! = null ) {
                native_set_agps_server( AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort) ;
            }
            // run event listener thread while we are enabled
            mEventThread = new GpsEventThread( ) ;
             mEventThread. start ( ) ;
        } else {
            Log . w( TAG, "Failed to enable location provider" ) ;
        }
    }

handleEnable函数中中主要做了3件事,不过有一件事情没有做成。先来看看哪三件事:

1)调用了 native 的初始化方法对 gps 进行初始化,

2)试图启动agps服务,

3)并启动一个线程去监听事件。

先 来说说它没有做成的第二件事,启动agps服务。其实在GpsLocationProvider类构造的时候就试图去读取agps的配置文件"/etc /gps.conf",该文件里面储存着agps的服务器地址以及端口号,但是服务器地址以及端口号都是错误的,所以它基本上无法启动agps服务,而且 对模拟器来说agps基本是个鸡肋。关于agps部分可能在以后的以后会提到。下面看它做成的第一和第三件事。

1) 调用native方法native_init,就是JNI层的android_location_GpsLocationProvider_init方法,在文件andoird_location_GpsLocationProvider.cpp中。

static jboolean android_location_GpsLocationProvider_init( JNIEnv* env, jobject obj)
{
    if ( ! sGpsInterface)
        sGpsInterface = gps_get_interface( ) ;
    if ( ! sGpsInterface | | sGpsInterface- > init ( & sGpsCallbacks) ! = 0)
        return false ;

    ...

    return true;

}


在初始化函数中会去确认 GpsInterface 是否已经得到,如果没有得到那么通过 gps_get_interface() 方法再次去得到,正如其实前面提到的那样该接口已经在 android_location_GpsLocationProvider_is_supported 函数(第一个吃螃蟹的人)中得到了。然后在第二个 if 语句中调用初始化方法 sGpsInterface- > init。

android_location_GpsLocationProvider_init的后半部分,试图通过GpsInterface->get_extension方法去得到gps相关的扩展接口,可是在2.2的模拟器实现中并没有实现这个函数,在gps_qume.c中明显写着return NULL。

gps_qume.c

static const void *
qemu_gps_get_extension( const char * name)
{
    return NULL ;
}

言归正传,分析sGpsInterface- > init方法。

gps_qume.c

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

sGpsInterface- > init中,也就是在qemu_gps_init方法,首先调用了gps_state_init,其次注册了回调函数,再说一次,这个回调函数就是在JNI层实现的,而且有JNI层传下来的函数。

static void
gps_state_init( GpsState* state )
{
    state- > init = 1;
    state- > control[ 0] = - 1;
    state- > control[ 1] = - 1;
    state- > fd = - 1;
    state- > fd = qemu_channel_open ( & state- > channel,
                                   QEMU_CHANNEL_NAME,
                                   O_RDONLY ) ;
    if ( state- > fd < 0) {
        D( "no gps emulation detected" ) ;
        return ;
    }
    D( "gps emulation will read from '%s' qemud channel" , QEMU_CHANNEL_NAME ) ;
    if ( socketpair ( AF_LOCAL , SOCK_STREAM , 0, state- > control ) < 0 ) {
        LOGE( "could not create thread control socket pair: %s" , strerror ( errno ) ) ;
        goto Fail;
    }
    if ( pthread_create ( & state- > thread, NULL , gps_state_thread, state ) ! = 0 ) {
        LOGE( "could not create gps thread: %s" , strerror ( errno ) ) ;
        goto Fail;
    }
    D( "gps state initialized" ) ;
    return ;
Fail:
    gps_state_done( state ) ;
}


在这个gps_state_init函数中,首先打开串口,然后建立socket通信,然后建立线程监听底层数据上报,分别对应于代码中黄低部分。

3)建立线程监听事件

mEventThread = new GpsEventThread( ) ;
mEventThread. start ( ) ;

来看看GpsEventThread的run函数。

public void run ( ) {
            if ( DEBUG) Log . d( TAG, "GpsEventThread starting" ) ;
            // Exit as soon as disable() is called instead of waiting for the GPS to stop.
            while ( mEnabled) {
                // this will wait for an event from the GPS,
                // which will be reported via reportLocation or reportStatus
                native_wait_for_event( ) ;
            }
            if ( DEBUG) Log . d( TAG, "GpsEventThread exiting" ) ;
        }
    }

run函数中还是需要调用native函 数:JNI:android_location_GpsLocationProvider_wait_for_event函数。这个函数就是在一个 while循环里面等待事件的触发(由回调函数触发),然后调用GpsLocationProvider类的数据上报函数(Location数据)。这个 在后面还会讲到。

static void android_location_GpsLocationProvider_wait_for_event( JNIEnv* env, jobject obj)
{
    pthread_mutex_lock ( & sEventMutex) ;
    while ( sPendingCallbacks = = 0) {
        pthread_cond_wait ( & sEventCond, & sEventMutex) ;
    }
. . .
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值