Android GPS学习笔记(5)—LMS初始化

来源:互联网 发布:知到演讲与口才答案 编辑:程序博客网 时间:2024/04/30 14:09
LocationManagerService(简称LMS)和Android Java Framework中的其他Service一样由SystemServer创建并运行在system_process进程中。LMS是系统Location模块的核心,我们来看一下它的初始化。

    目录:frameworks/base/services/core/java/com/android/server

1. SystemServer.java

    在SystemServer.java文件中,startOtherService函数创建LMS的代码如下,首先创建了LMS对象,并将LOCATION_SERVICE添加到ServiceManager中。

[java] view plaincopy
  1. if (!disableLocation) {  
  2.                 try {  
  3.                     Slog.i(TAG, "Location Manager");  
  4.                     location = new LocationManagerService(context);  
  5.                     ServiceManager.addService(Context.LOCATION_SERVICE, location);  
  6.                 } catch (Throwable e) {  
  7.                     reportWtf("starting Location Manager", e);  
  8.                 }  
同样是在startOtherService函数中,调用了LMS的systemRunning函数,代码如下:
[java] view plaincopy
  1. try {  
  2.          if (locationF != null) locationF.systemRunning();  
  3.      } catch (Throwable e) {  
  4.          reportWtf("Notifying Location Service running", e);  
  5.      }  

2. LMS(LocationManagerService)

LMS的systemRunning函数实现如下:

[java] view plaincopy
  1. public void systemRunning() {  
  2.         synchronized (mLock) {  
  3.             if (D) Log.d(TAG, "systemReady()");  
  4.   
  5.             // fetch package manager  
  6.             mPackageManager = mContext.getPackageManager();  
  7.   
  8.             // fetch power manager  
  9.             mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);  
  10.   
  11.             // prepare worker thread  
  12.             mLocationHandler = new LocationWorkerHandler(BackgroundThread.get().getLooper());  
  13.   
  14.             // prepare mLocationHandler's dependents  
  15.             // Android平台提供粗细两种精度的位置信息。其中,粗精度的位置信息由LocationFudger根据细精度的位置  
  16.             // 信息进行一定的数学模糊处理后得到。  
  17.             mLocationFudger = new LocationFudger(mContext, mLocationHandler);  
  18.             // 系统有一个黑白名单用于禁止使用某些特定的LP,在黑白名单中,LP由其对应的java包名指定  
  19.             mBlacklist = new LocationBlacklist(mContext, mLocationHandler);  
  20.             mBlacklist.init();  
  21.             //GeofenceManager为地理围栏对象。              
  22.             mGeofenceManager = new GeofenceManager(mContext, mBlacklist);  
  23.   
  24.             // prepare providers 关键函数  
  25.             loadProvidersLocked();  
  26.             // 根据设置中的开关情况,开启或者禁止某个LP。在此函数中,各LP实现的LocationProviderInterface接口的enable/disable函数被调用  
  27.             updateProvidersLocked();  
  28.         }  
  29.   
  30.         // listen for settings changes 监听设置数据库的变化,字段LOCATION_PROVIDERS_ALLOWED,当用户点击设置菜单按钮时,会改变数据库该字段的值  
  31.         mContext.getContentResolver().registerContentObserver(  
  32.                 Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,  
  33.                 new ContentObserver(mLocationHandler) {  
  34.                     @Override  
  35.                     public void onChange(boolean selfChange) {  
  36.                         synchronized (mLock) {  
  37.                             updateProvidersLocked();  
  38.                         }  
  39.                     }  
  40.                 }, UserHandle.USER_ALL);  
  41.         mPackageMonitor.register(mContext, mLocationHandler.getLooper(), true);  
  42.   
  43.         // 其他如监听用户切换,APK安装/卸载等事件在此不赘述  
  44.         ... ...  
  45.     }  

systemRunning中的内容较多,我们看其中的关键函数:loadProvidersLocked(),该函数用于创建及加载系统中所有的LP,其代码如下:

[java] view plaincopy
  1. private void loadProvidersLocked() {  
  2.           
  3.         //创建PassiveProvider,这个LP始终是enable的。passive译为被动,它自己不能更新位置信息,而是靠其他LP来触发  
  4.         //位置更新,PassiveProvider的位置更新是由LMS接收到其他LP的位置更新通知后,主动调用PassiveProvider的  
  5.         //updateLocation函数来完成的  
  6.         PassiveProvider passiveProvider = new PassiveProvider(this);  
  7.         //LMS将保存所有的LP  
  8.         addProviderLocked(passiveProvider);  
  9.         //PassiveProvider永远处于启用状态。mEnabledProviders用于保存那些被启用的LP          
  10.         mEnabledProviders.add(passiveProvider.getName());  
  11.         mPassiveProvider = passiveProvider;  
  12.           
  13.         //创建GPSLP实例   
  14.         GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this,  
  15.                 mLocationHandler.getLooper());  
  16.   
  17.         if (GpsLocationProvider.isSupported()) {  
  18.             mGpsStatusProvider = gpsProvider.getGpsStatusProvider();  
  19.             mNetInitiatedListener = gpsProvider.getNetInitiatedListener();  
  20.             //保存GPSLP  
  21.             addProviderLocked(gpsProvider);  
  22.             //GPSLP是真实的位置提供者,将它保存在mRealProviders中             
  23.             mRealProviders.put(LocationManager.GPS_PROVIDER, gpsProvider);  
  24.         }  
  25.         mGpsMeasurementsProvider = gpsProvider.getGpsMeasurementsProvider();  
  26.         mGpsNavigationMessageProvider = gpsProvider.getGpsNavigationMessageProvider();  
  27.   
  28.    
  29.         Resources resources = mContext.getResources();  
  30.         ArrayList<String> providerPackageNames = new ArrayList<String>();  
  31.         //config_locationProviderPackageNames存储了第三方LP的java包名。Android原生代码中该值为  
  32.         //"com.android.location.fused"。FusedLP对应的源码路径为frameworks/base/packages/FusedLocation  
  33.         String[] pkgs = resources.getStringArray(  
  34.                 com.android.internal.R.array.config_locationProviderPackageNames);  
  35.         if (D) Log.d(TAG, "certificates for location providers pulled from: " +  
  36.                 Arrays.toString(pkgs));  
  37.         if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs));  
  38.         //加载应用程序的实现的LP服务时,LMS将检查它们的签名信息以及版本信息  
  39.         ensureFallbackFusedProviderPresentLocked(providerPackageNames);  
  40.   
  41.         // 加载NetworkLP  
  42.         LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(  
  43.                 mContext,  
  44.                 LocationManager.NETWORK_PROVIDER,  
  45.                 NETWORK_LOCATION_SERVICE_ACTION,  
  46.                 com.android.internal.R.bool.config_enableNetworkLocationOverlay,  
  47.                 com.android.internal.R.string.config_networkLocationProviderPackageName,  
  48.                 com.android.internal.R.array.config_locationProviderPackageNames,  
  49.                 mLocationHandler);  
  50.         if (networkProvider != null) {  
  51.             //NetworkLP属于真实的LP  
  52.             mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);  
  53.             //应用程序实现的LP保存在mProxyProviders中  
  54.             mProxyProviders.add(networkProvider);  
  55.             addProviderLocked(networkProvider);  
  56.         } else {  
  57.             Slog.w(TAG,  "no network location provider found");  
  58.         }  
  59.   
  60.         // 加载FusedLP  
  61.         LocationProviderProxy fusedLocationProvider = LocationProviderProxy.createAndBind(  
  62.                 mContext,  
  63.                 LocationManager.FUSED_PROVIDER,  
  64.                 FUSED_LOCATION_SERVICE_ACTION,  
  65.                 com.android.internal.R.bool.config_enableFusedLocationOverlay,  
  66.                 com.android.internal.R.string.config_fusedLocationProviderPackageName,  
  67.                 com.android.internal.R.array.config_locationProviderPackageNames,  
  68.                 mLocationHandler);  
  69.         if (fusedLocationProvider != null) {  
  70.             addProviderLocked(fusedLocationProvider);  
  71.             mProxyProviders.add(fusedLocationProvider);  
  72.             //FusedLP默认处于启用的状态  
  73.             mEnabledProviders.add(fusedLocationProvider.getName());  
  74.             mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider);  
  75.         } else {  
  76.             Slog.e(TAG, "no fused location provider found",  
  77.                     new IllegalStateException("Location service needs a fused location provider"));  
  78.         }  
  79.   
  80.         // 加载Geocoder  
  81.         mGeocodeProvider = GeocoderProxy.createAndBind(mContext,  
  82.                 com.android.internal.R.bool.config_enableGeocoderOverlay,  
  83.                 com.android.internal.R.string.config_geocoderProviderPackageName,  
  84.                 com.android.internal.R.array.config_locationProviderPackageNames,  
  85.                 mLocationHandler);  
  86.         if (mGeocodeProvider == null) {  
  87.             Slog.e(TAG,  "no geocoder provider found");  
  88.         }  
  89.   
  90.         ... ...  
  91.           
  92.     }  

