(红字表示2.3的变化) Framework:
1.frameworks/base/location/java/android/location
这里主要是用来被App调用的,API包是android.location。
2.frameworks/base/location/java/com/android/internal/location
这个目录是Framework对Location服务的内部实现。 3.framework/services/java/com/android/server
这个目录只有一个文件 |-- LocationManagerService.java
是Location服务对内部实现的一种封装。 JNI: 2.2
frameworks/base/core/jni/android_location_GpsLocationProvider.cpp 2.3 /framework/base/services/jni/com_android_server_location_GpsLocationProvider.cpp
JNI层只有一个文件,起到承上启下的作用。上层承接Framework,下层调用HAL层具体硬件抽象实现。 HAL:Hardware Abstract Layer 硬件抽象层
hardware/libhardware_legacy/gps
hardware/libhardware_legacy/include/hardware_legacy/gps.h
HAL层相当于一个linux应用程序接口,通过open,close等操作,操作硬件设备。Android的源代码只实现了模拟器的gps接口,具体在文件gps_qemu.c中。在2.2版本中提供了对QCOM公司的gps的实现,在以下目录:
/hardware/qcom 下面介绍几个重要的数据结构:
1. GpsInterface接口是gps模块中最重要的数据结构,它是底层驱动实现的接口,如果要porting到自己的板子上,就需要实现这些接口。该接口的定义在gps.h中,模拟器实现在gps_qemu.c中。 view plain copy to clipboard print ?
  1. /**RepresentsthestandardGPSinterface.*/
  2. typedefstruct{
  3. /**settosizeof(GpsInterface)*/
  4. size_tsize;
  5. /**
  6. *Openstheinterfaceandprovidesthecallbackroutines
  7. *totheimplemenationofthisinterface.
  8. */
  9. int(*init)(GpsCallbacks*callbacks);
  10. /**Startsnavigating.*/
  11. int(*start)(void);
  12. /**Stopsnavigating.*/
  13. int(*stop)(void);
  14. /**Closestheinterface.*/
  15. void(*cleanup)(void);
  16. /**Injectsthecurrenttime.*/
  17. int(*inject_time)(GpsUtcTimetime,int64_ttimeReference,
  18. intuncertainty);
  19. /**Injectscurrentlocationfromanotherlocationprovider
  20. *(typicallycellID).
  21. *latitudeandlongitudearemeasuredindegrees
  22. *expectedaccuracyismeasuredinmeters
  23. */
  24. int(*inject_location)(doublelatitude,doublelongitude,floataccuracy);
  25. /**
  26. *Specifiesthatthenextcalltostartwillnotusethe
  27. *informationdefinedintheflags.GPS_DELETE_ALLispassedfor
  28. *acoldstart.
  29. */
  30. void(*delete_aiding_data)(GpsAidingDataflags);
  31. /**
  32. *min_intervalrepresentsthetimebetweenfixesinmilliseconds.
  33. *preferred_accuracyrepresentstherequestedfixaccuracyinmeters.
  34. *preferred_timerepresentstherequestedtimetofirstfixinmilliseconds.
  35. */
  36. int(*set_position_mode)(GpsPositionModemode,GpsPositionRecurrencerecurrence,
  37. uint32_tmin_interval,uint32_tpreferred_accuracy,uint32_tpreferred_time);
  38. /**Getapointertoextensioninformation.*/
  39. constvoid*(*get_extension)(constchar*name);
  40. }GpsInterface;
[cpp] view plain copy print ?
  1. /**RepresentsthestandardGPSinterface.*/
  2. typedefstruct{
  3. /**settosizeof(GpsInterface)*/
  4. size_tsize;
  5. /**
  6. *Openstheinterfaceandprovidesthecallbackroutines
  7. *totheimplemenationofthisinterface.
  8. */
  9. int(*init)(GpsCallbacks*callbacks);
  10. /**Startsnavigating.*/
  11. int(*start)(void);
  12. /**Stopsnavigating.*/
  13. int(*stop)(void);
  14. /**Closestheinterface.*/
  15. void(*cleanup)(void);
  16. /**Injectsthecurrenttime.*/
  17. int(*inject_time)(GpsUtcTimetime,int64_ttimeReference,
  18. intuncertainty);
  19. /**Injectscurrentlocationfromanotherlocationprovider
  20. *(typicallycellID).
  21. *latitudeandlongitudearemeasuredindegrees
  22. *expectedaccuracyismeasuredinmeters
  23. */
  24. int(*inject_location)(doublelatitude,doublelongitude,floataccuracy);
  25. /**
  26. *Specifiesthatthenextcalltostartwillnotusethe
  27. *informationdefinedintheflags.GPS_DELETE_ALLispassedfor
  28. *acoldstart.
  29. */
  30. void(*delete_aiding_data)(GpsAidingDataflags);
  31. /**
  32. *min_intervalrepresentsthetimebetweenfixesinmilliseconds.
  33. *preferred_accuracyrepresentstherequestedfixaccuracyinmeters.
  34. *preferred_timerepresentstherequestedtimetofirstfixinmilliseconds.
  35. */
  36. int(*set_position_mode)(GpsPositionModemode,GpsPositionRecurrencerecurrence,
  37. uint32_tmin_interval,uint32_tpreferred_accuracy,uint32_tpreferred_time);
  38. /**Getapointertoextensioninformation.*/
  39. constvoid*(*get_extension)(constchar*name);
  40. }GpsInterface;

