GPS 研究(Android2.3)

(红字表示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中
  1. /** Represents the standard GPS interface. */  
  2. typedef struct {   
  3.     /** set to sizeof(GpsInterface) */  
  4.     size_t          size;   
  5.     /**  
  6.      * Opens the interface and provides the callback routines  
  7.      * to the implemenation of this interface.  
  8.      */  
  9.     int   (*init)( GpsCallbacks* callbacks );   
  10.   
  11.     /** Starts navigating. */  
  12.     int   (*start)( void );   
  13.   
  14.     /** Stops navigating. */  
  15.     int   (*stop)( void );   
  16.   
  17.     /** Closes the interface. */  
  18.     void  (*cleanup)( void );   
  19.   
  20.     /** Injects the current time. */  
  21.     int   (*inject_time)(GpsUtcTime time, int64_t timeReference,   
  22.                          int uncertainty);   
  23.   
  24.     /** Injects current location from another location provider  
  25.      *  (typically cell ID).  
  26.      *  latitude and longitude are measured in degrees  
  27.      *  expected accuracy is measured in meters  
  28.      */  
  29.     int  (*inject_location)(double latitude, double longitude, float accuracy);   
  30.   
  31.     /**  
  32.      * Specifies that the next call to start will not use the  
  33.      * information defined in the flags. GPS_DELETE_ALL is passed for  
  34.      * a cold start.  
  35.      */  
  36.     void  (*delete_aiding_data)(GpsAidingData flags);   
  37.   
  38.     /**  
  39.      * min_interval represents the time between fixes in milliseconds.  
  40.      * preferred_accuracy represents the requested fix accuracy in meters.  
  41.      * preferred_time represents the requested time to first fix in milliseconds.  
  42.      */  
  43.     int   (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,   
  44.             uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);   
  45.   
  46.     /** Get a pointer to extension information. */  
  47.     const void* (*get_extension)(const char* name);   
  48. } GpsInterface;  
  1. /** Represents the standard GPS interface. */  
  2. typedef struct {  
  3.     /** set to sizeof(GpsInterface) */  
  4.     size_t          size;  
  5.     /** 
  6.      * Opens the interface and provides the callback routines 
  7.      * to the implemenation of this interface. 
  8.      */  
  9.     int   (*init)( GpsCallbacks* callbacks );  
  10.     /** Starts navigating. */  
  11.     int   (*start)( void );  
  12.     /** Stops navigating. */  
  13.     int   (*stop)( void );  
  14.     /** Closes the interface. */  
  15.     void  (*cleanup)( void );  
  16.     /** Injects the current time. */  
  17.     int   (*inject_time)(GpsUtcTime time, int64_t timeReference,  
  18.                          int uncertainty);  
  19.     /** Injects current location from another location provider 
  20.      *  (typically cell ID). 
  21.      *  latitude and longitude are measured in degrees 
  22.      *  expected accuracy is measured in meters 
  23.      */  
  24.     int  (*inject_location)(double latitude, double longitude, float accuracy);  
  25.     /** 
  26.      * Specifies that the next call to start will not use the 
  27.      * information defined in the flags. GPS_DELETE_ALL is passed for 
  28.      * a cold start. 
  29.      */  
  30.     void  (*delete_aiding_data)(GpsAidingData flags);  
  31.     /** 
  32.      * min_interval represents the time between fixes in milliseconds. 
  33.      * preferred_accuracy represents the requested fix accuracy in meters. 
  34.      * preferred_time represents the requested time to first fix in milliseconds. 
  35.      */  
  36.     int   (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,  
  37.             uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);  
  38.     /** Get a pointer to extension information. */  
  39.     const void* (*get_extension)(const char* name);  
  40. } GpsInterface;  

2.GpsCallbacks回调函数

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

2.2

  1. /** GPS callback structure. */  
  2. typedef struct {   
  3.     /** set to sizeof(GpsCallbacks) */  
  4.     size_t      size;   
  5.     gps_location_callback location_cb;   
  6.     gps_status_callback status_cb;   
  7.     gps_sv_status_callback sv_status_cb;   
  8.     gps_nmea_callback nmea_cb;   
  9. } GpsCallbacks;  
[c-sharp] view plain copy print ?
  1. /** GPS callback structure. */  
  2. typedef struct {  
  3.     /** set to sizeof(GpsCallbacks) */  
  4.     size_t      size;  
  5.     gps_location_callback location_cb;  
  6.     gps_status_callback status_cb;  
  7.     gps_sv_status_callback sv_status_cb;  
  8.     gps_nmea_callback nmea_cb;  
  9. } GpsCallbacks;  

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

 

  1. gps_set_capabilities set_capabilities_cb;   
  2. gps_acquire_wakelock acquire_wakelock_cb;   
  3. gps_release_wakelock release_wakelock_cb;   
  4. gps_create_thread create_thread_cb;  
  1. gps_set_capabilities set_capabilities_cb;  
  2. gps_acquire_wakelock acquire_wakelock_cb;  
  3. gps_release_wakelock release_wakelock_cb;  
  4. gps_create_thread create_thread_cb;  

 

 

3. GpsLocation

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

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

  1. /** Represents a location. */  
  2. typedef struct {   
  3.     /** set to sizeof(GpsLocation) */  
  4.     size_t          size;   
  5.     /** Contains GpsLocationFlags bits. */  
  6.     uint16_t        flags;   
  7.     /** Represents latitude in degrees. */  
  8.     double          latitude;   
  9.     /** Represents longitude in degrees. */  
  10.     double          longitude;   
  11.     /** Represents altitude in meters above the WGS 84 reference  
  12.      * ellipsoid. */  
  13.     double          altitude;   
  14.     /** Represents speed in meters per second. */  
  15.     float           speed;   
  16.     /** Represents heading in degrees. */  
  17.     float           bearing;   
  18.     /** Represents expected accuracy in meters. */  
  19.     float           accuracy;   
  20.     /** Timestamp for the location fix. */  
  21.     GpsUtcTime      timestamp;   
  22. } GpsLocation;  
  1. /** Represents a location. */  
  2. typedef struct {  
  3.     /** set to sizeof(GpsLocation) */  
  4.     size_t          size;  
  5.     /** Contains GpsLocationFlags bits. */  
  6.     uint16_t        flags;  
  7.     /** Represents latitude in degrees. */  
  8.     double          latitude;  
  9.     /** Represents longitude in degrees. */  
  10.     double          longitude;  
  11.     /** Represents altitude in meters above the WGS 84 reference 
  12.      * ellipsoid. */  
  13.     double          altitude;  
  14.     /** Represents speed in meters per second. */  
  15.     float           speed;  
  16.     /** Represents heading in degrees. */  
  17.     float           bearing;  
  18.     /** Represents expected accuracy in meters. */  
  19.     float           accuracy;  
  20.     /** Timestamp for the location fix. */  
  21.     GpsUtcTime      timestamp;  
  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.         
  9.         ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
  10.         if (records != null) {
  11.             final int N = records.size();
  12.             for (int i=0; i<N; i++) {
  13.                 UpdateRecord record = records.get(i);
  14.                 // Sends a notification message to the receiver

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

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

这边我们看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.         ... ...
  4.         // wait until we are fully initialized before returning

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

查看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的完成

所以完了
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值