Android系统Gps分析

6610阅读 0评论2013-06-09 conceptcon
分类:嵌入式

http://blog.csdn.net/xnwyd/article/details/7198728
1 GPS架构


2 GPS分析

2.1 头文件

头文件定义在:hardware/libhardware/include/hardware/gps.h,定义了GPS底层相关的结构体和接口

GPS位置信息结构体,包含经纬度,高度,速度,方位角等。


  1. /** Flags to indicate which values are valid in a GpsLocation. */  
  2. typedef uint16_t GpsLocationFlags;  
  3. // IMPORTANT: Note that the following values must match   
  4. // constants in GpsLocationProvider.java.   
  5. /** GpsLocation has valid latitude and longitude. */  
  6. #define GPS_LOCATION_HAS_LAT_LONG   0x0001   
  7. /** GpsLocation has valid altitude. */  
  8. #define GPS_LOCATION_HAS_ALTITUDE   0x0002   
  9. /** GpsLocation has valid speed. */  
  10. #define GPS_LOCATION_HAS_SPEED      0x0004   
  11. /** GpsLocation has valid bearing. */  
  12. #define GPS_LOCATION_HAS_BEARING    0x0008   
  13. /** GpsLocation has valid accuracy. */  
  14. #define GPS_LOCATION_HAS_ACCURACY   0x0010   
  15.   
  16. /** Represents a location. */  
  17. typedef struct {  
  18.     /** set to sizeof(GpsLocation) */  
  19.     size_t          size;  
  20.     /** Contains GpsLocationFlags bits. */  
  21.     uint16_t        flags;  
  22.     /** Represents latitude in degrees. */  
  23.     double          latitude;  
  24.     /** Represents longitude in degrees. */  
  25.     double          longitude;  
  26.     /** Represents altitude in meters above the WGS 84 reference 
  27.      * ellipsoid. */  
  28.     double          altitude;  
  29.     /** Represents speed in meters per second. */  
  30.     float           speed;  
  31.     /** Represents heading in degrees. */  
  32.     float           bearing;  
  33.     /** Represents expected accuracy in meters. */  
  34.     float           accuracy;  
  35.     /** Timestamp for the location fix. */  
  36.     GpsUtcTime      timestamp;  
  37. } GpsLocation;  
/** Flags to indicate which values are valid in a GpsLocation. */ typedef uint16_t GpsLocationFlags; // IMPORTANT: Note that the following values must match // constants in GpsLocationProvider.java. /** GpsLocation has valid latitude and longitude. */ #define GPS_LOCATION_HAS_LAT_LONG 0x0001 /** GpsLocation has valid altitude. */ #define GPS_LOCATION_HAS_ALTITUDE 0x0002 /** GpsLocation has valid speed. */ #define GPS_LOCATION_HAS_SPEED 0x0004 /** GpsLocation has valid bearing. */ #define GPS_LOCATION_HAS_BEARING 0x0008 /** GpsLocation has valid accuracy. */ #define GPS_LOCATION_HAS_ACCURACY 0x0010 /** Represents a location. */ typedef struct { /** set to sizeof(GpsLocation) */ size_t size; /** Contains GpsLocationFlags bits. */ uint16_t flags; /** Represents latitude in degrees. */ double latitude; /** Represents longitude in degrees. */ double longitude; /** Represents altitude in meters above the WGS 84 reference * ellipsoid. */ double altitude; /** Represents speed in meters per second. */ float speed; /** Represents heading in degrees. */ float bearing; /** Represents expected accuracy in meters. */ float accuracy; /** Timestamp for the location fix. */ GpsUtcTime timestamp; } GpsLocation;

GPS状态包括5种状态,分别为未知,正在定位,停止定位,启动未定义,未启动。


  1. /** GPS status event values. */  
  2. typedef uint16_t GpsStatusValue;  
  3. // IMPORTANT: Note that the following values must match   
  4. // constants in GpsLocationProvider.java.   
  5. /** GPS status unknown. */  
  6. #define GPS_STATUS_NONE             0   
  7. /** GPS has begun navigating. */  
  8. #define GPS_STATUS_SESSION_BEGIN    1   
  9. /** GPS has stopped navigating. */  
  10. #define GPS_STATUS_SESSION_END      2   
  11. /** GPS has powered on but is not navigating. */  
  12. #define GPS_STATUS_ENGINE_ON        3   
  13. /** GPS is powered off. */AgpsCallbacks  
  14.   
  15. AgpsInterface  
  16. #define GPS_STATUS_ENGINE_OFF       4   
  17.   
  18. /** Represents the status. */  
  19. typedef struct {  
  20.     /** set to sizeof(GpsStatus) */  
  21.     size_t          size;  
  22.     GpsStatusValue status;  
  23. } GpsStatus;  
/** GPS status event values. */ typedef uint16_t GpsStatusValue; // IMPORTANT: Note that the following values must match // constants in GpsLocationProvider.java. /** GPS status unknown. */ #define GPS_STATUS_NONE 0 /** GPS has begun navigating. */ #define GPS_STATUS_SESSION_BEGIN 1 /** GPS has stopped navigating. */ #define GPS_STATUS_SESSION_END 2 /** GPS has powered on but is not navigating. */ #define GPS_STATUS_ENGINE_ON 3 /** GPS is powered off. */AgpsCallbacks AgpsInterface #define GPS_STATUS_ENGINE_OFF 4 /** Represents the status. */ typedef struct { /** set to sizeof(GpsStatus) */ size_t size; GpsStatusValue status; } GpsStatus;


GPS卫星信息,包含卫星编号,信号强度,卫星仰望角,方位角等。

  1. /** Represents SV information. */  
  2. typedef struct {  
  3.     /** set to sizeof(GpsSvInfo) */  
  4.     size_t          size;  
  5.     /** Pseudo-random number for the SV. */  
  6.     int     prn;  
  7.     /** Signal to noise ratio. */  
  8.     float   snr;  
  9.     /** Elevation of SV in degrees. */  
  10.     float   elevation;  
  11.     /** Azimuth of SV in degrees. */  
  12.     float   azimuth;  
  13. } GpsSvInfo;  
/** Represents SV information. */ typedef struct { /** set to sizeof(GpsSvInfo) */ size_t size; /** Pseudo-random number for the SV. */ int prn; /** Signal to noise ratio. */ float snr; /** Elevation of SV in degrees. */ float elevation; /** Azimuth of SV in degrees. */ float azimuth; } GpsSvInfo;

GPS卫星状态,包含可见卫星数和信息,星历时间,年历时间等。


  1. /** Represents SV status. */  
  2. typedef struct {  
  3.     /** set to sizeof(GpsSvStatus) */  
  4.     size_t          size;  
  5.   
  6.     /** Number of SVs currently visible. */  
  7.     int         num_svs;  
  8.   
  9.     /** Contains an array of SV information. */  
  10.     GpsSvInfo   sv_list[GPS_MAX_SVS];  
  11.   
  12.     /** Represents a bit mask indicating which SVs 
  13.      * have ephemeris data. 
  14.      */  
  15.     uint32_t    ephemeris_mask;  
  16.   
  17.     /** Represents a bit mask indicating which SVs 
  18.      * have almanac data. 
  19.      */  
  20.     uint32_t    almanac_mask;  
  21.   
  22.     /** 
  23.      * Represents a bit mask indicating which SVs 
  24.      * were used for computing the most recent position fix. 
  25.      */  
  26.     uint32_t    used_in_fix_mask;  
  27. } GpsSvStatus;  
/** Represents SV status. */ typedef struct { /** set to sizeof(GpsSvStatus) */ size_t size; /** Number of SVs currently visible. */ int num_svs; /** Contains an array of SV information. */ GpsSvInfo sv_list[GPS_MAX_SVS]; /** Represents a bit mask indicating which SVs * have ephemeris data. */ uint32_t ephemeris_mask; /** Represents a bit mask indicating which SVs * have almanac data. */ uint32_t almanac_mask; /** * Represents a bit mask indicating which SVs * were used for computing the most recent position fix. */ uint32_t used_in_fix_mask; } GpsSvStatus;