2.GpsCallbacks回调函数

这个是回调函数结构体,定义也在gps.h中。它们的实现是在com_android_server_android_location_GpsLocationProvider.cpp中,google已经实现了,我们不需要做任何动作。

2.2

view plain copy to clipboard print ?
  1. /**GPScallbackstructure.*/
  2. typedefstruct{
  3. /**settosizeof(GpsCallbacks)*/
  4. size_tsize;
  5. gps_location_callbacklocation_cb;
  6. gps_status_callbackstatus_cb;
  7. gps_sv_status_callbacksv_status_cb;
  8. gps_nmea_callbacknmea_cb;
  9. }GpsCallbacks;
[c-sharp] view plain copy print ?
  1. /**GPScallbackstructure.*/
  2. typedefstruct{
  3. /**settosizeof(GpsCallbacks)*/
  4. size_tsize;
  5. gps_location_callbacklocation_cb;
  6. gps_status_callbackstatus_cb;
  7. gps_sv_status_callbacksv_status_cb;
  8. gps_nmea_callbacknmea_cb;
  9. }GpsCallbacks;

2.3 中 多加入了 以下几个回调函数

view plain copy to clipboard print ?
  1. gps_set_capabilitiesset_capabilities_cb;
  2. gps_acquire_wakelockacquire_wakelock_cb;
  3. gps_release_wakelockrelease_wakelock_cb;
  4. gps_create_threadcreate_thread_cb;
[cpp] view plain copy print ?
  1. gps_set_capabilitiesset_capabilities_cb;
  2. gps_acquire_wakelockacquire_wakelock_cb;
  3. gps_release_wakelockrelease_wakelock_cb;
  4. gps_create_threadcreate_thread_cb;

3. GpsLocation

表示Locatin数据信息,底层驱动获得Location的raw信息,通常是nmea码,然后通过解析就得到了location信息。

其中Android2.3比android2.2多加入了 size 属性 以获取其大小。

view plain copy to clipboard print ?
  1. /**Representsalocation.*/
  2. typedefstruct{
  3. /**settosizeof(GpsLocation)*/
  4. size_tsize;
  5. /**ContainsGpsLocationFlagsbits.*/
  6. uint16_tflags;
  7. /**Representslatitudeindegrees.*/
  8. doublelatitude;
  9. /**Representslongitudeindegrees.*/
  10. doublelongitude;
  11. /**RepresentsaltitudeinmetersabovetheWGS84reference
  12. *ellipsoid.*/
  13. doublealtitude;
  14. /**Representsspeedinmeterspersecond.*/
  15. floatspeed;
  16. /**Representsheadingindegrees.*/
  17. floatbearing;
  18. /**Representsexpectedaccuracyinmeters.*/
  19. floataccuracy;
  20. /**Timestampforthelocationfix.*/
  21. GpsUtcTimetimestamp;
  22. }GpsLocation;
[cpp] view plain copy print ?
  1. /**Representsalocation.*/
  2. typedefstruct{
  3. /**settosizeof(GpsLocation)*/
  4. size_tsize;
  5. /**ContainsGpsLocationFlagsbits.*/
  6. uint16_tflags;
  7. /**Representslatitudeindegrees.*/
  8. doublelatitude;
  9. /**Representslongitudeindegrees.*/
  10. doublelongitude;
  11. /**RepresentsaltitudeinmetersabovetheWGS84reference
  12. *ellipsoid.*/
  13. doublealtitude;
  14. /**Representsspeedinmeterspersecond.*/
  15. floatspeed;
  16. /**Representsheadingindegrees.*/
  17. floatbearing;
  18. /**Representsexpectedaccuracyinmeters.*/
  19. floataccuracy;
  20. /**Timestampforthelocationfix.*/
  21. GpsUtcTimetimestamp;
  22. }GpsLocation;

JNI层文件 2.2 frameworks/base/core/jni/android_location_GpsLocationProvider.cpp
2.3 /framework/base/services/jni/com_android_server_location_GpsLocationProvider.cpp 下面来看看gps的定位服务(LocationManager)的启动过程 LocationManager 这项服务是在SystemServer.java 中启动的,也就是系统启动之后,这个服务就已经启动了

SystemServer.javainit2函数中启动了一个线程来注册Android的诸多服务,如:Bluetooth ServiceNetworkManagement ServiceNotification Manager等,当然也包括Location Service

