因爲各類緣由,老師但願我學習Android系統源碼以應對可能參與的項目。我只好深刻曹營,刺探軍情了。java
定位服務是手機上最經常使用的功能之一,聽說也是相對比較簡單的服務,因此從這裏入手。其餘系統服務的架構都是相似的。明白其中一個以後,再去理解其餘的會容易得多。下面以 Android 源碼爲基礎,大體分析了 Android 系統中定位服務的架構和實現。版本是6.0.1。android
一. 應用層:
1.在App中調用位置服務git
在Android App中使用定位服務,要先向系統請求一個LocationManager實例,
LocationManager mLocationManager = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE); api
而後用Criteria對其進行設置,獲取一個provider,provider有3種基本定位類型 network/gps/passive
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
...
String provider = mLocationManager.getBestProvider(criteria, true);網絡
(1)LocationManager利用provider直接獲取一個最新的位置信息
Location location = mLocationManager.getLastKnownLocation(provider);架構
(2)使用事件綁定的方式,獲取更新的位置信息
LocationListener{
...
public void onLocationChanged(Location location)
}框架
二.框架層
2.LocationManager類的實現(/frameworks/base/location/java/android/location/LocationManager.java)
其代碼的主要做用是訪問系統位置服務LocationManagerService
關鍵成員
private final ILocationManager mService;ide
構造器
public LocationManager(Context context, ILocationManager service);
ILocationManager與系統服務通訊的接口函數
mService=Service;學習
如getProviders方法,實際是經過mService成員請求系統服務響應這個方法
public List<String> getProviders(boolean enabledOnly) {
...
return mService.getProviders(null, enabledOnly);
}
3.接口定義(/frameworks/base/location/java/android/location/ILocationManager.aidl)
經過aidl定義通訊接口,與系統位置服務進行進程間通訊icp(涉及binder)
4.LocationManagerService的實現(/frameworks/base/services/core/java/com/android/server/LocationManagerService.java)
系統位置服務的實現,包括實現LocationManager調用的接口
如
public List<String> getProviders(Criteria criteria, boolean enabledOnly)
public Location getLastLocation(LocationRequest request, String packageName)
...
在LocationManagerService中主要是有兩種定位方式,一種經過網絡,一種經過GPS模塊。經過GPS模塊定位的是GpsLocationProvider。
5.GpsLocationProvider(frameworks/base/services/core/java/com/android/server/location/GpsLocationProvider.java)
核心的涉及定位的方法是native的,經過JNI與HAL層C++語言函數交互
如這個注入一條位置信息的函數,接下來主要以他爲線索。
private native void native_inject_location(double latitude, double longitude, float accuracy);
3、硬件抽象層(HAL)
6.GpsLocationProvider 本地方法在HAL層的實現(/frameworks/base/services/core/jni/com_android_server_location_GpsLocationProvider.cpp)
#include "hardware/hardware.h"
#include "hardware/gps.h" //這裏的hardware目錄爲/hardware/libhardware/include/hardware/
...
上面第5點中native_inject_location方法對應的實現
static void android_location_GpsLocationProvider_inject_location(JNIEnv* /* env */,
jobject /* obj */, jdouble latitude, jdouble longitude, jfloat accuracy)
{
if (sGpsInterface)
sGpsInterface->inject_location(latitude, longitude, accuracy);
}
能夠看出這裏是經過sGpsInterface調用下一層函數去實現,他是一個GpsInterface結構體指針,
static const GpsInterface* sGpsInterface = NULL;
GpsInterface結構體定義在gps.h中
結構體包含函數指針,則sGpsInterface引用的實例包含函數的具體實現
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;
//在這裏得到了device提供的具體的sGpsInterface
sGpsInterface = gps_device->get_gps_interface(gps_device);
}
}
7.上面提到的gps.h(/hardware/libhardware/include/hardware/gps.h)
GpsInterface的定義
typedef struct {
...
/** 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);
...
} GpsInterface;
4、高通的一個實現
硬件廠商主要的工做室引用gps.h, 實現一個gps.c,把GpsInterface等內容實現了。這裏分析一下高通的一個實現。
8.gps.c(/hardware/qcom/gps/loc_api/libloc_api_50001/gps.c)
#include <hardware/gps.h>
...
extern const GpsInterface* get_gps_interface(); //外部函數
const GpsInterface* gps__get_gps_interface(struct gps_device_t* dev)
{
return get_gps_interface();
//在高通的實現中,第6點中的gps_device->get_gps_interface()調用的函數來自於此,此處
//返回的函數指針是一個外部函數,該外部函數實際在9.2中實現
}
...
//dev結構體
struct gps_device_t *dev = (struct gps_device_t *) malloc(sizeof(struct gps_device_t));
...
//給dev結構體get_gps_interface的函數指針指向前面高通實現的函數。
dev->get_gps_interface = gps__get_gps_interface;
9.loc.cpp(/hardware/qcom/gps/loc_api/libloc_api_50001/loc.cpp)
9.1
//這裏定義的靜態函數,供同一個文件裏的sLocEngInterface使用
static int loc_init(GpsCallbacks* callbacks);
static int loc_start();
static int loc_inject_time(GpsUtcTime time, int64_t timeReference, int uncertainty);
static int loc_inject_location(double latitude, double longitude, float accuracy);
...
//在gps.h中的GpsInterface,在這裏被實現成了sLocEngInterface
static const GpsInterface sLocEngInterface =
{
sizeof(GpsInterface),
loc_init,
loc_start,
loc_inject_time,
loc_inject_location,
...
};
9.2
// for gps.c
extern "C" const GpsInterface* get_gps_interface(){
...
}
9.3
這個文件裏的靜態函數的具體實現
static int loc_inject_location(double latitude, double longitude, float accuracy)
{
ENTRY_LOG();
int ret_val = 0;
ret_val = loc_eng_inject_location(loc_afw_data, latitude, longitude, accuracy);
//這裏又是依靠調用其它函數,還要繼續深挖到 loc_eng,在第10點
EXIT_LOG(%d, ret_val);
return ret_val;
}
10.loc_eng.cpp(/hardware/qcom/gps/loc_api/libloc_api_50001/loc_eng.cpp)
int loc_eng_inject_location(loc_eng_data_s_type &loc_eng_data, double latitude,
double longitude, float accuracy)
{
ENTRY_LOG_CALLFLOW();
INIT_CHECK(loc_eng_data.adapter, return -1);
LocEngAdapter* adapter = loc_eng_data.adapter;
if(adapter->mSupportsPositionInjection)
{
adapter->sendMsg(new LocEngInjectLocation(adapter, latitude, longitude,
accuracy));
//這裏發出了消息
}
EXIT_LOG(%d, 0);
return 0;
}
再往下就得是Linux kernel裏面GPS模塊的寫的驅動程序了,應該經過UART,傳送基本的數據和控制命令,我就沒去看了。。。
第一次看Android源碼,簡單分析,水平有限,若有錯漏,還請包涵。