回调函数定义

  1. /** Callback with location information. 向上层传递GPS位置信息 
  2.  *  Can only be called from a thread created by create_thread_cb. 
  3.  */  
  4. typedef void (* gps_location_callback)(GpsLocation* location);  
  5.   
  6. /** Callback with status information. 向上层传递GPS状态信息 
  7.  *  Can only be called from a thread created by create_thread_cb. 
  8.  */  
  9. typedef void (* gps_status_callback)(GpsStatus* status);  
  10.   
  11. /** Callback with SV status information. 向上层传递GPS卫星信息 
  12.  *  Can only be called from a thread created by create_thread_cb. 
  13.  */  
  14. typedef void (* gps_sv_status_callback)(GpsSvStatus* sv_info);  
  15.   
  16. /** Callback for reporting NMEA sentences. 向上层传递MEMA数据 
  17.  *  Can only be called from a thread created by create_thread_cb. 
  18.  */  
  19. typedef void (* gps_nmea_callback)(GpsUtcTime timestamp, const char* nmea, int length);  
  20.   
  21. /** Callback to inform framework of the GPS engine's capabilities.告知GPS模块可以实现的功能 
  22.  *  Capability parameter is a bit field of GPS_CAPABILITY_* flags. 
  23.  */  
  24. typedef void (* gps_set_capabilities)(uint32_t capabilities);  
  25.   
  26. /** Callback utility for acquiring the GPS wakelock.上锁,防止处理GPS事件时中止。 
  27.  *  This can be used to prevent the CPU from suspending while handling GPS events. 
  28.  */  
  29. typedef void (* gps_acquire_wakelock)();  
  30.   
  31. /** Callback utility for releasing the GPS wakelock. */释放锁  
  32. typedef void (* gps_release_wakelock)();  
  33.   
  34. /** Callback for creating a thread that can call into the Java framework code.等待上层请求 
  35.  *  This must be used to create any threads that report events up to the framework. 
  36.  */  
  37. typedef pthread_t (* gps_create_thread)(const char* name, void (*start)(void *), void* arg);  
  38.   
  39. /** GPS callback structure. */  
  40. typedef struct {  
  41.     /** set to sizeof(GpsCallbacks) */  
  42.     size_t      size;  
  43.     gps_location_callback location_cb;  
  44.     gps_status_callback status_cb;  
  45.     gps_sv_status_callback sv_status_cb;  
  46.     gps_nmea_callback nmea_cb;  
  47.     gps_set_capabilities set_capabilities_cb;  
  48.     gps_acquire_wakelock acquire_wakelock_cb;  
  49.     gps_release_wakelock release_wakelock_cb;  
  50.     gps_create_thread create_thread_cb;  
  51. } GpsCallbacks;  
/** Callback with location information. 向上层传递GPS位置信息 * Can only be called from a thread created by create_thread_cb. */ typedef void (* gps_location_callback)(GpsLocation* location); /** Callback with status information. 向上层传递GPS状态信息 * Can only be called from a thread created by create_thread_cb. */ typedef void (* gps_status_callback)(GpsStatus* status); /** Callback with SV status information. 向上层传递GPS卫星信息 * Can only be called from a thread created by create_thread_cb. */ typedef void (* gps_sv_status_callback)(GpsSvStatus* sv_info); /** Callback for reporting NMEA sentences. 向上层传递MEMA数据 * Can only be called from a thread created by create_thread_cb. */ typedef void (* gps_nmea_callback)(GpsUtcTime timestamp, const char* nmea, int length); /** Callback to inform framework of the GPS engine's capabilities.告知GPS模块可以实现的功能 * Capability parameter is a bit field of GPS_CAPABILITY_* flags. */ typedef void (* gps_set_capabilities)(uint32_t capabilities); /** Callback utility for acquiring the GPS wakelock.上锁,防止处理GPS事件时中止。 * This can be used to prevent the CPU from suspending while handling GPS events. */ typedef void (* gps_acquire_wakelock)(); /** Callback utility for releasing the GPS wakelock. */释放锁 typedef void (* gps_release_wakelock)(); /** Callback for creating a thread that can call into the Java framework code.等待上层请求 * This must be used to create any threads that report events up to the framework. */ typedef pthread_t (* gps_create_thread)(const char* name, void (*start)(void *), void* arg); /** GPS callback structure. */ typedef struct { /** set to sizeof(GpsCallbacks) */ size_t size; gps_location_callback location_cb; gps_status_callback status_cb; gps_sv_status_callback sv_status_cb; gps_nmea_callback nmea_cb; gps_set_capabilities set_capabilities_cb; gps_acquire_wakelock acquire_wakelock_cb; gps_release_wakelock release_wakelock_cb; gps_create_thread create_thread_cb; } GpsCallbacks;

GPS接口是最重要的结构体,上层是通过此接口与硬件适配层交互的。


  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. 关闭GPS接口*/  
  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.     /**设置定位模式和GPS工作模式等 
  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;  
/** Represents the standard GPS interface. */ typedef struct { /** set to sizeof(GpsInterface) */ size_t size; /** * Opens the interface and provides the callback routines * to the implemenation of this interface. */ int (*init)( GpsCallbacks* callbacks ); /** Starts navigating. 启动定位*/ int (*start)( void ); /** Stops navigating. 取消定位*/ int (*stop)( void ); /** Closes the interface. 关闭GPS接口*/ void (*cleanup)( void ); /** Injects the current time.填入时间 */ int (*inject_time)(GpsUtcTime time, int64_t timeReference, int uncertainty); /** Injects current location from another location provider填入位置 * (typically cell ID). * latitude and longitude are measured in degrees * expected accuracy is measured in meters */ int (*inject_location)(double latitude, double longitude, float accuracy); /** * Specifies that the next call to start will not use the删除全部或部分辅助数据,在性能测试时使用 * information defined in the flags. GPS_DELETE_ALL is passed for * a cold start. */ void (*delete_aiding_data)(GpsAidingData flags); /**设置定位模式和GPS工作模式等 * min_interval represents the time between fixes in milliseconds. * preferred_accuracy represents the requested fix accuracy in meters. * preferred_time represents the requested time to first fix in milliseconds. */ int (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence, uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time); /** Get a pointer to extension information. 自定义的接口*/ const void* (*get_extension)(const char* name); } GpsInterface;


GPS设备结构体,继承自hw_device_tcommon,硬件适配接口,向上层提供了重要的get_gps_interface接口。


  1. struct gps_device_t {  
  2.     struct hw_device_t common;  
  3.   
  4.     /** 
  5.      * Set the provided lights to the provided values. 
  6.      * 
  7.      * Returns: 0 on succes, error code on failure. 
  8.      */  
  9.     const GpsInterface* (*get_gps_interface)(struct gps_device_t* dev);  
  10. };  
struct gps_device_t { struct hw_device_t common; /** * Set the provided lights to the provided values. * * Returns: 0 on succes, error code on failure. */ const GpsInterface* (*get_gps_interface)(struct gps_device_t* dev); };

2.2硬件适配层

GPS硬件适配层的源码位于:hardware/qcom/gps目录下。

我们看gps/loc_api/llibloc_api/gps.c,首先定义了gps设备模块实例:

  1. const struct hw_module_t HAL_MODULE_INFO_SYM = {  
  2.     .tag = HARDWARE_MODULE_TAG,  
  3.     .version_major = 1,  
  4.     .version_minor = 0,  
  5.     .id = GPS_HARDWARE_MODULE_ID,  
  6.     .name = "loc_api GPS Module",  
  7.     .author = "Qualcomm USA, Inc.",  
  8.     .methods = &gps_module_methods,  
  9. };  
const struct hw_module_t HAL_MODULE_INFO_SYM = { .tag = HARDWARE_MODULE_TAG, .version_major = 1, .version_minor = 0, .id = GPS_HARDWARE_MODULE_ID, .name = "loc_api GPS Module", .author = "Qualcomm USA, Inc.", .methods = &gps_module_methods, };

