【Android】GPS启动流程及数据流向分析(基于2.3.5)

GPS启动流程及数据流向分析:

 首先在系统init阶段,会通过ServiceManager addService添加很多的Service,这其中就包含LocationService。
代码在SystemServer.java中:

              try {
                  Slog.i(TAG, "Location Manager");
                  location =  new LocationManagerService(context);
                  ServiceManager.addService(Context.LOCATION_SERVICE, location);
             }  catch (Throwable e) {
                  reportWtf("starting Location Manager", e);
             }
 随后调用LocationManagerService的systemReady函数开启一个线程。
             final LocationManagerService locationF = location;
             try {
                      if (locationF !=  null) locationF.systemReady();
                 }  catch (Throwable e) {
                     reportWtf("making Location Service ready", e);
            }
--LocationManagerService.java
      void systemReady() {
           //  we defer starting up the service until the system is ready 
          Thread thread =  new Thread( nullthis, "LocationManagerService");
          thread.start();
     }
在 Thread的run函数中为接收消息做好了准备,并且调用了一个initialize函数:
      public  void run()
     {
          Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
          Looper.prepare();
          mLocationHandler =  new LocationWorkerHandler();
          initialize();
          Looper.loop();
     }
接着看initialize():
private  void initialize() {
           //  Create a wake lock, needs to be done before calling loadProviders() below
          PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
          mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);

           //  Load providers
          loadProviders();

           //  Register for Network (Wifi or Mobile) updates
          IntentFilter intentFilter =  new IntentFilter();
          intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
           //  Register for Package Manager updates
          intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
          intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
          intentFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
          mContext.registerReceiver(mBroadcastReceiver, intentFilter);
         IntentFilter sdFilter =  new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
          mContext.registerReceiver(mBroadcastReceiver, sdFilter);

           //  listen for settings changes
          ContentResolver resolver = mContext.getContentResolver();
          Cursor settingsCursor = resolver.query(Settings.Secure.CONTENT_URI,  null,
                  "(" + Settings.System.NAME + "=?)",
                   new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
                  null);
          mSettings =  new ContentQueryMap(settingsCursor, Settings.System.NAME,  true, mLocationHandler);
          SettingsObserver settingsObserver =  new SettingsObserver();
          mSettings.addObserver(settingsObserver);
     }
其中有两个重要的地方:
 1) loadProviders(),会new一个GpsLocationProvider,并将本GpsLocationProvider添加一个ArrayList<LocationProviderInterface>的链 表中。
 2) new 一个 SettingsObserver对象,该对象应该是负责在Settings中有数据变化时通知本地程序进行相应处理的功能。其中 SettingsObserver类中实现 了Observer接口,该接口中的update函数应该就是一个回调函数,当Settings中有数据变化时会回调进这个函数:
private  final  class SettingsObserver  implements Observer {
           public  void update(Observable o, Object arg) {
               synchronized (mLock) {
                   updateProvidersLocked();
              }
          }
     }

  private  void updateProvidersLocked() {
           boolean changesMade =  false;
           for ( int i = mProviders.size() - 1; i >= 0; i--) {
               LocationProviderInterface p = mProviders.get(i);
                boolean isEnabled = p.isEnabled();
               String name = p.getName();
                boolean shouldBeEnabled = isAllowedBySettingsLocked(name);
               If (isEnabled && !shouldBeEnabled) {
                    updateProviderListenersLocked(name,  false);
                    changesMade =  true;
               }  else  if (!isEnabled && shouldBeEnabled) {
                    updateProviderListenersLocked(name,  true);
                    changesMade =  true;
               }
          }
           if (changesMade) {
               mContext.sendBroadcast( new Intent(LocationManager.PROVIDERS_CHANGED_ACTION));
          }
     }

  private  void updateProviderListenersLocked(String provider,  boolean enabled) {
         int listeners = 0;

         LocationProviderInterface p = mProvidersByName.get(provider);
          if (p ==  null) {
               return;
         }

         ArrayList<Receiver> deadReceivers =  null;
        
         ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
          if (records !=  null) {
               final  int N = records.size();
               for ( int i=0; i<N; i++) {
                  UpdateRecord record = records.get(i);
                   //  Sends a notification message to the receiver
                   if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
                       if (deadReceivers ==  null) {
                           deadReceivers =  new ArrayList<Receiver>();
                      }
                      deadReceivers.add(record.mReceiver);
                  }
                  listeners++;
             }
         }

          if (deadReceivers !=  null) {
               for ( int i=deadReceivers.size()-1; i>=0; i--) {
                  removeUpdatesLocked(deadReceivers.get(i));
              }
         }
        
          if (enabled) {
              p.enable();
               if (listeners > 0) {
                   p.setMinTime(getMinTimeLocked(provider), mTmpWorkSource);
                   p.enableLocationTracking( true);
              }
         }  else {
              p.enableLocationTracking( false);
              p.disable();
         }
     }
