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

来源:互联网 发布:武林外传排名知乎 编辑:程序博客网 时间:2024/04/30 03:37

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

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

[java] view plaincopy
  1. try {  
  2.    Slog.i(TAG, "Location Manager");  
  3.    location = new LocationManagerService(context);  
  4.    ServiceManager.addService(Context.LOCATION_SERVICE, location);  
  5. catch (Throwable e) {  
  6.    reportWtf("starting Location Manager", e);  
  7. }   


 随后调用LocationManagerService的systemReady函数开启一个线程。
  

[java] view plaincopy
  1. final LocationManagerService locationF = location;  
  2. try {  
  3.      if (locationF != null) locationF.systemReady();  
  4. catch (Throwable e) {  
  5.      reportWtf("making Location Service ready", e);  
  6. }  



 --LocationManagerService.java

[java] view plaincopy
  1. void systemReady() {  
  2.          // we defer starting up the service until the system is ready   
  3.          Thread thread = new Thread(nullthis"LocationManagerService");  
  4.          thread.start();  
  5.     }  


 在 Thread的run函数中为接收消息做好了准备,并且调用了一个initialize函数:

[java] view plaincopy
  1. public void run()  
  2. {  
  3.      Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);  
  4.      Looper.prepare();  
  5.      mLocationHandler = new LocationWorkerHandler();  
  6.      initialize();  
  7.      Looper.loop();  
  8. }  


 接着看initialize():

[java] view plaincopy
  1. private void initialize() {  
  2.          // Create a wake lock, needs to be done before calling loadProviders() below  
  3.          PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);  
  4.          mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);  
  5.   
  6.          // Load providers  
  7.          loadProviders();  
  8.   
  9.          // Register for Network (Wifi or Mobile) updates  
  10.          IntentFilter intentFilter = new IntentFilter();  
  11.          intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);  
  12.          // Register for Package Manager updates  
  13.          intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);  
  14.          intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);  
  15.          intentFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);  
  16.          mContext.registerReceiver(mBroadcastReceiver, intentFilter);  
  17.         IntentFilter sdFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);  
  18.          mContext.registerReceiver(mBroadcastReceiver, sdFilter);  
  19.   
  20.          // listen for settings changes  
  21.          ContentResolver resolver = mContext.getContentResolver();  
  22.          Cursor settingsCursor = resolver.query(Settings.Secure.CONTENT_URI, null,  
  23.                  "(" + Settings.System.NAME + "=?)",  
  24.                  new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},  
  25.                 null);  
  26.          mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mLocationHandler);  
  27.          SettingsObserver settingsObserver = new SettingsObserver();  
  28.          mSettings.addObserver(settingsObserver);  
  29.     }  


 其中有两个重要的地方:
 1) loadProviders(),会new一个GpsLocationProvider,并将本GpsLocationProvider添加一个ArrayList<LocationProviderInterface>的链 表中。
 2) new 一个 SettingsObserver对象,该对象应该是负责在Settings中有数据变化时通知本地程序进行相应处理的功能。其中 SettingsObserver类中实现 了Observer接口,该接口中的update函数应该就是一个回调函数,当Settings中有数据变化时会回调进这个函数:
 

[java] view plaincopy
  1. private final class SettingsObserver implements Observer {  
  2.          public void update(Observable o, Object arg) {  
  3.              synchronized (mLock) {  
  4.                   updateProvidersLocked();  
  5.              }  
  6.          }  
  7.     }  
  8.   
  9. private void updateProvidersLocked() {  
  10.          boolean changesMade = false;  
  11.          for (int i = mProviders.size() - 1; i >= 0; i--) {  
  12.               LocationProviderInterface p = mProviders.get(i);  
  13.               boolean isEnabled = p.isEnabled();  
  14.               String name = p.getName();  
  15.               boolean shouldBeEnabled = isAllowedBySettingsLocked(name);  
  16.               If (isEnabled && !shouldBeEnabled) {  
  17.                    updateProviderListenersLocked(name, false);  
  18.                    changesMade = true;  
  19.               } else if (!isEnabled && shouldBeEnabled) {  
  20.                    updateProviderListenersLocked(name, true);  
  21.                    changesMade = true;  
  22.               }  
  23.          }  
  24.          if (changesMade) {  
  25.               mContext.sendBroadcast(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION));  
  26.          }  
  27.     }  
  28.   
  29. private void updateProviderListenersLocked(String provider, boolean enabled) {  
  30.        int listeners = 0;  
  31.   
  32.         LocationProviderInterface p = mProvidersByName.get(provider);  
  33.         if (p == null) {  
  34.              return;  
  35.         }  
  36.   
  37.         ArrayList<Receiver> deadReceivers = null;  
  38.          
  39.         ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);  
  40.         if (records != null) {  
  41.              final int N = records.size();  
  42.              for (int i=0; i<N; i++) {  
  43.                  UpdateRecord record = records.get(i);  
  44.                  // Sends a notification message to the receiver  
  45.                  if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {  
  46.                      if (deadReceivers == null) {  
  47.                           deadReceivers = new ArrayList<Receiver>();  
  48.                      }  
  49.                      deadReceivers.add(record.mReceiver);  
  50.                  }  
  51.                  listeners++;  
  52.             }  
  53.         }  
  54.   
  55.         if (deadReceivers != null) {  
  56.              for (int i=deadReceivers.size()-1; i>=0; i--) {  
  57.                  removeUpdatesLocked(deadReceivers.get(i));  
  58.              }  
  59.         }  
  60.          
  61.         if (enabled) {  
  62.              p.enable();  
  63.              if (listeners > 0) {  
  64.                   p.setMinTime(getMinTimeLocked(provider), mTmpWorkSource);  
  65.                   p.enableLocationTracking(true);  
  66.              }  
  67.         } else {  
  68.              p.enableLocationTracking(false);  
  69.              p.disable();  
  70.         }  
  71.     }  


 可知是在 updateProviderListenersLocked函数中,通过 LocationProviderInterface p调用enable或者disable来开关位置服务。这里会调用到 LocationProviderInterface的子类GpsLocationProvider中的enable或者disable中:
 
