Chinaunix首页 | 论坛 | 博客
  • 博客访问: 226130
  • 博文数量: 29
  • 博客积分: 1477
  • 博客等级: 上尉
  • 技术积分: 451
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-06 14:48
文章分类
文章存档

2012年(1)

2011年(14)

2010年(14)

我的朋友

分类: 嵌入式

2010-12-24 14:27:28

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


阅读(4273) | 评论(5) | 转发(1) |
给主人留下些什么吧!~~

chinaunix网友2011-06-09 09:12:53

博主啊,将上述网友问到的GPS相关问题整理成一篇问答式文章,供大家学习学习把!谢谢了!

chinaunix网友2011-06-01 20:07:17

希望博主能够将所有回复的问题答案公开化,供大家一起学习。大家问的很多问题我也同样困惑过,比如WIFI定位,AGPS工作原理等等,由于网上说法不一,急切需要博主的回答来判定!谢谢!

chinaunix网友2011-04-15 14:55:50

看了你的文章。收益非浅,能讲解一下agps的工作原理吗,我很期待,或者给我一点指点也行。谢谢了。feiqiyun@126.com

chinaunix网友2011-04-07 10:21:31

楼主,您好! 可否讲解一下,从SecuritySettings里面打开Gps后,是怎样一个过程到LocationManagerService中的吗? 我现在想在我的手机上面加装一个Gps模块,现在的版本中SecuritySettings里面没有开启Gps的选项,我已经通过修改XML文件将其调出,但是打开开关后,使用GpsTest软件检测到GpsOff,也就是说界面上显示已经打开了,实际上还是没有打开。 在对Settings.apk进行反编译后的SecuritySettings.java中,已经增加了mGps相关的代码,刷回系统后并没有报错。 现在怀疑没有和LocationManagerService通信上,可否抽时间指教一二。 非常感谢!langhongjian@163.com

chinaunix网友2011-03-09 11:46:38

楼主,你好,我现在刚开始做GPS开发,发现在froyo上装上Google map,同时关掉GPS,只用网络定位,但是手机无法定位。使用eclair 装上就可以定位。我打了adb log,发现有如下log D/NetworkLocationProvider( 1579): addListener(): apps.maps D/NetworkLocationProvider( 1579): setMinTime: 0 D/NetworkLocationProvider( 1579): enableLocationTracking(): true D/LocationMasfClient( 1579): getNetworkLocation(): Returning cache location with accuracy 536.0 这些log我在froyo上打不出来,但是NetworkLocationProvider这个类在代码里我也没找到,请帮忙解答一下,我邮箱是sky19840819@163.com,非常感谢。