可知是在 updateProviderListenersLocked函数中,通过 LocationProviderInterface p调用enable或者disable来开关位置服务。这里会调用到 LocationProviderInterface的子类GpsLocationProvider中的enable或者disable中:
 
 GpsLocationProvider.java
  public  void enable() {
           synchronized (mHandler) {
             sendMessage(ENABLE, 1,  null);
          }
       }
handlenable就是ENABLE的消息处理函数:
  private  void handleEnable() {
           if (DEBUG) Log.d(TAG, "handleEnable");
           if (mEnabled)  return;
          mEnabled = native_init();
        
          Intent intent =  new Intent(LocationManager.GPS_SETTING_ENABLED_CHANGE_ACTION);
          intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mEnabled);
          mContext.sendBroadcast(intent);

           if (mEnabled) {
              mSupportsXtra = native_supports_xtra();
               if (mSuplServerHost !=  null) {
                   native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
              }
               if (mC2KServerHost !=  null) {
                   native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
              }
          }  else {
              Log.w(TAG, "Failed to enable location provider");
          }
     }
可见这里就开始与native层通信了。
 native_init对应jni中的android_location_GpsLocationProvider_init函数,在该函数中调用了
 sGpsInterface->init(&sGpsCallbacks),
 而 sGpsCallbacks定义如下:
GpsCallbacks sGpsCallbacks = {
      sizeof(GpsCallbacks),
      location_callback,
      status_callback,
      sv_status_callback,
      nmea_callback,
      set_capabilities_callback,
      acquire_wakelock_callback,
      release_wakelock_callback,
      create_thread_callback,
      request_utc_time_callback,
 };
 这是将jni的一些函数作为参数传递到native c 空间中去,这样在native c中如果有可用数据将通过回调的方式调用到jni中的函数。简单的看一下 location_callback的定义:
static  void location_callback(GpsLocation* location)
 {
      JNIEnv* env = AndroidRuntime::getJNIEnv();
      env->CallVoidMethod(mCallbacksObj, method_reportLocation, location->flags,
             (jdouble)location->latitude, (jdouble)location->longitude,
             (jdouble)location->altitude,
             (jfloat)location->speed, (jfloat)location->bearing,
             (jfloat)location->accuracy, (jlong)location->timestamp);
      checkAndClearExceptionFromCallback(env, __FUNCTION__);
 }

其中有定义:
 static jmethodID method_reportLocation;并且:
 method_reportLocation = env->GetMethodID(clazz, "reportLocation","(IDDDFFFJ)V"); 
 可见jni中的callback函数其实又回调掉了java空间(Framework)中的  reportLocation函数,这便是整个GPS框架的数据流向结构了。所有的数据都是通过回调的方式通知上层:
 nativeC通过回调通知JNI,JNI通过回调通知Framework。这应该是gps整个框架最重要的部分吧,理解了数据流向,其他的应该都简单了。
 我们的native c中并没有实现 native_set_agps_server的功能,所以使用agps的数据服务器不在上层指定,而是在c文件中直接指定的。 native_set_agps_server只是一个空函数。

 上面介绍了 sGpsInterface->init(&sGpsCallbacks)中sGpsCallbacks的作用,但是init函数调用还未进行剖析:
  sGpsInterface定义如下:
 static const GpsInterface* sGpsInterface = NULL;
 它是在android_location_GpsLocationProvider_class_init_native函数初始化的,该函数在GpsLocationProvider中通过static方式预加载:

 err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t  const**)&module);
      if (err == 0) {
         hw_device_t* device;
  // 通过open调用,在native层分配了一个 gps_device_t的空间,并传递回来。
         err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
          if (err == 0) {
   // 这个强制转换是因为 gps_device_t中第一个item是一个 hw_device_t。
  
// 并且在native中确实是分配的gps_device_t空间
            gps_device_t* gps_device = (gps_device_t *)device;
            sGpsInterface = gps_device->get_gps_interface(gps_device);
         }
     }

 