这里的methods指向gps.c文件中的gps_module_methods


  1. static struct hw_module_methods_t gps_module_methods = {  
  2.     .open = open_gps  
  3. };  
static struct hw_module_methods_t gps_module_methods = { .open = open_gps };

gps_module_methods定义了设备的open函数为open_gps,我们看open_gps函数:


  1. static int open_gps(const struct hw_module_t* module, char const* name,  
  2.         struct hw_device_t** device)  
  3. {  
  4.     struct gps_device_t *dev = malloc(sizeof(struct gps_device_t));  
  5.     memset(dev, 0, sizeof(*dev));  
  6.   
  7.     dev->common.tag = HARDWARE_DEVICE_TAG;  
  8.     dev->common.version = 0;  
  9.     dev->common.module = (struct hw_module_t*)module;  
  10.     dev->get_gps_interface = gps__get_gps_interface;  
  11.   
  12.     *device = (struct hw_device_t*)dev;  
  13.     return 0;  
  14. }  
static int open_gps(const struct hw_module_t* module, char const* name, struct hw_device_t** device) { struct gps_device_t *dev = malloc(sizeof(struct gps_device_t)); memset(dev, 0, sizeof(*dev)); dev->common.tag = HARDWARE_DEVICE_TAG; dev->common.version = 0; dev->common.module = (struct hw_module_t*)module; dev->get_gps_interface = gps__get_gps_interface; *device = (struct hw_device_t*)dev; return 0; }

此处可以看作是GPS设备的初始化函数,在使用设备前必须执行此函数。函数里面指定了hw_device_tmodule成员,以及gps_device_tget_gps_interface成员。上层可通过gps_device_tget_gps_interface调用gps__get_gps_interface函数。gps__get_gps_interface的定义如下:

  1. const GpsInterface* gps__get_gps_interface(struct gps_device_t* dev)  
  2. {  
  3.     return get_gps_interface();  
  4. }  
const GpsInterface* gps__get_gps_interface(struct gps_device_t* dev) { return get_gps_interface(); }

用代码跟踪可看到,此函数返回了gps/loc_eng.cpp文件的sLocEngInterface变量,sLocEngInterface定义如下:

  1. // Defines the GpsInterface in gps.h   
  2. static const GpsInterface sLocEngInterface =  
  3. {  
  4.     sizeof(GpsInterface),  
  5.     loc_eng_init,  
  6.     loc_eng_start,  
  7.     loc_eng_stop,  
  8.     loc_eng_cleanup,  
  9.     loc_eng_inject_time,  
  10.     loc_eng_inject_location,  
  11.     loc_eng_delete_aiding_data,  
  12.     loc_eng_set_position_mode,  
  13.     loc_eng_get_extension,  
  14. };  
// Defines the GpsInterface in gps.h static const GpsInterface sLocEngInterface = { sizeof(GpsInterface), loc_eng_init, loc_eng_start, loc_eng_stop, loc_eng_cleanup, loc_eng_inject_time, loc_eng_inject_location, loc_eng_delete_aiding_data, loc_eng_set_position_mode, loc_eng_get_extension, };

sLocEngInterface指定了GpsInterface结构体的各个回调函数,如启动定位/取消定位等,这些回调函数的实现均在loc_eng.cpp中实现。



2.2 JNI适配层

GPSJNI适配层的源码位于:frameworks/base/services/jni/com_android_server_location_GpsLocationProvider.cpp

首先看注册JNI方法的函数定义:

  1. int register_android_server_location_GpsLocationProvider(JNIEnv* env)  
  2. {  
  3.     return jniRegisterNativeMethods(env, "com/android/server/location/GpsLocationProvider", sMethods, NELEM(sMethods));  
  4. }  
int register_android_server_location_GpsLocationProvider(JNIEnv* env) { return jniRegisterNativeMethods(env, "com/android/server/location/GpsLocationProvider", sMethods, NELEM(sMethods)); }

此函数被同目录下onload.cpp文件调用,调用地方在:

  1. extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)  
  2. {  
  3.     JNIEnv* env = NULL;  
  4.     jint result = -1;  
  5.   
  6.     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {  
  7.         LOGE("GetEnv failed!");  
  8.         return result;  
  9.     }  
  10.     LOG_ASSERT(env, "Could not retrieve the env!");  
  11.   
  12.     //...省略其他注册代码   
  13.     register_android_server_location_GpsLocationProvider(env);  
  14.   
  15.     return JNI_VERSION_1_4;  
  16. }  
extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = NULL; jint result = -1; if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { LOGE("GetEnv failed!"); return result; } LOG_ASSERT(env, "Could not retrieve the env!"); //...省略其他注册代码 register_android_server_location_GpsLocationProvider(env); return JNI_VERSION_1_4; }

从这里可以看到,JNI初始化的时候,即会进行JNI方法的注册,从而使上层应用能通过JNI调用c/c++本地方法。