--GpsLocationProvider.java

[java] view plaincopy
  1. public void enable() {  
  2.          synchronized (mHandler) {  
  3.             sendMessage(ENABLE, 1null);  
  4.          }  
  5.       }  


 handlenable就是ENABLE的消息处理函数:

[html] view plaincopy
  1. private void handleEnable() {  
  2.          if (DEBUG) Log.d(TAG, "handleEnable");  
  3.          if (mEnabled) return;  
  4.          mEnabled = native_init();  
  5.          
  6.          Intent intent = new Intent(LocationManager.GPS_SETTING_ENABLED_CHANGE_ACTION);  
  7.          intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mEnabled);  
  8.          mContext.sendBroadcast(intent);  
  9.   
  10.          if (mEnabled) {  
  11.              mSupportsXtra = native_supports_xtra();  
  12.              if (mSuplServerHost != null) {  
  13.                   native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);  
  14.              }  
  15.              if (mC2KServerHost != null) {  
  16.                   native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);  
  17.              }  
  18.          } else {  
  19.              Log.w(TAG, "Failed to enable location provider");  
  20.          }  
  21.     }  


 可见这里就开始与native层通信了。
 native_init对应jni中的android_location_GpsLocationProvider_init函数,在该函数中调用了
 sGpsInterface->init(&sGpsCallbacks),
 而 sGpsCallbacks定义如下:
 

[cpp] view plaincopy
  1. GpsCallbacks sGpsCallbacks = {  
  2.       sizeof(GpsCallbacks),  
  3.       location_callback,  
  4.       status_callback,  
  5.       sv_status_callback,  
  6.       nmea_callback,  
  7.       set_capabilities_callback,  
  8.       acquire_wakelock_callback,  
  9.       release_wakelock_callback,  
  10.       create_thread_callback,  
  11.       request_utc_time_callback,  
  12.  };  


 这是将jni的一些函数作为参数传递到native c 空间中去,这样在native c中如果有可用数据将通过回调的方式调用到jni中的函数。简单的看一下 location_callback的定义:

[java] view plaincopy
  1. static void location_callback(GpsLocation* location)  
  2. {  
  3.      JNIEnv* env = AndroidRuntime::getJNIEnv();  
  4.      env->CallVoidMethod(mCallbacksObj, method_reportLocation, location->flags,  
  5.             (jdouble)location->latitude, (jdouble)location->longitude,  
  6.             (jdouble)location->altitude,  
  7.             (jfloat)location->speed, (jfloat)location->bearing,  
  8.             (jfloat)location->accuracy, (jlong)location->timestamp);  
  9.      checkAndClearExceptionFromCallback(env, __FUNCTION__);  
  10. }  


 其中有定义:
 static jmethodID method_reportLocation;并且:
 method_reportLocation = env->GetMethodID(clazz, "reportLocation","(IDDDFFFJ)V"); 
 可见jni中的callback函数其实又回调掉了java空间(Framework)中的  reportLocation函数,这便是整个GPS框架的数据流向结构了。所有的数据都是通过回调的方式通知上层:
 nativeC通过回调通知JNI,JNI通过回调通知Framework。这应该是gps整个框架最重要的部分吧,理解了数据流向,其他的应该都简单了。

因为代码授权方面的原因,关于native的代码就分析到这里。

最后应用层通过调用

[cpp] view plaincopy
  1. Settings.Secure.setLocationProviderEnabled(  
  2.                        resolver,  
  3.                        LocationManager.GPS_PROVIDER,  
  4.                        desiredState);  


 来enable或者Disable位置服务。

                                                     kuangkondy@gmail.com

                                                       2011,12


原文地址http://blog.csdn.net/kondykuang/article/details/7315482 

,感谢作者分享,让我这个android菜鸟收货不小