可见这个 sGpsInterface是从hwModule中获取的。来看看get_gps_interface函数:
  static  int open_gps( const struct hw_module_t* module,  char  const* name,        
      struct hw_device_t** device) 
 {    
      struct gps_device_t *dev = malloc(sizeof(struct gps_device_t));    
       if (dev == NULL) { 
          LOGE("gps device can not malloc memery!"); 
           return -ENOMEM; 
     } 
    
     memset(dev, 0, sizeof(*dev));    
     dev->common.tag = HARDWARE_DEVICE_TAG;    
     dev->common.version = 0;    
     dev->common.module = (struct hw_module_t*)module;  
     dev->common.close = close_gps; 
  // 注意一个有参 一个无参   
     dev->get_gps_interface = gps_get_hardware_interface;    
     *device = (struct hw_device_t *)dev;    
    
      return 0; 
 }

  const GpsInterface *gps_get_hardware_interface() 
 { 
       return &ubloxGpsInterface; 
 }

  /* gps interface struct */ 
  static  const GpsInterface  ubloxGpsInterface = 
 { 
      .size = sizeof(GpsInterface), 
      .init = ublox_gps_init, 
      .start = ublox_gps_start, 
      .stop = ublox_gps_stop, 
      .cleanup = ublox_gps_cleanup, 
      .inject_location = ublox_gps_inject_location, 
      .delete_aiding_data = ublox_gps_delete_aiding_data, 
      .set_position_mode = ublox_gps_set_position_mode, 
      .get_extension = ublox_gps_get_extension, 
 };

  static  int ublox_gps_init(GpsCallbacks* callbacks) 
 { 
      UbloxGpsData *gps_data = &ublox_gps_data; 

       // ublox gps support MS-based A-GPS, fix in the gps terminal 
      callbacks->set_capabilities_cb(GPS_CAPABILITY_SCHEDULING | GPS_CAPABILITY_MSB);


      pthread_mutex_init(&gps_data->deferred_action_mutex, NULL); 
      pthread_cond_init(&gps_data->deferred_action_cond, NULL); 
      agps_state->used_proxy = 0; 

      gps_data->gps_callbacks = *callbacks; 
      gps_data->thread_start = 0; 

      LOGD("gps finishes initialization"); 
   
       return 0; 
 }
 所以 sGpsInterface实际上指向了native层的 ubloxGpsInterface。调用其init函数,将JNI空间的回调函数传递到了native空间。
应用层通过调用
 Settings.Secure.setLocationProviderEnabled(
                        resolver,
                        LocationManager.GPS_PROVIDER,
                        desiredState);
来enable或者Disable位置服务。
url: http://greatverve.cnblogs.com/archive/2012/01/31/android-gps.html

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ArcGIS流向分析是一种地理信息系统(GIS)中的空间分析方法,旨在揭示特定地点或区域内物质或信息的流动方向和路径。该分析方法通常在城市规划、交通规划、水资源管理等领域中广泛应用。 ArcGIS流向分析的基本原理是通过建立网络模型,根据各种条件和约束,推测物质或信息可能的传输路径。该分析方法可以基于现有的道路、河流、通道等地理要素进行分析,也可以通过构建新的网络模型来模拟特定情景下的流向。 在ArcGIS中进行流向分析,可以使用各种工具和功能。其中最常用的是网络分析工具集中的路径分析工具。用户可以选择起点和终点,然后通过设置各种条件和参数,运行路径分析工具,系统将根据网络模型的设定,计算出最短路径或最优路径,并将结果显示在地图上。 ArcGIS流向分析可以帮助用户更好地了解物质或信息的流动规律,从而为城市规划、交通规划等决策提供科学依据。例如,通过流向分析可以确定交通拥堵的原因和解决方案,优化道路布局,提高交通效率。同时,该分析方法还可以用于水资源管理,预测水流的路径和速度,帮助决策者制定合理的水利政策。 总之,ArcGIS流向分析是一种实用的空间分析方法,通过建立网络模型和运用路径分析工具,可以揭示物质或信息在地理空间中的传输规律,为各种决策提供科学依据。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值