Location Service 分析

  因爲各類緣由,老師但願我學習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源碼,簡單分析,水平有限,若有錯漏,還請包涵。

相關文章
相關標籤/搜索