systemServer.java [framework/base/services/java/com/android/server]

  1. public static final void init2() {

  2. Slog.i(TAG, "Entered the Android system server!");

  3. Thread thr = new ServerThread();

  4. thr.setName("android.server.ServerThread");

  5. thr.start();

  6. }

ServerThread线程的run函数中LocationManager服务的代码段如下:

  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. Slog.e(TAG, "Failure starting Location Manager", e);
  7. }

run函数的后半部分,是服务对系统的反馈,就是systemReady()函数。 LocationManager服务的反馈函数如下:

  1. final LocationManagerService locationF = location;

其中的locationF LocationManagerServicefinal类型,就是一旦赋值,不能更改。

  1. if (locationF != null) locationF.systemReady();

下面我们来看看2.3的 LocationManagerService 构造函数。

  1. /**
  2. * @param context the context that the LocationManagerService runs in
  3. */
  4. public LocationManagerService(Context context) {
  5. super();
  6. mContext = context;
  7. Resources resources = context.getResources();
  8. mNetworkLocationProviderPackageName = resources.getString(
  9. com.android.internal.R.string.config_networkLocationProvider);
  10. mGeocodeProviderPackageName = resources.getString(
  11. com.android.internal.R.string.config_geocodeProvider);
  12. mPackageMonitor.register(context, true);

  13. if (LOCAL_LOGV) {
  14. Slog.v(TAG, "Constructed LocationManager Service");
  15. }
  16. }

以下为2.2

  1. public LocationManagerService(Context context) {
  2. super();
  3. mContext = context;
  4. if (LOCAL_LOGV) {
  5. Slog.v(TAG, "Constructed LocationManager Service");
  6. }
  7. }

然后我们再看SystemReady()

  1. void systemReady() {
  2. // we defer starting up the service until the system is ready

  3. Thread thread = new Thread(null, this, "LocationManagerService");
  4. thread.start();
  5. }

在这个函数当中,我们创建了一个新线程。然后start之。

因此我们的视线也随之跟随到run函数里面。

  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. }

在run函数中,又调用了initialize 函数

  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. // Load providers

  6. loadProviders();

  7. // Register for Network (Wifi or Mobile) updates

  8. IntentFilter intentFilter = new IntentFilter();
  9. intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
  10. // Register for Package Manager updates

  11. intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
  12. intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
  13. intentFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
  14. mContext.registerReceiver(mBroadcastReceiver, intentFilter);
  15. IntentFilter sdFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
  16. mContext.registerReceiver(mBroadcastReceiver, sdFilter);

  17. // listen for settings changes

  18. ContentResolver resolver = mContext.getContentResolver();
  19. Cursor settingsCursor = resolver.query(Settings.Secure.CONTENT_URI, null,
  20. "(" + Settings.System.NAME + "=?)",
  21. new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
  22. null);
  23. mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mLocationHandler);
  24. SettingsObserver settingsObserver = new SettingsObserver();
  25. mSettings.addObserver(settingsObserver);
  26. }

初始化函数中,最重要的便是 loadProviders()函数。

  1. private void loadProviders() {
  2. synchronized (mLock) {
  3. if (sProvidersLoaded) {
  4. return;
  5. }

  6. // Load providers

  7. loadProvidersLocked();
  8. sProvidersLoaded = true;
  9. }
  10. }

loadProvidersLocked函数

  1. private void loadProvidersLocked() {
  2. try {
  3. _loadProvidersLocked();
  4. } catch (Exception e) {
  5. Slog.e(TAG, "Exception loading providers:", e);
  6. }
  7. }

_loadProvidersLocked函数

  1. private void _loadProvidersLocked() {
  2. // Attempt to load "real" providers first

  3. if (GpsLocationProvider.isSupported()) {
  4. // Create a gps location provider

  5. GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);
  6. mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
  7. mNetInitiatedListener = gpsProvider.getNetInitiatedListener();
  8. addProvider(gpsProvider);
  9. mGpsLocationProvider = gpsProvider;
  10. }
  11. ...
  12. ...
  13. updateProvidersLocked();
  14. }

首先,我们看GpsLocationProvider.isSupported 这个函数, 这个函数很重要,我们跟进这个函数可以看到, 因为在这个语句中得到了HAL层的GPS接口GpsInterface。就是通过调用GpsLocationProviderisSupported()函数才调用到gps.cpp[hardware/libhardware_legacy/gps]中的gps_get_interface()。这个isSupported函数才是第一个吃螃蟹的人。(而不是JNI层的init函数,这个下面会提到)。

  1. public static boolean isSupported() {
  2. return native_is_supported();
  3. }

函数中只有一句话, 这调用了native方法,既Jni层定义的方法。native_is_supported对应在

framework/base/services/jni/com_android_server_location_GpsLocationProvider.cpp文件中的android_location_GpsLocationProvider_is_supported方法。

  1. static jboolean android_location_GpsLocationProvider_is_supported(JNIEnv* env, jclass clazz) {
  2. return (sGpsInterface != NULL || get_gps_interface() != NULL);
  3. }