在LMS的初始化函数中,loadProvidersLocked用于创建和加载系统中所有的LP如下:

1. PassiveProvider:提供被动式的位置数据更新服务,其位置数据来源于其他LP

2. GpsLocationProvider:由LMS创建并加载,运行在LMS所在的进程system_process中,属于系统提供的LP服务

3. NetworkLocationProvider:该LP服务是由应用程序提供的

4. FusedLocationProvider:由FusedLocation.apk服务,属于系统提供的应用程序。其内部将使用其他的LP

5. GeocodeProvider:由第三方应用程序提供,一般和NetworkLP位于同一个应用程序中。

其中GpsLocationProvider是重点,在下一篇文章中将介绍它的初始化。我们先来看一下LMS是如何与应用进程中的LP交互的。

3. LocationProviderProxy.java

    由loadProvidersProxy.java代码可知,LMS通过LocationProviderProxy的createAndBind函数来加载应用进程中的LP。

[java] view plaincopy
  1. public static LocationProviderProxy createAndBind(  
  2.             Context context, String name, String action,  
  3.             int overlaySwitchResId, int defaultServicePackageNameResId,  
  4.             int initialPackageNamesResId, Handler handler) {  
  5.         LocationProviderProxy proxy = new LocationProviderProxy(context, name, action,  
  6.                 overlaySwitchResId, defaultServicePackageNameResId, initialPackageNamesResId,  
  7.                 handler);  
  8.         if (proxy.bind()) {  
  9.             return proxy;  
  10.         } else {  
  11.             return null;  
  12.         }  
  13.     }  
上述函数中有两个重要函数,一个是LocationProviderProxy的构造函数,另一个是bind函数。我们先来看一下其构造函数:

[java] view plaincopy
  1. private LocationProviderProxy(Context context, String name, String action,  
  2.             int overlaySwitchResId, int defaultServicePackageNameResId,  
  3.             int initialPackageNamesResId, Handler handler) {  
  4.         mContext = context;  
  5.         mName = name;  
  6.         mServiceWatcher = new ServiceWatcher(mContext, TAG + "-" + name, action, overlaySwitchResId,  
  7.                 defaultServicePackageNameResId, initialPackageNamesResId,  
  8.                 mNewServiceWork, handler);  
  9.     }  

其中ServiceWatcher是LocationProviderProxy中最重要的对象。在Android LMS架构中,应用程序实现的LP服务是通过Service提供的。ServiceWatcher是LocationProviderProxy中用来连接和监视应用程序实现的LP服务的。

再来看一下bind函数:

[java] view plaincopy
  1. private boolean bind () {  
  2.         return mServiceWatcher.start();  
  3.     }  
bind函数直接调用了ServiceWatcher的start函数,我们直接来看start函数:

[java] view plaincopy
  1. public boolean start() {  
  2.         synchronized (mLock) {  
  3.         //关键函数bindBestPackageLocked  
  4.         if (!bindBestPackageLocked(mServicePackageName)) return false;  
  5.         }  
  6.   
  7.         // 监听用户切换  
  8.         IntentFilter intentFilter = new IntentFilter();  
  9.         intentFilter.addAction(Intent.ACTION_USER_SWITCHED);  
  10.         mContext.registerReceiverAsUser(new BroadcastReceiver() {  
  11.             @Override  
  12.             public void onReceive(Context context, Intent intent) {  
  13.                 String action = intent.getAction();  
  14.                 if (Intent.ACTION_USER_SWITCHED.equals(action)) {  
  15.                     switchUser();  
  16.                 }  
  17.             }  
  18.         }, UserHandle.ALL, intentFilter, null, mHandler);  
  19.   
  20.         // 监听应用程序的安装,卸载,更新等广播事件  
  21.         if (mServicePackageName == null) {  
  22.             mPackageMonitor.register(mContext, null, UserHandle.ALL, true);  
  23.         }  
  24.   
  25.         return true;  
  26.     }  