回到register_android_server_location_GpsLocationProvider函数,变量sMethods定义如下:

  1. static JNINativeMethod sMethods[] = {  
  2.      /* name, signature, funcPtr */  
  3.     {"class_init_native""()V", (void *)android_location_GpsLocationProvider_class_init_native},  
  4.     {"native_is_supported""()Z", (void*)android_location_GpsLocationProvider_is_supported},  
  5.     {"native_init""()Z", (void*)android_location_GpsLocationProvider_init},  
  6.     {"native_cleanup""()V", (void*)android_location_GpsLocationProvider_cleanup},  
  7.     {"native_set_position_mode""(IIIII)Z", (void*)android_location_GpsLocationProvider_set_position_mode},  
  8.     {"native_start""()Z", (void*)android_location_GpsLocationProvider_start},  
  9.     {"native_stop""()Z", (void*)android_location_GpsLocationProvider_stop},  
  10.     {"native_delete_aiding_data""(I)V", (void*)android_location_GpsLocationProvider_delete_aiding_data},  
  11.     {"native_read_sv_status""([I[F[F[F[I)I", (void*)android_location_GpsLocationProvider_read_sv_status},  
  12.     {"native_read_nmea""([BI)I", (void*)android_location_GpsLocationProvider_read_nmea},  
  13.     {"native_inject_time""(JJI)V", (void*)android_location_GpsLocationProvider_inject_time},  
  14.     {"native_inject_location""(DDF)V", (void*)android_location_GpsLocationProvider_inject_location},  
  15.     {"native_supports_xtra""()Z", (void*)android_location_GpsLocationProvider_supports_xtra},  
  16.     {"native_inject_xtra_data""([BI)V", (void*)android_location_GpsLocationProvider_inject_xtra_data},  
  17.     {"native_agps_data_conn_open""(Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_agps_data_conn_open},  
  18.     {"native_agps_data_conn_closed""()V", (void*)android_location_GpsLocationProvider_agps_data_conn_closed},  
  19.     {"native_agps_data_conn_failed""()V", (void*)android_location_GpsLocationProvider_agps_data_conn_failed},  
  20.     {"native_agps_set_id","(ILjava/lang/String;)V",(void*)android_location_GpsLocationProvider_agps_set_id},  
  21.     {"native_agps_set_ref_location_cellid","(IIIII)V",(void*)android_location_GpsLocationProvider_agps_set_reference_location_cellid},  
  22.     {"native_set_agps_server""(ILjava/lang/String;I)V", (void*)android_location_GpsLocationProvider_set_agps_server},  
  23.     {"native_send_ni_response""(II)V", (void*)android_location_GpsLocationProvider_send_ni_response},  
  24.     {"native_agps_ni_message""([BI)V", (void *)android_location_GpsLocationProvider_agps_send_ni_message},  
  25.     {"native_get_internal_state""()Ljava/lang/String;", (void*)android_location_GpsLocationProvider_get_internal_state},  
  26.     {"native_update_network_state""(ZIZLjava/lang/String;)V", (void*)android_location_GpsLocationProvider_update_network_state },  
  27. };  
static JNINativeMethod sMethods[] = { /* name, signature, funcPtr */ {"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native}, {"native_is_supported", "()Z", (void*)android_location_GpsLocationProvider_is_supported}, {"native_init", "()Z", (void*)android_location_GpsLocationProvider_init}, {"native_cleanup", "()V", (void*)android_location_GpsLocationProvider_cleanup}, {"native_set_position_mode", "(IIIII)Z", (void*)android_location_GpsLocationProvider_set_position_mode}, {"native_start", "()Z", (void*)android_location_GpsLocationProvider_start}, {"native_stop", "()Z", (void*)android_location_GpsLocationProvider_stop}, {"native_delete_aiding_data", "(I)V", (void*)android_location_GpsLocationProvider_delete_aiding_data}, {"native_read_sv_status", "([I[F[F[F[I)I", (void*)android_location_GpsLocationProvider_read_sv_status}, {"native_read_nmea", "([BI)I", (void*)android_location_GpsLocationProvider_read_nmea}, {"native_inject_time", "(JJI)V", (void*)android_location_GpsLocationProvider_inject_time}, {"native_inject_location", "(DDF)V", (void*)android_location_GpsLocationProvider_inject_location}, {"native_supports_xtra", "()Z", (void*)android_location_GpsLocationProvider_supports_xtra}, {"native_inject_xtra_data", "([BI)V", (void*)android_location_GpsLocationProvider_inject_xtra_data}, {"native_agps_data_conn_open", "(Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_agps_data_conn_open}, {"native_agps_data_conn_closed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_closed}, {"native_agps_data_conn_failed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_failed}, {"native_agps_set_id","(ILjava/lang/String;)V",(void*)android_location_GpsLocationProvider_agps_set_id}, {"native_agps_set_ref_location_cellid","(IIIII)V",(void*)android_location_GpsLocationProvider_agps_set_reference_location_cellid}, {"native_set_agps_server", "(ILjava/lang/String;I)V", (void*)android_location_GpsLocationProvider_set_agps_server}, {"native_send_ni_response", "(II)V", (void*)android_location_GpsLocationProvider_send_ni_response}, {"native_agps_ni_message", "([BI)V", (void *)android_location_GpsLocationProvider_agps_send_ni_message}, {"native_get_internal_state", "()Ljava/lang/String;", (void*)android_location_GpsLocationProvider_get_internal_state}, {"native_update_network_state", "(ZIZLjava/lang/String;)V", (void*)android_location_GpsLocationProvider_update_network_state }, };

这里定义了GPS所有向上层提供的JNI本地方法,这些本地方法是如何与硬件适配层交互的呢?我们看其中一个本地方法android_location_GpsLocationProvider_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. }  
static jboolean android_location_GpsLocationProvider_start(JNIEnv* env, jobject obj) { const GpsInterface* interface = GetGpsInterface(env, obj); if (interface) return (interface->start() == 0); else return false; }

它调用了GetGpsInterface获得GpsInterface接口,然后直接调用该接口的start回调函数。GetGpsInterface方法定义如下:

  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.   
  6.     if (!sGpsInterface) {  
  7.         sGpsInterface = get_gps_interface();  
  8.         if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0) {  
  9.             sGpsInterface = NULL;  
  10.             return NULL;  
  11.         }  
  12.     }  
  13.     return sGpsInterface;  
  14. }  
static const GpsInterface* GetGpsInterface(JNIEnv* env, jobject obj) { // this must be set before calling into the HAL library if (!mCallbacksObj) mCallbacksObj = env->NewGlobalRef(obj); if (!sGpsInterface) { sGpsInterface = get_gps_interface(); if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0) { sGpsInterface = NULL; return NULL; } } return sGpsInterface; }

这个函数返回了sGpsInterface,而sGpsInterface又是从get_gps_interface()获得的,我们继续查看get_gps_interface()函数的实现:

  1. static const GpsInterface* get_gps_interface() {  
  2.     int err;  
  3.     hw_module_t* module;  
  4.     const GpsInterface* interface = NULL;  
  5.   
  6.     err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);  
  7.     if (err == 0) {  
  8.         hw_device_t* device;  
  9.         err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);  
  10.         if (err == 0) {  
  11.             gps_device_t* gps_device = (gps_device_t *)device;  
  12.             interface = gps_device->get_gps_interface(gps_device);  
  13.         }  
  14.     }  
  15.   
  16.     return interface;  
  17. }  
static const GpsInterface* get_gps_interface() { int err; hw_module_t* module; const GpsInterface* interface = NULL; err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module); if (err == 0) { hw_device_t* device; err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device); if (err == 0) { gps_device_t* gps_device = (gps_device_t *)device; interface = gps_device->get_gps_interface(gps_device); } } return interface; }

这里面调用hw_get_module加载硬件适配模块.so文件,接着通过hw_device_t接口调用open()函数,实际执行gps/loc_api/llibloc_api/gps.c定义的open_gps函数,而后调用gps_device_t接口的get_gps_interface函数,此函数也是在gps.c中定义的,最后返回硬件适配层中loc_eng.cpp文件的sLocEngInterface,从而打通了上层到底层的通道。



2.3 Java Framework

GPSFramework源码位于:frameworks/base/location

2.3.1接口和类简介

首先对GPSFramework重要的接口和类作一个简单的介绍



GpsStatus.Listener

用于当Gps状态发生变化时接收通知

GpsStatus.NmeaListener

用于接收GpsNMEA数据

LocationListener

用于接收当位置信息发生变化时,LocationManager发出的通知



Address

地址信息类

Criteria

用于根据设备情况动态选择provider

Geocoder

用于处理地理编码信息

GpsSatellite

用于获取当前卫星状态

GpsStatus

用于获取当前Gps状态

Location

地理位置信息类

LocationManager

用于获取和操作gps系统服务

LocationProvider

抽象类,用于提供位置提供者(Locationprovider



2.3.2 使用Gps编程接口

下面,我们用一个代码示例说明如何在应用层写一个简单的gps程序。

  1.      
  2.      
  3.     
  4.     
             
  • 接着获取位置信息:

  1.         //获取位置服务   
  2.  LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);    
  3.        Criteria criteria = new Criteria();    
  4.        // 获得最好的定位效果     
  5.        criteria.setAccuracy(Criteria.ACCURACY_FINE);  //设置为最大精度   
  6.        criteria.setAltitudeRequired(false);  //不获取海拔信息   
  7.        criteria.setBearingRequired(false);  //不获取方位信息   
  8.        criteria.setCostAllowed(false);  //是否允许付费   
  9.        criteria.setPowerRequirement(Criteria.POWER_LOW);  // 使用省电模式   
  10.        // 获得当前的位置提供者     
  11.        String provider = locationManager.getBestProvider(criteria, true);    
  12.        // 获得当前的位置     
  13.        Location location = locationManager.getLastKnownLocation(provider);    
  14. Geocoder gc = new Geocoder(this);     
  15.        List
     addresses = null;    
  16.        try {  
  17.     //根据经纬度获得地址信息     
  18.            addresses = gc.getFromLocation(location.getLatitude(), location.getLongitude(), 1);    
  19.        } catch (IOException e) {    
  20.            e.printStackTrace();    
  21.        } if (addresses.size() > 0) {  
  22. //获取address类的成员信息   
  23. Sring msg = “”;     
  24.        msg += "AddressLine:" + addresses.get(0).getAddressLine(0)+ "\n";     
  25.        msg += "CountryName:" + addresses.get(0).getCountryName()+ "\n";     
  26.        msg += "Locality:" + addresses.get(0).getLocality() + "\n";     
  27.        msg += "FeatureName:" + addresses.get(0).getFeatureName();     
  28.        }     
//获取位置服务 LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); Criteria criteria = new Criteria(); // 获得最好的定位效果 criteria.setAccuracy(Criteria.ACCURACY_FINE); //设置为最大精度 criteria.setAltitudeRequired(false); //不获取海拔信息 criteria.setBearingRequired(false); //不获取方位信息 criteria.setCostAllowed(false); //是否允许付费 criteria.setPowerRequirement(Criteria.POWER_LOW); // 使用省电模式 // 获得当前的位置提供者 String provider = locationManager.getBestProvider(criteria, true); // 获得当前的位置 Location location = locationManager.getLastKnownLocation(provider); Geocoder gc = new Geocoder(this); List
addresses = null; try { //根据经纬度获得地址信息 addresses = gc.getFromLocation(location.getLatitude(), location.getLongitude(), 1); } catch (IOException e) { e.printStackTrace(); } if (addresses.size() > 0) { //获取address类的成员信息 Sring msg = “”; msg += "AddressLine:" + addresses.get(0).getAddressLine(0)+ "\n"; msg += "CountryName:" + addresses.get(0).getCountryName()+ "\n"; msg += "Locality:" + addresses.get(0).getLocality() + "\n"; msg += "FeatureName:" + addresses.get(0).getFeatureName(); }
  • 设置侦听,当位置信息发生变化时,自动更新相关信息

  1.       //匿名类,继承自LocationListener接口   
  2. private final LocationListener locationListener = new LocationListener() {  
  3.            public void onLocationChanged(Location location) {  
  4.            updateWithNewLocation(location);//更新位置信息   
  5.            }  
  6.            public void onProviderDisabled(String provider){  
  7.            updateWithNewLocation(null);//更新位置信息   
  8.            }  
  9.            public void onProviderEnabled(String provider){ }  
  10.            public void onStatusChanged(String provider, int status,Bundle extras){ }  
  11.    };  
  12. //更新位置信息   
  13. private void updateWithNewLocation(Location location) {  
  14.          
  15.   
  16.            if (location != null) {  
  17.     //获取经纬度   
  18.            double lat = location.getLatitude();  
  19.            double lng = location.getLongitude();  
  20.    }  
  21. //添加侦听   
  22.  locationManager.requestLocationUpdates(provider, 200010,locationListener);  
//匿名类,继承自LocationListener接口 private final LocationListener locationListener = new LocationListener() { public void onLocationChanged(Location location) { updateWithNewLocation(location);//更新位置信息 } public void onProviderDisabled(String provider){ updateWithNewLocation(null);//更新位置信息 } public void onProviderEnabled(String provider){ } public void onStatusChanged(String provider, int status,Bundle extras){ } }; //更新位置信息 private void updateWithNewLocation(Location location) { if (location != null) { //获取经纬度 double lat = location.getLatitude(); double lng = location.getLongitude(); } //添加侦听 locationManager.requestLocationUpdates(provider, 2000, 10,locationListener);

2.3.3接口和类分析

下面对相关的类或接口进行分析,LocationManager的代码文件位于: frameworks/base/location/java/location/LocationManager.java 

我们看其构造函数:

  1. public LocationManager(ILocationManager service) {  
  2.         mService = service;  
  3.     }  
public LocationManager(ILocationManager service) { mService = service; }

其中mServiceILocationManager接口类型,构造函数的参数为service,外部调用时传入LocationManagerService实例。LocationManagerandroid系统的gps位置信息系统服务,在稍后将会对其进行分析。由带参构造函数实例化LocationManager类的方式用得不多,一般用的方式是getSystemService获得LocationManagerService服务,再强制转换为LocationManager。例如在2.3.2中的代码示例中是这样获取gps服务的:

  1. LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);    
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

这里的Context.LOCATION_SERVICElocation”,标识gps服务。

LocationManagerService服务是整个GpsFramework的核心,首先看它是如何加载的,代码文件位于:frameworks/base/services/java/com/android/server/systemserver.java

  1. //省略其他代码   
  2. LocationManagerService location = null;  
  3. //省略其他代码   
  4. try {  
  5.                 Slog.i(TAG, "Location Manager");  
  6.                 location = new LocationManagerService(context);  
  7.                 ServiceManager.addService(Context.LOCATION_SERVICE, location);  
  8.             } catch (Throwable e) {  
  9.                 Slog.e(TAG, "Failure starting Location Manager", e);  
  10.             }  
…//省略其他代码 LocationManagerService location = null; …//省略其他代码 try { Slog.i(TAG, "Location Manager"); location = new LocationManagerService(context); ServiceManager.addService(Context.LOCATION_SERVICE, location); } catch (Throwable e) { Slog.e(TAG, "Failure starting Location Manager", e); }

此处向ServiceManger系统服务管理器注册了新的服务,其名称为location”,类型为LocationManagerService。注册此服务后,Java应用程序可通过ServiceManager获得LocationManagerService的代理接口ILocationManager.Stub从而调用LocationManagerService提供的接口函数。ILocationManager位于:

frameworks/base/location/java/location/ILocationManager.aidl,其代码如下:

  1. /** 
  2.  * System private API for talking with the location service. 
  3.  * 
  4.  * {@hide} 
  5.  */  
  6. interface ILocationManager  
  7. {  
  8.     List getAllProviders();  
  9.     List getProviders(in Criteria criteria, boolean enabledOnly);  
  10.     String getBestProvider(in Criteria criteria, boolean enabledOnly);  
  11.     boolean providerMeetsCriteria(String provider, in Criteria criteria);  
  12.   
  13.     void requestLocationUpdates(String provider, in Criteria criteria, long minTime, float minDistance,  
  14.         boolean singleShot, in ILocationListener listener);  
  15.     void requestLocationUpdatesPI(String provider, in Criteria criteria, long minTime, float minDistance,  
  16.         boolean singleShot, in PendingIntent intent);  
  17.     void removeUpdates(in ILocationListener listener);  
  18.     void removeUpdatesPI(in PendingIntent intent);  
  19.   
  20.     boolean addGpsStatusListener(IGpsStatusListener listener);  
  21.     void removeGpsStatusListener(IGpsStatusListener listener);  
  22.   
  23.     // for reporting callback completion   
  24.     void locationCallbackFinished(ILocationListener listener);  
  25.   
  26.     boolean sendExtraCommand(String provider, String command, inout Bundle extras);  
  27.   
  28.     void addProximityAlert(double latitude, double longitude, float distance,  
  29.         long expiration, in PendingIntent intent);  
  30.     void removeProximityAlert(in PendingIntent intent);  
  31.   
  32.     Bundle getProviderInfo(String provider);  
  33.     boolean isProviderEnabled(String provider);  
  34.   
  35.     Location getLastKnownLocation(String provider);  
  36.   
  37.     // Used by location providers to tell the location manager when it has a new location.   
  38.     // Passive is true if the location is coming from the passive provider, in which case   
  39.     // it need not be shared with other providers.   
  40.     void reportLocation(in Location location, boolean passive);  
  41.   
  42.     boolean geocoderIsPresent();  
  43.     String getFromLocation(double latitude, double longitude, int maxResults,  
  44.         in GeocoderParams params, out List
     addrs);  
  45.     String getFromLocationName(String locationName,  
  46.         double lowerLeftLatitude, double lowerLeftLongitude,  
  47.         double upperRightLatitude, double upperRightLongitude, int maxResults,  
  48.         in GeocoderParams params, out List
     addrs);  
  49.   
  50.     void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite,  
  51.         boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,  
  52.         boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy);  
  53.     void removeTestProvider(String provider);  
  54.     void setTestProviderLocation(String provider, in Location loc);  
  55.     void clearTestProviderLocation(String provider);  
  56.     void setTestProviderEnabled(String provider, boolean enabled);  
  57.     void clearTestProviderEnabled(String provider);  
  58.     void setTestProviderStatus(String provider, int status, in Bundle extras, long updateTime);  
  59.     void clearTestProviderStatus(String provider);  
  60.   
  61.     // for NI support   
  62.     boolean sendNiResponse(int notifId, int userResponse);  
  63. }  
/** * System private API for talking with the location service. * * {@hide} */ interface ILocationManager { List getAllProviders(); List getProviders(in Criteria criteria, boolean enabledOnly); String getBestProvider(in Criteria criteria, boolean enabledOnly); boolean providerMeetsCriteria(String provider, in Criteria criteria); void requestLocationUpdates(String provider, in Criteria criteria, long minTime, float minDistance, boolean singleShot, in ILocationListener listener); void requestLocationUpdatesPI(String provider, in Criteria criteria, long minTime, float minDistance, boolean singleShot, in PendingIntent intent); void removeUpdates(in ILocationListener listener); void removeUpdatesPI(in PendingIntent intent); boolean addGpsStatusListener(IGpsStatusListener listener); void removeGpsStatusListener(IGpsStatusListener listener); // for reporting callback completion void locationCallbackFinished(ILocationListener listener); boolean sendExtraCommand(String provider, String command, inout Bundle extras); void addProximityAlert(double latitude, double longitude, float distance, long expiration, in PendingIntent intent); void removeProximityAlert(in PendingIntent intent); Bundle getProviderInfo(String provider); boolean isProviderEnabled(String provider); Location getLastKnownLocation(String provider); // Used by location providers to tell the location manager when it has a new location. // Passive is true if the location is coming from the passive provider, in which case // it need not be shared with other providers. void reportLocation(in Location location, boolean passive); boolean geocoderIsPresent(); String getFromLocation(double latitude, double longitude, int maxResults, in GeocoderParams params, out List
addrs); String getFromLocationName(String locationName, double lowerLeftLatitude, double lowerLeftLongitude, double upperRightLatitude, double upperRightLongitude, int maxResults, in GeocoderParams params, out List
addrs); void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite, boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude, boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy); void removeTestProvider(String provider); void setTestProviderLocation(String provider, in Location loc); void clearTestProviderLocation(String provider); void setTestProviderEnabled(String provider, boolean enabled); void clearTestProviderEnabled(String provider); void setTestProviderStatus(String provider, int status, in Bundle extras, long updateTime); void clearTestProviderStatus(String provider); // for NI support boolean sendNiResponse(int notifId, int userResponse); }

android系统通过ILocationManager.aidl文件自动生成IlocationManager.Stub代理接口,在Java客户端获取LocationManagerService的方式如下:

  1. ILocationManager mLocationManager;  
  2. IBinder b = ServiceManager.getService(Context.LOCATION_SERVICE);  
  3. mLocationManager = IlocationManager.Stub.asInterface(b);  
ILocationManager mLocationManager; IBinder b = ServiceManager.getService(Context.LOCATION_SERVICE); mLocationManager = IlocationManager.Stub.asInterface(b);

客户端通过mLocationManager即可操作LocationMangerService继承自ILocationManager.Stub的的公共接口。之前提到了通过getSystemSerivice方式也可以获得LocationManagerService,但getSystemService()返回的是Object,必须转换为其他接口,我们可以看到之前的是强制转换为LocationManager类型,而此处由ServiceManager.getService返回IBinder接口,再通过ILocationManager.Stub转换为ILocationManager类型,是更加规范的做法。

LocationMangerService的代码文件位于:

frameworks/base/services/java/com/android/server/LocationMangerService.java

我们首先看其中的systemReady()函数

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

此处启动自身服务线程,因LocationMangerService继承自Runnable接口,当启动此线程后,会执行继承自Runnable接口的run()函数,我们看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.     }  
public void run() { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); Looper.prepare(); mLocationHandler = new LocationWorkerHandler(); initialize(); Looper.loop(); }