这里的get_gps_interface指的是本文件中

  1. static const GpsInterface* get_gps_interface() {
  2. int err;
  3. hw_module_t* module;
  4. const GpsInterface* interface = NULL;

  5. err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
  6. if (err == 0) {
  7. hw_device_t* device;
  8. err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
  9. if (err == 0) {
  10. gps_device_t* gps_device = (gps_device_t *)device;
  11. interface = gps_device->get_gps_interface(gps_device);
  12. }
  13. }

  14. return interface;
  15. }

而在该get_gps_interface中,去打开模组,之后打开设备,然后通过设备区调用HAL层中的get_gps_interface(gps_device)。

在gps.c(hardware/qcom/gps/loc_api/libloc_api)文件中实现的gps__get_gps_interface调用了loc_eng.cpp里面的 get_gps_interface 接口。

  1. extern "C" const GpsInterface* get_gps_interface()
  2. {
  3. return &sLocEngInterface;
  4. }
  1. static const GpsInterface sLocEngInterface =
  2. {
  3. sizeof(GpsInterface),
  4. loc_eng_init,
  5. loc_eng_start,
  6. loc_eng_stop,
  7. loc_eng_cleanup,
  8. loc_eng_inject_time,
  9. loc_eng_inject_location,
  10. loc_eng_delete_aiding_data,
  11. loc_eng_set_position_mode,
  12. loc_eng_get_extension,
  13. };

到这里为止, 一句简单的isSupported()执行的内容终于告一段落了。 我们获取到了GPS 的接口。在上面的LocationManagerService.java中, 如果找到gps硬件,并获取了接口则我们据悉执行isSupported()的下一句。

  1. GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);

注意GpsLocationProvider构造函数里面的两个参数:mContext, this。下面来看看GpsLocationProvider的构造函数的前面几句:

  1. public GpsLocationProvider(Context context, ILocationManager locationManager) {
  2. mContext = context;
  3. mLocationManager = locationManager;
  4. mNIHandler = new GpsNetInitiatedHandler(context, this);

  5. ...

  6. }
GpsLocationProvider类里面的成员变量mLocationManager是构造函数的第二个参数,就是说是LocationManagerService对象。这一点在这里先明确。

接着看_loadProvidersLocked函数。

  1. private void _loadProvidersLocked() {
  2. // Attempt to load "real" providers first

  3. if (GpsLocationProvider.isSupported()) {
  4. // Create a gps location provider

  5. GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);
  6. mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
  7. mNetInitiatedListener = gpsProvider.getNetInitiatedListener();
  8. addProvider(gpsProvider);
  9. mGpsLocationProvider = gpsProvider;
  10. }

  11. // create a passive location provider, which is always enabled

  12. PassiveProvider passiveProvider = new PassiveProvider(this);
  13. addProvider(passiveProvider);
  14. mEnabledProviders.add(passiveProvider.getName());

  15. // initialize external network location and geocoder services

  16. if (mNetworkLocationProviderPackageName != null) {
  17. mNetworkLocationProvider =
  18. new LocationProviderProxy(mContext, LocationManager.NETWORK_PROVIDER,
  19. mNetworkLocationProviderPackageName, mLocationHandler);
  20. addProvider(mNetworkLocationProvider);
  21. }

  22. if (mGeocodeProviderPackageName != null) {
  23. mGeocodeProvider = new GeocoderProxy(mContext, mGeocodeProviderPackageName);
  24. }

  25. updateProvidersLocked();
  26. }

在构造完GpsLocationProvider之后将其add到全局变量ArrayList<LocationProviderInterface> mProviders中,备以后调用。

PassiveProvider暂时未了解到其用意。

然后启动了nerwork location和geocoder 两个service。但是可惜的是这两个服务都无法启动,因为他们是通过配置文件conifg.xml [framework/base/core/res/res/values]得到服务的名字,然后启动服务的。但是在这个配置文件中,两个服务的名字都是null

conifg.xml [framework/base/core/res/res/values]

<!-- Component name of the service providing network location support. -->
<string name="config_networkLocationProvider">@null</string>
<!-- Component name of the service providing geocoder API support. -->
<string name="config_geocodeProvider">@null</string>

其实这也导致了,在调用GetFromLocationName和GetFromLocation两个函数时提示“Service not Available”,这个是google Android 2.2中就存在的bug。

_loadProvidersLocked函数的最后一句是调用updateProvidersLocked函数,仍然在LocationManagerServic.java文件中。

2.3:

  1. private void updateProvidersLocked() {
  2. boolean changesMade = false;
  3. for (int i = mProviders.size() - 1; i >= 0; i--) {
  4. LocationProviderInterface p = mProviders.get(i);
  5. boolean isEnabled = p.isEnabled();
  6. String name = p.getName();
  7. boolean shouldBeEnabled = isAllowedBySettingsLocked(name);
  8. if (isEnabled && !shouldBeEnabled) {
  9. updateProviderListenersLocked(name, false);
  10. changesMade = true;
  11. } else if (!isEnabled && shouldBeEnabled) {
  12. updateProviderListenersLocked(name, true);
  13. changesMade = true;
  14. }
  15. }
  16. if (changesMade) {
  17. mContext.sendBroadcast(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION));
  18. }
  19. }

