[android2.3]GPS启动流程及数据流向分析

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(null, this, "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的代码就分析到这里。

最后应用层通过调用

 Settings.Secure.setLocationProviderEnabled(
                        resolver,
                        LocationManager.GPS_PROVIDER,
                        desiredState);


 来enable或者Disable位置服务。

                                                     [email protected]

                                                       2011,12

你可能感兴趣的:(thread,android,jni,service,null,callback)