此处调用了initialize()进行初始化,initialize()函数定义如下:

  1. private void initialize() {  
  2.        //...省略其他代码   
  3.         loadProviders();  
  4.       
  5.     //...省略其他代码   
  6.           
  7.     }  
private void initialize() { //...省略其他代码 loadProviders(); //...省略其他代码 }

此处调用了loadProviders()函数,loadProviders()函数调用了_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.         // create a passive location provider, which is always enabled   
  13.         PassiveProvider passiveProvider = new PassiveProvider(this);  
  14.         addProvider(passiveProvider);  
  15.         mEnabledProviders.add(passiveProvider.getName());  
  16.   
  17.         // initialize external network location and geocoder services   
  18.         if (mNetworkLocationProviderPackageName != null) {  
  19.             mNetworkLocationProvider =  
  20.                 new LocationProviderProxy(mContext, LocationManager.NETWORK_PROVIDER,  
  21.                         mNetworkLocationProviderPackageName, mLocationHandler);  
  22.             addProvider(mNetworkLocationProvider);  
  23.         }  
  24.   
  25.         if (mGeocodeProviderPackageName != null) {  
  26.             mGeocodeProvider = new GeocoderProxy(mContext, mGeocodeProviderPackageName);  
  27.         }  
  28.   
  29.         updateProvidersLocked();  
  30.     }  