依靠前面的代码我们可以推测在mProviders里面应该存在一个gpsProvider 和PassiveProvider,而gpsProvider是未被enable的。而passiveProvider是enable的。

这边我们对gpsProvider进行讨论,他执行的是updateProviderListenersLocked(name,true) 然后当有发生改变,就是changesMade=true时,它发送了广播,内容是告诉大家LocationManager发生了变化,让需要的接收者自己接收。

下面我们跟进updateProviderListenersLocked(name,true)函数。

在LocationManagerService.java文件中

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

  3. LocationProviderInterface p = mProvidersByName.get(provider);
  4. if (p == null) {
  5. return;
  6. }

  7. ArrayList<Receiver> deadReceivers = null;
  8. ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
  9. if (records != null) {
  10. final int N = records.size();
  11. for (int i=0; i<N; i++) {
  12. UpdateRecord record = records.get(i);
  13. // Sends a notification message to the receiver

  14. if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
  15. if (deadReceivers == null) {
  16. deadReceivers = new ArrayList<Receiver>();
  17. }
  18. deadReceivers.add(record.mReceiver);
  19. }
  20. listeners++;
  21. }
  22. }

  23. if (deadReceivers != null) {
  24. for (int i=deadReceivers.size()-1; i>=0; i--) {
  25. removeUpdatesLocked(deadReceivers.get(i));
  26. }
  27. }
  28. if (enabled) {
  29. p.enable();
  30. if (listeners > 0) {
  31. p.setMinTime(getMinTimeLocked(provider), mTmpWorkSource);
  32. p.enableLocationTracking(true);
  33. }
  34. } else {
  35. p.enableLocationTracking(false);
  36. p.disable();
  37. }
  38. }

这边我们看if(enable)内的主题部分。 enable为真, 则启动了GPS服务。然后执行p.enable()函数。

enable()函数在GPSLocationProvider.java中

  1. /**
  2. * Enables this provider. When enabled, calls to getStatus()
  3. * must be handled. Hardware may be started up
  4. * when the provider is enabled.
  5. */
  6. public void enable() {
  7. synchronized (mHandler) {
  8. sendMessage(ENABLE, 1, null);
  9. }
  10. }
  1. private void sendMessage(int message, int arg, Object obj) {
  2. // hold a wake lock while messages are pending

  3. synchronized (mWakeLock) {
  4. mPendingMessageBits |= (1 << message);
  5. mWakeLock.acquire();
  6. mHandler.removeMessages(message);
  7. Message m = Message.obtain(mHandler, message);
  8. m.arg1 = arg;
  9. m.obj = obj;
  10. mHandler.sendMessage(m);
  11. }
  12. }

我们看到enable函数中只是调用了sendMessage。 跟进函数,可看到sendMessage函数,首先做的是把相关的消息标志位给设置位。而后获取mWakeLock ?这边有点疑问,之前进入本段代码的时候不是获取了mWakeLock了? 然后将上一次的相关消息删除,重新构造心的消息,让后发送给mHandler。

收到消息后,Hnadler会自动去调用handleMessage去处理收到的消息。

  1. public void handleMessage(Message msg) {
  2. int message = msg.what;
  3. switch (message) {
  4. case ENABLE:
  5. if (msg.arg1 == 1) {
  6. handleEnable();
  7. } else {
  8. handleDisable();
  9. }
  10. break;
  11. ...

根据构造的消息,我们将执行hanleEnable()。

  1. private void handleEnable() {
  2. if (DEBUG) Log.d(TAG, "handleEnable");
  3. if (mEnabled) return;
  4. mEnabled = native_init();

  5. if (mEnabled) {
  6. mSupportsXtra = native_supports_xtra();
  7. if (mSuplServerHost != null) {
  8. native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
  9. }
  10. if (mC2KServerHost != null) {
  11. native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
  12. }
  13. } else {
  14. Log.w(TAG, "Failed to enable location provider");
  15. }
  16. }

这边handleEnable函数主要做了两件事。

1.调用JNI层的native_init()方法去初始化GPS。

2.试图启动agps服务。

我们先看第一件事。在com_android_server_location_GPSLocationProvider.cpp可以找到JNI层的相关实现

  1. static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject obj)
  2. {
  3. const GpsInterface* interface = GetGpsInterface(env, obj);
  4. if (!interface)
  5. return false;

  6. if (!sGpsDebugInterface)
  7. sGpsDebugInterface = (const GpsDebugInterface*)interface->get_extension(GPS_DEBUG_INTERFACE);

  8. return true;
  9. }

这边调用了GetGpsInterface去获取接口并初始化GPS。 后半部分试图去调用其相关的扩展接口。

  1. static const GpsInterface* GetGpsInterface(JNIEnv* env, jobject obj) {
  2. // this must be set before calling into the HAL library

  3. if (!mCallbacksObj)
  4. mCallbacksObj = env->NewGlobalRef(obj);

  5. if (!sGpsInterface) {
  6. sGpsInterface = get_gps_interface();
  7. if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0) {
  8. sGpsInterface = NULL;
  9. return NULL;
  10. }
  11. }
  12. return sGpsInterface;
  13. }

