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位置服务。
2011,12