private void _loadProvidersLocked() { // Attempt to load "real" providers first if (GpsLocationProvider.isSupported()) { // Create a gps location provider GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this); mGpsStatusProvider = gpsProvider.getGpsStatusProvider(); mNetInitiatedListener = gpsProvider.getNetInitiatedListener(); addProvider(gpsProvider); mGpsLocationProvider = gpsProvider; } // create a passive location provider, which is always enabled PassiveProvider passiveProvider = new PassiveProvider(this); addProvider(passiveProvider); mEnabledProviders.add(passiveProvider.getName()); // initialize external network location and geocoder services if (mNetworkLocationProviderPackageName != null) { mNetworkLocationProvider = new LocationProviderProxy(mContext, LocationManager.NETWORK_PROVIDER, mNetworkLocationProviderPackageName, mLocationHandler); addProvider(mNetworkLocationProvider); } if (mGeocodeProviderPackageName != null) { mGeocodeProvider = new GeocoderProxy(mContext, mGeocodeProviderPackageName); } updateProvidersLocked(); }

在这里对GpsLocationProviderNetworkLocationProvider类作了初始化,并添加到provider集合中。GpsLocationProviderNetworkLocationProvider继承自LocationProviderInterface接口,分别代表两种位置提供者(LocationProvider)

1LocationManager.GPS_PROVIDERGPS模式,精度比较高,但是慢而且消耗电力,而且可能因为天气原因或者障碍物而无法获取卫星信息,另外设备可能没有GPS模块(2LocationManager.NETWORK_PROVIDER:通过网络获取定位信息,精度低,耗电少,获取信息速度较快,不依赖GPS模块。


Android提供criteria类,可根据当前设备情况动态选择位置提供者。我们在之前2.3.2的代码示例中,有这样一句代码:

  1. // 获得当前的位置提供者     
  2. String provider = locationManager.getBestProvider(criteria, true);    
// 获得当前的位置提供者 String provider = locationManager.getBestProvider(criteria, true);

getBestProvider其实是根据Criteria的条件遍历mProviders集合,返回符合条件的provider名称。我们再看GpsLocationProvider的实现,其代码文件位于:

frameworks/base/services/java/com/android/server/location/GpsLocationProvider.java

GpsLocationProvider的构造函数中:

  1. public GpsLocationProvider(Context context, ILocationManager locationManager) {  
  2.          
  3.     //...省略部分代码  
  4.         IntentFilter intentFilter = new IntentFilter();  
  5.         intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION);  
  6.         intentFilter.addDataScheme("sms");  
  7.         intentFilter.addDataAuthority("localhost","7275");  
  8.         context.registerReceiver(mBroadcastReciever, intentFilter);  
  9.   
  10.         intentFilter = new IntentFilter();  
  11.         intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION);  
  12.         try {  
  13.             intentFilter.addDataType("application/vnd.omaloc-supl-init");  
  14.         } catch (IntentFilter.MalformedMimeTypeException e) {  
  15.             Log.w(TAG, "Malformed SUPL init mime type");  
  16.         }  
  17.         context.registerReceiver(mBroadcastReciever, intentFilter);  
  18.   
  19.           
  20.         //...省略部分代码  
  21.         // wait until we are fully initialized before returning  
  22.         mThread = new GpsLocationProviderThread();  
  23.         mThread.start();  
  24.         while (true) {  
  25.             try {  
  26.                 mInitializedLatch.await();  
  27.                 break;  
  28.             } catch (InterruptedException e) {  
  29.                 Thread.currentThread().interrupt();  
  30.             }  
  31.         }  
  32.     }  