GetGpsInterface里面也去调用了get_gps_interface(),而这个函数前面也有提到,最早的地方便是isSupported()的这个函数。在获取了这个接口之后,使用sGpsInterface->init函数进行了初始化。

在gps_qemu.c中(模拟器中)

  1. static int
  2. qemu_gps_init(GpsCallbacks* callbacks)
  3. {
  4. GpsState* s = _gps_state;

  5. if (!s->init)
  6. gps_state_init(s);

  7. if (s->fd < 0)
  8. return -1;

  9. s->callbacks = *callbacks;

  10. return 0;
  11. }

这边qemu_gps_init函数即是sGpsInterface->init函数,其中里面做了gps_state_init初始化,并注册了callbacks回调函数,而这个函数也是在JNI层实现的,而且有JNI层传下来的函数。

  1. static void
  2. gps_state_init( GpsState* state )
  3. {
  4. state->init = 1;
  5. state->control[0] = -1;
  6. state->control[1] = -1;
  7. state->fd = -1;

  8. state->fd = qemud_channel_open(QEMU_CHANNEL_NAME);

  9. if (state->fd < 0) {
  10. D("no gps emulation detected");
  11. return;
  12. }

  13. D("gps emulation will read from '%s' qemud channel", QEMU_CHANNEL_NAME );

  14. if ( socketpair( AF_LOCAL, SOCK_STREAM, 0, state->control ) < 0 ) {
  15. LOGE("could not create thread control socket pair: %s", strerror(errno));
  16. goto Fail;
  17. }

  18. if ( pthread_create( &state->thread, NULL, gps_state_thread, state ) != 0 ) {
  19. LOGE("could not create gps thread: %s", strerror(errno));
  20. goto Fail;
  21. }

  22. D("gps state initialized");
  23. return;

  24. Fail:
  25. gps_state_done( state );
  26. }

在这个gps_state_init函数中,首先打开串口,然后建立socket通信,然后建立线程监听底层数据上报,分别对应于代码中黄低部分。

我们顺便看到qemu_gps_get_extension 函数,

  1. static const void*
  2. qemu_gps_get_extension(const char* name)
  3. {
  4. // no extensions supported

  5. return NULL;
  6. }

这是一个空函数,说明初始化的时候调用的相关扩展接口是没有用的。

在Android2.2中,handleEnable还做了一件事情,就是创建了一个监听线程 。

而android2.3中,在GPSlocationProvider构造的时候就创建了一个线程。

  1. public GpsLocationProvider(Context context, ILocationManager locationManager) {
  2. ... ...
  3. // wait until we are fully initialized before returning

  4. mThread = new GpsLocationProviderThread();
  5. mThread.start();
  6. while (true) {
  7. try {
  8. mInitializedLatch.await();
  9. break;
  10. } catch (InterruptedException e) {
  11. Thread.currentThread().interrupt();
  12. }
  13. }
  14. }

查看run函数相关内容:

  1. public void run() {
  2. Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
  3. initialize();
  4. Looper.prepare();
  5. mHandler = new ProviderHandler();
  6. // signal when we are initialized and ready to go

  7. mInitializedLatch.countDown();
  8. Looper.loop();
  9. }

run函数去调用了 initialize初始化函数,然后新建一个looper,新建一个providerHandler 用于处理该线程的消息。然后看是否初始化完成。然后进入消息循环,准备收发,处理消息。

  1. private void initialize() {
  2. // register our receiver on our thread rather than the main thread
  1. IntentFilter intentFilter = new IntentFilter();
  2. intentFilter.addAction(ALARM_WAKEUP);
  3. intentFilter.addAction(ALARM_TIMEOUT);
  4. mContext.registerReceiver(mBroadcastReciever, intentFilter);
  5. }

初始化主要是将线程的接收者注册到我们的线程上,而不是注册到主线程上。

到这边为止我们完成了 p.enable()函数的分析。

LocationManageService.java中
  1. private void updateProviderListenersLocked(String provider, boolean enabled) {
  2. ... ...
  3. if (enabled) {
  4. p.enable();
  5. if (listeners > 0) {
  6. p.setMinTime(getMinTimeLocked(provider), mTmpWorkSource);
  7. p.enableLocationTracking(true);
  8. }
  9. } else {
  10. p.enableLocationTracking(false);
  11. p.disable();
  12. }
  13. }