其中的重要函数是bindBestPackageLocked,它的工作主要有以下内容:

1. 检查目标应用程序的签名

2. 根据createAndBind第三个参数查找该目标应用程序实现的Service。以NetworkLP为例,目标应用程序必须提供一个名为"com.android.location.service.v2.NetworkLocationProvider"的服务

3. 绑定到该服务上,并获取一个类型为ILocationProvider的实例。通过该实例,LocationProviderProxy可与应用程序中的LP服务交互

bindBestPackageLocked中最重要的函数是bindToPackageLocked,其代码如下:

[java] view plaincopy
  1. private void bindToPackageLocked(String packageName, int version, boolean isMultiuser) {  
  2.         unbindLocked();  
  3.         Intent intent = new Intent(mAction);  
  4.         intent.setPackage(packageName);  
  5.         mPackageName = packageName;  
  6.         mVersion = version;  
  7.         mIsMultiuser = isMultiuser;  
  8.         if (D) Log.d(mTag, "binding " + packageName + " (version " + version + ") ("  
  9.                 + (isMultiuser ? "multi" : "single") + "-user)");  
  10.         mContext.bindServiceAsUser(intent, this, Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND  
  11.                 | Context.BIND_NOT_VISIBLE, mIsMultiuser ? UserHandle.OWNER : UserHandle.CURRENT);  
  12.     }  

bindServiceAsUser函数绑定了第三方应用程序的LP服务,参数intent中传入的mAction是在ServiceWatcher的构造函数中赋值的,从LocationProviderProxy的代码中可以看出,这个action是在createAndBind函数中传入的,即在LMS中定义了此Action:

[java] view plaincopy
  1. private static final String NETWORK_LOCATION_SERVICE_ACTION =  
  2.             "com.android.location.service.v3.NetworkLocationProvider"  

绑定成功后,ServiceWatcher的onServiceConnected函数将被调用:

[java] view plaincopy
  1. public void onServiceConnected(ComponentName name, IBinder binder) {  
  2.         synchronized (mLock) {  
  3.             String packageName = name.getPackageName();  
  4.             if (packageName.equals(mPackageName)) {  
  5.                 if (D) Log.d(mTag, packageName + " connected");  
  6.                 mBinder = binder;  
  7.                 if (mHandler !=null && mNewServiceWork != null) {  
  8.                     mHandler.post(mNewServiceWork);  
  9.                 }  
  10.             } else {  
  11.                 Log.w(mTag, "unexpected onServiceConnected: " + packageName);  
  12.             }  
  13.         }  
  14.     }  
mNewServiceWork由LocationProviderProxy提供,是一个Runnable对象,其代码如下:

[java] view plaincopy
  1. private Runnable mNewServiceWork = new Runnable() {  
  2.     @Override  
  3.     public void run() {  
  4.         if (D) Log.d(TAG, "applying state to connected service");  
  5.   
  6.         boolean enabled;  
  7.         ProviderProperties properties = null;  
  8.         ProviderRequest request;  
  9.         WorkSource source;  
  10.         ILocationProvider service;  
  11.         synchronized (mLock) {  
  12.             enabled = mEnabled;  
  13.             request = mRequest;  
  14.             source = mWorksource;  
  15.             service = getService();  
  16.         }  
  17.   
  18.         if (service == nullreturn;  
  19.   
  20.         try {  
  21.             // 获取LP的属性信息,这些属性统一封装在类型为ProviderProperties的对象中  
  22.             properties = service.getProperties();  
  23.             if (properties == null) {  
  24.                 Log.e(TAG, mServiceWatcher.getBestPackageName() +  
  25.                         " has invalid locatino provider properties");  
  26.             }  
  27.   
  28.             // apply current state to new service  
  29.             if (enabled) {  
  30.                 service.enable();//启动这个LP  
  31.                 if (request != null) {//如果客户端有请求,则将该请求发送给LP  
  32.                     service.setRequest(request, source);  
  33.                 }  
  34.             }  
  35.         } catch (RemoteException e) {  
  36.             Log.w(TAG, e);  
  37.         } catch (Exception e) {  
  38.             // never let remote service crash system server  
  39.             Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);  
  40.         }  
  41.   
  42.         synchronized (mLock) {  
  43.             mProperties = properties;  
  44.         }  
  45.     }  
  46. }; 
0 0