public GpsLocationProvider(Context context, ILocationManager locationManager) { //...省略部分代码 IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION); intentFilter.addDataScheme("sms"); intentFilter.addDataAuthority("localhost","7275"); context.registerReceiver(mBroadcastReciever, intentFilter); intentFilter = new IntentFilter(); intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION); try { intentFilter.addDataType("application/vnd.omaloc-supl-init"); } catch (IntentFilter.MalformedMimeTypeException e) { Log.w(TAG, "Malformed SUPL init mime type"); } context.registerReceiver(mBroadcastReciever, intentFilter); //...省略部分代码 // wait until we are fully initialized before returning mThread = new GpsLocationProviderThread(); mThread.start(); while (true) { try { mInitializedLatch.await(); break; } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }

这里注册了广播接受者mBroadcastReciever,用于接收广播消息,消息过滤在intentFilter中定义。下面看它接收广播消息时的动作:

  1. private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() {  
  2.         @Override public void onReceive(Context context, Intent intent) {  
  3.             String action = intent.getAction();  
  4.   
  5.             if (action.equals(ALARM_WAKEUP)) {  
  6.                 if (DEBUG) Log.d(TAG, "ALARM_WAKEUP");  
  7.                 startNavigating(false);  
  8.             } else if (action.equals(ALARM_TIMEOUT)) {  
  9.                 if (DEBUG) Log.d(TAG, "ALARM_TIMEOUT");  
  10.                 hibernate();  
  11.             } else if (action.equals(Intents.DATA_SMS_RECEIVED_ACTION)) {  
  12.                 checkSmsSuplInit(intent);  
  13.             } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {  
  14.                 checkWapSuplInit(intent);  
  15.              }  
  16.         }  
  17.     };  
private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(ALARM_WAKEUP)) { if (DEBUG) Log.d(TAG, "ALARM_WAKEUP"); startNavigating(false); } else if (action.equals(ALARM_TIMEOUT)) { if (DEBUG) Log.d(TAG, "ALARM_TIMEOUT"); hibernate(); } else if (action.equals(Intents.DATA_SMS_RECEIVED_ACTION)) { checkSmsSuplInit(intent); } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) { checkWapSuplInit(intent); } } };

当接收ALARM_EAKEUP时,执行startNavigating函数,当接收到ALARM_TIMEOUT广播时,执行hibernate函数。这两个函数很关键,下面看他们的实现:

  1. private void startNavigating(boolean singleShot) {  
  2.           
  3.         //...省略部分代码   
  4.               
  5.             if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,  
  6.                     interval, 00)) {  
  7.                 mStarted = false;  
  8.                 Log.e(TAG, "set_position_mode failed in startNavigating()");  
  9.                 return;  
  10.             }  
  11.             if (!native_start()) {  
  12.                 mStarted = false;  
  13.                 Log.e(TAG, "native_start failed in startNavigating()");  
  14.                 return;  
  15.             }  
  16.         //...省略部分代码   
  17.     }  
private void startNavigating(boolean singleShot) { //...省略部分代码 if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC, interval, 0, 0)) { mStarted = false; Log.e(TAG, "set_position_mode failed in startNavigating()"); return; } if (!native_start()) { mStarted = false; Log.e(TAG, "native_start failed in startNavigating()"); return; } //...省略部分代码 }

看到没有,这里调用了native_set_position_modenative_start方法,而这些方法正是我们之前在JNI适配层提到的注册的本地方法。同样的,hibernate函数调用了JNI提供的native_stop方法。我们再看GpsLocationProvider的内部私有函数:




可以看到所有这些本地方法,都是在JNI层注册的,GpsLocationProvider类是从JNI层到Framework层的通道。

下面回到LocationManagerService,分析如何获取最新的位置信息(Location),获取最新的location的函数是getLastKnownLocation,其实现如下:

  1. private Location _getLastKnownLocationLocked(String provider) {  
  2.         checkPermissionsSafe(provider);  
  3.   
  4.         LocationProviderInterface p = mProvidersByName.get(provider);  
  5.         if (p == null) {  
  6.             return null;  
  7.         }  
  8.   
  9.         if (!isAllowedBySettingsLocked(provider)) {  
  10.             return null;  
  11.         }  
  12.   
  13.         return mLastKnownLocation.get(provider);  
  14.     }  
private Location _getLastKnownLocationLocked(String provider) { checkPermissionsSafe(provider); LocationProviderInterface p = mProvidersByName.get(provider); if (p == null) { return null; } if (!isAllowedBySettingsLocked(provider)) { return null; } return mLastKnownLocation.get(provider); }

这里mLastKnownLocation类型为HashMap,所以mLastKnownLocation.get(provider)表示通过provider的名称在哈希字典中获取相应的location,那么这些location是什么时候被存入到哈希字典中的呢?

我们回到LocationManagerServicerun函数:

  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.     }  
public void run() { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); Looper.prepare(); mLocationHandler = new LocationWorkerHandler(); initialize(); Looper.loop(); }

这里对类型为LocationWorkerHandler的变量进行初始化,LocationWorkerHandler是在LocationManagerService的一个内部类,它继承自Handler类,HandlerAndroid系统用于应用程序内部通信的组件,内部通信指同个进程的主线程与其他线程间的通信,Handler通过MessageRunnable对象进行通信。我们继续看LocationWorkerHandler的实现:

  1. private class LocationWorkerHandler extends Handler {  
  2.   
  3.         @Override  
  4.         public void handleMessage(Message msg) {  
  5.             try {  
  6.                 if (msg.what == MESSAGE_LOCATION_CHANGED) {  
  7.                     // log("LocationWorkerHandler: MESSAGE_LOCATION_CHANGED!");   
  8.   
  9.                     synchronized (mLock) {  
  10.                         Location location = (Location) msg.obj;  
  11.                         String provider = location.getProvider();  
  12.                         boolean passive = (msg.arg1 == 1);  
  13.   
  14.                         if (!passive) {  
  15.                             // notify other providers of the new location   
  16.                             for (int i = mProviders.size() - 1; i >= 0; i--) {  
  17.                                 LocationProviderInterface p = mProviders.get(i);  
  18.                                 if (!provider.equals(p.getName())) {  
  19.                                     p.updateLocation(location);  
  20.                                 }  
  21.                             }  
  22.                         }  
  23.   
  24.                         if (isAllowedBySettingsLocked(provider)) {  
  25.                             handleLocationChangedLocked(location, passive);  
  26.                         }  
  27.                     }  
  28.                 } else if (msg.what == MESSAGE_PACKAGE_UPDATED) {  
  29.                     //...省略部分代码   
  30.                     }  
  31.                 }  
  32.             } catch (Exception e) {  
  33.                 // Log, don't crash!   
  34.                 Slog.e(TAG, "Exception in LocationWorkerHandler.handleMessage:", e);  
  35.             }  
  36.         }  
  37.     }  
private class LocationWorkerHandler extends Handler { @Override public void handleMessage(Message msg) { try { if (msg.what == MESSAGE_LOCATION_CHANGED) { // log("LocationWorkerHandler: MESSAGE_LOCATION_CHANGED!"); synchronized (mLock) { Location location = (Location) msg.obj; String provider = location.getProvider(); boolean passive = (msg.arg1 == 1); if (!passive) { // notify other providers of the new location for (int i = mProviders.size() - 1; i >= 0; i--) { LocationProviderInterface p = mProviders.get(i); if (!provider.equals(p.getName())) { p.updateLocation(location); } } } if (isAllowedBySettingsLocked(provider)) { handleLocationChangedLocked(location, passive); } } } else if (msg.what == MESSAGE_PACKAGE_UPDATED) { //...省略部分代码 } } } catch (Exception e) { // Log, don't crash! Slog.e(TAG, "Exception in LocationWorkerHandler.handleMessage:", e); } } }

这里重写Handle类的handleMessage方法,处理用Handle接收的Message对象消息。当接受到位置信息变化的消息MESSAGE_LOCATION_CHANGED时,调用p.updateLocationhandleLocationChangedLocked方法,其实现如下:

  1. private void handleLocationChangedLocked(Location location, boolean passive) {  
  2.        //...省略部分代码   
  3.   
  4.         // Update last known location for provider   
  5.         Location lastLocation = mLastKnownLocation.get(provider);  
  6.         if (lastLocation == null) {  
  7.             mLastKnownLocation.put(provider, new Location(location));  
  8.         } else {  
  9.             lastLocation.set(location);  
  10.         }  
  11.     //...省略部分代码   
  12. }  
private void handleLocationChangedLocked(Location location, boolean passive) { //...省略部分代码 // Update last known location for provider Location lastLocation = mLastKnownLocation.get(provider); if (lastLocation == null) { mLastKnownLocation.put(provider, new Location(location)); } else { lastLocation.set(location); } //...省略部分代码 }

可以看到是在handleLocationChangedLocked函数中实现对lastknownlocation的更新的,那么在LocationWorkerHandler类中处理的MESSAGE_LOCATION_CHANGED消息是谁发送出来的呢?答案是在LocationManagerService类的reportLocation函数中:

  1. public void reportLocation(Location location, boolean passive) {  
  2.         if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)  
  3.                 != PackageManager.PERMISSION_GRANTED) {  
  4.             throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission");  
  5.         }  
  6.   
  7.         mLocationHandler.removeMessages(MESSAGE_LOCATION_CHANGED, location);  
  8.         Message m = Message.obtain(mLocationHandler, MESSAGE_LOCATION_CHANGED, location);  
  9.         m.arg1 = (passive ? 1 : 0);  
  10.         mLocationHandler.sendMessageAtFrontOfQueue(m);  
  11.     }  
public void reportLocation(Location location, boolean passive) { if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission"); } mLocationHandler.removeMessages(MESSAGE_LOCATION_CHANGED, location); Message m = Message.obtain(mLocationHandler, MESSAGE_LOCATION_CHANGED, location); m.arg1 = (passive ? 1 : 0); mLocationHandler.sendMessageAtFrontOfQueue(m); }

此处构造了新的Message对象,然后发送到消息队列的首位置。在GpsLocationProvider类的reportLocation函数中,有这样一段代码:

  1. try     {  
  2.                 mLocationManager.reportLocation(mLocation, false);  
  3.             } catch (RemoteException e) {  
  4.                 Log.e(TAG, "RemoteException calling reportLocation");  
  5.            }  
try { mLocationManager.reportLocation(mLocation, false); } catch (RemoteException e) { Log.e(TAG, "RemoteException calling reportLocation"); }

所以实际是由GpsLocationProvider主动调用LocationManagerServicereportLocation方法,从而更新最新的位置信息。

实际上,GpsLocationoProviderreportLocation对应了硬件适配层中的GpsCallbacks结构体中的回调函数gps_location_callback

  1. /** Callback with location information. 向上层传递GPS位置信息 
  2.  *  Can only be called from a thread created by create_thread_cb. 
  3.  */  
  4. typedef void (* gps_location_callback)(GpsLocation* location);  
/** Callback with location information. 向上层传递GPS位置信息 * Can only be called from a thread created by create_thread_cb. */ typedef void (* gps_location_callback)(GpsLocation* location);


那么GpsLocationProvider中的reportLocation函数是如何与GpsCallbacksgps_location_callback挂钩的呢?我们回到JNI适配层的代码文件:

frameworks/base/services/jni/com_android_server_location_GpsLocationProvider.cpp

其中定义的GetGpsInterface函数:

  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.   
  6.     if (!sGpsInterface) {  
  7.         sGpsInterface = get_gps_interface();  
  8.         if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0) {  
  9.             sGpsInterface = NULL;  
  10.             return NULL;  
  11.         }  
  12.     }  
  13.     return sGpsInterface;  
  14. }  
static const GpsInterface* GetGpsInterface(JNIEnv* env, jobject obj) { // this must be set before calling into the HAL library if (!mCallbacksObj) mCallbacksObj = env->NewGlobalRef(obj); if (!sGpsInterface) { sGpsInterface = get_gps_interface(); if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0) { sGpsInterface = NULL; return NULL; } } return sGpsInterface; }

这里面的sGpsInterface->init(&sGpsCallbacks)调用了GpsInterfaceinit回调函数,即初始化GpsCallbacks结构体变量sGpsCallbackssGpsCallbacks定义如下:

  1. GpsCallbacks sGpsCallbacks = {  
  2.     sizeof(GpsCallbacks),  
  3.     location_callback,  
  4.     status_callback,  
  5.     sv_status_callback,  
  6.     nmea_callback,  
  7.     set_capabilities_callback,  
  8.     acquire_wakelock_callback,  
  9.     release_wakelock_callback,  
  10.     create_thread_callback,  
  11. };  
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, };

我们再次看GpsCallbacks的定义(其代码文件在硬件适配层的头文件gps.h中):

  1. typedef struct {  
  2.     size_t      size;  
  3.     gps_location_callback location_cb;  
  4.     gps_status_callback status_cb;  
  5.     gps_sv_status_callback sv_status_cb;  
  6.     gps_nmea_callback nmea_cb;  
  7.     gps_set_capabilities set_capabilities_cb;  
  8.     gps_acquire_wakelock acquire_wakelock_cb;  
  9.     gps_release_wakelock release_wakelock_cb;  
  10.     gps_create_thread create_thread_cb;  
  11. } GpsCallbacks;  
typedef struct { size_t size; gps_location_callback location_cb; gps_status_callback status_cb; gps_sv_status_callback sv_status_cb; gps_nmea_callback nmea_cb; gps_set_capabilities set_capabilities_cb; gps_acquire_wakelock acquire_wakelock_cb; gps_release_wakelock release_wakelock_cb; gps_create_thread create_thread_cb; } GpsCallbacks;

比较sGpsCallbacksGpsCallbacks,可以看到location_callbackgps_location_callback对应。再看location_callback函数的定义:

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

这里面利用JNI调用了Java语言的方法method_reportLocationmethod_reportLocation是一个jmethodID变量,表示一个由Java语言定义的方法。下面我们看method_reportLocation的赋值代码:

  1. static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {  
  2.     method_reportLocation = env->GetMethodID(clazz, "reportLocation""(IDDDFFFJ)V");  
  3.     //...省略部分代码   
  4. }  
static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz) { method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V"); //...省略部分代码 }

这里表示method_reportLocation指向Javaclazz里的方法reportLocation,那么这个Javaclazz是不是表示GpsLocationProvider呢?我们找到注册JNI方法的方法表:

  1. tatic JNINativeMethod sMethods[] = {  
  2.      /* name, signature, funcPtr */  
  3.     {"class_init_native""()V", (void *)android_location_GpsLocationProvider_class_init_native},  
  4.     //...省略部分代码   
  5. }  
tatic JNINativeMethod sMethods[] = { /* name, signature, funcPtr */ {"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native}, //...省略部分代码 }

这里说明_GpsLocationProvider_class_init_native对应的native方法名称是class_init_native,下面我们只要确定在Java中的某个类A调用了class_init_native方法,即可以说明A类的reportLocation函数是GpsCallbacks的回调函数。

我们回到GpsLocationProvider的代码文件:

frameworks/base/services/java/com/android/server/location/GpsLocationProvider.java

其中有一段代码:

  1. static { class_init_native(); }  
static { class_init_native(); }

说明是在GpsLocationProvider中调用了class_init_native方法,从而说明GpsLocationProviderreportLocation函数是GpsCallbacks的回调函数,即当Gps设备的位置信息发生变化时,它调用GpsLocationProvider的回调函数reportLocation,继而调用LocationManagerServicereportLocation函数,从而更新应用层的位置信息。


3 参考文章

基于androidGPS移植——主要结构体及接口介绍

androidGPS定位,定位城市称,经纬度


上一篇:Android开发:在Android源码下编译C文件
下一篇:(转载)static_cast,const_cast 用法