接上, 我们研究完了p.enable函数。接下去 如果有listeners ,我们去调用p.enableLocationTracking()函数。

enableLocationTracking 在GPSLocationProvider.java中。

  1. public void enableLocationTracking(boolean enable) {
  2. // FIXME - should set a flag here to avoid race conditions with single shot request

  3. synchronized (mHandler) {
  4. sendMessage(ENABLE_TRACKING, (enable ? 1 : 0), null);
  5. }
  6. }
  1. public void handleMessage(Message msg) {
  2. int message = msg.what;
  3. switch (message) {
  4. case ENABLE:
  5. if (msg.arg1 == 1) {
  6. handleEnable();
  7. } else {
  8. handleDisable();
  9. }
  10. break;
  11. case ENABLE_TRACKING:
  12. handleEnableLocationTracking(msg.arg1 == 1);
  13. break;
  1. private void handleEnableLocationTracking(boolean enable) {
  2. if (enable) {
  3. mTTFF = 0;
  4. mLastFixTime = 0;
  5. startNavigating(false);
  6. } else {
  7. if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
  8. mAlarmManager.cancel(mWakeupIntent);
  9. mAlarmManager.cancel(mTimeoutIntent);
  10. }
  11. stopNavigating();
  12. }
  13. }
  1. private void startNavigating(boolean singleShot) {
  2. if (!mStarted) {
  3. if (DEBUG) Log.d(TAG, "startNavigating");
  4. mStarted = true;
  5. mSingleShot = singleShot;
  6. mPositionMode = GPS_POSITION_MODE_STANDALONE;

  7. if (Settings.Secure.getInt(mContext.getContentResolver(),
  8. Settings.Secure.ASSISTED_GPS_ENABLED, 1) != 0) {
  9. if (singleShot && hasCapability(GPS_CAPABILITY_MSA)) {
  10. mPositionMode = GPS_POSITION_MODE_MS_ASSISTED;
  11. } else if (hasCapability(GPS_CAPABILITY_MSB)) {
  12. mPositionMode = GPS_POSITION_MODE_MS_BASED;
  13. }
  14. }

  15. int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000);
  16. if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
  17. interval, 0, 0)) {
  18. mStarted = false;
  19. Log.e(TAG, "set_position_mode failed in startNavigating()");
  20. return;
  21. }
  22. if (!native_start()) {
  23. mStarted = false;
  24. Log.e(TAG, "native_start failed in startNavigating()");
  25. return;
  26. }

  27. // reset SV count to zero

  28. updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
  29. mFixRequestTime = System.currentTimeMillis();
  30. if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
  31. // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT

  32. // and our fix interval is not short

  33. if (mFixInterval >= NO_FIX_TIMEOUT) {
  34. mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
  35. SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);
  36. }
  37. }
  38. }
  39. }

这边我中主要关注两个native函数。native_set_position_mode 和native_start!

在com_android_server_location_GpslocationProvider.cpp中找到两个对应的函数。

首先是native_set_position_mode:

  1. static jboolean android_location_GpsLocationProvider_set_position_mode(JNIEnv* env, jobject obj,
  2. jint mode, jint recurrence, jint min_interval, jint preferred_accuracy, jint preferred_time)
  3. {
  4. const GpsInterface* interface = GetGpsInterface(env, obj);
  5. if (interface)
  6. return (interface->set_position_mode(mode, recurrence, min_interval, preferred_accuracy,
  7. preferred_time) == 0);
  8. else
  9. return false;
  10. }

这边调用了interface->set_position_mode。我们到gps_qemu.c当中去找其相关实现

  1. static int qemu_gps_set_position_mode(GpsPositionMode mode, int fix_frequency)
  2. {
  3. // FIXME - support fix_frequency

  4. return 0;
  5. }

显然其中没有相关的实现。

接下去我们看native_start函数。

  1. static jboolean android_location_GpsLocationProvider_start(JNIEnv* env, jobject obj)
  2. {
  3. const GpsInterface* interface = GetGpsInterface(env, obj);
  4. if (interface)
  5. return (interface->start() == 0);
  6. else
  7. return false;
  8. }
  1. static int qemu_gps_start()
  2. {
  3. GpsState* s = _gps_state;

  4. if (!s->init) {
  5. D("%s: called with uninitialized state !!", __FUNCTION__);
  6. return -1;
  7. }

  8. D("%s: called", __FUNCTION__);
  9. gps_state_start(s);
  10. return 0;
  11. }
通过向底层发送命令,CMD_START来启动gps。其实这个所谓的底层就是在enable/init函数中启动的等待数据的线程。
  1. static void
  2. gps_state_start( GpsState* s )
  3. {
  4. char cmd = CMD_START;
  5. int ret;

  6. do { ret=write( s->control[0], &cmd, 1 ); }
  7. while (ret < 0 && errno == EINTR);

  8. if (ret != 1)
  9. D("%s: could not send CMD_START command: ret=%d: %s",
  10. __FUNCTION__, ret, strerror(errno));
  11. }

数据监听线程

  1. /* this is the main thread, it waits for commands from gps_state_start/stop and,
  2. * when started, messages from the QEMU GPS daemon. these are simple NMEA sentences
  3. * that must be parsed to be converted into GPS fixes sent to the framework
  4. */
  5. static void*
  6. gps_state_thread( void* arg )
  7. {
  8. GpsState* state = (GpsState*) arg;
  9. NmeaReader reader[1];
  10. int epoll_fd = epoll_create(2);
  11. int started = 0;
  12. int gps_fd = state->fd;
  13. int control_fd = state->control[1];

  14. nmea_reader_init( reader );

  15. // register control file descriptors for polling

  16. epoll_register( epoll_fd, control_fd );
  17. epoll_register( epoll_fd, gps_fd );

  18. D("gps thread running");

  19. // now loop

  20. for (;;) {
  21. struct epoll_event events[2];
  22. int ne, nevents;

  23. nevents = epoll_wait( epoll_fd, events, 2, -1 );
  24. if (nevents < 0) {
  25. if (errno != EINTR)
  26. LOGE("epoll_wait() unexpected error: %s", strerror(errno));
  27. continue;
  28. }
  29. D("gps thread received %d events", nevents);
  30. for (ne = 0; ne < nevents; ne++) {
  31. if ((events[ne].events & (EPOLLERR|EPOLLHUP)) != 0) {
  32. LOGE("EPOLLERR or EPOLLHUP after epoll_wait() !?");
  33. goto Exit;
  34. }
  35. if ((events[ne].events & EPOLLIN) != 0) {
  36. int fd = events[ne].data.fd;

  37. if (fd == control_fd)
  38. {
  39. char cmd = 255;
  40. int ret;
  41. D("gps control fd event");
  42. do {
  43. ret = read( fd, &cmd, 1 );
  44. } while (ret < 0 && errno == EINTR);

  45. if (cmd == CMD_QUIT) {
  46. D("gps thread quitting on demand");
  47. goto Exit;
  48. }
  49. else if (cmd == CMD_START) {
  50. if (!started) {
  51. D("gps thread starting location_cb=%p", state->callbacks.location_cb);
  52. started = 1;
  53. nmea_reader_set_callback( reader, state->callbacks.location_cb );
  54. }
  55. }
  56. else if (cmd == CMD_STOP) {
  57. if (started) {
  58. D("gps thread stopping");
  59. started = 0;
  60. nmea_reader_set_callback( reader, NULL );
  61. }
  62. }
  63. }
  64. else if (fd == gps_fd)
  65. {
  66. char buff[32];
  67. D("gps fd event");
  68. for (;;) {
  69. int nn, ret;

  70. ret = read( fd, buff, sizeof(buff) );
  71. if (ret < 0) {
  72. if (errno == EINTR)
  73. continue;
  74. if (errno != EWOULDBLOCK)
  75. LOGE("error while reading from gps daemon socket: %s:", strerror(errno));
  76. break;
  77. }
  78. D("received %d bytes: %.*s", ret, ret, buff);
  79. for (nn = 0; nn < ret; nn++)
  80. nmea_reader_addc( reader, buff[nn] );
  81. }
  82. D("gps fd event end");
  83. }
  84. else
  85. {
  86. LOGE("epoll_wait() returned unkown fd %d ?", fd);
  87. }
  88. }
  89. }
  90. }
  91. Exit:
  92. return NULL;
  93. }

这个监听线程最主要的一个就是nmea_reader_set_callback( )函数

其实就是注册了一个回调函数,location_cb 这个回调函数就是对底层location数据上报的回调函数。

到此

enableLocationTracking函数完成了,

也就是LocationManageService.java中

updateProviderListenersLocked的完成

也就是updateProvidersLocked的完成,

也就是loadProviders函数的完成

也就是 initialize的完成,

也就是run的完成,

也就是systemReady的完成

所以完了

更多相关文章

  1. android是如何做DNS解析的
  2. Android(安卓)native 开发总结
  3. MTK平台camera bsp学习之camera HW架构篇
  4. Android控件笔记——使用RadioGroup和RadioButton实现单选效果
  5. Android(安卓)客户端Socket 实现及简单封装。
  6. 利用签名机制进行程序自检——Android防破解
  7. 知识梳理系列之五——OkHttp的原理
  8. Android(安卓)JNI(实现自己的JNI_OnLoad函数)
  9. [置顶] [Android基础]Android中使用HttpURLConnection

随机推荐

  1. Android——点击水纹效果
  2. Android电话拨号程序
  3. Android自定义View--时钟
  4. Android实现异步加载图片(转)
  5. Material Design : Maintaining Compatib
  6. 自定义弹窗,dialog
  7. Android异步加载图片详解之方式一(4)
  8. Android(安卓)ViewPager 的简单应用
  9. DialogUtils Material风格对话框工具类
  10. 安卓 图片处理