Android GPS 简介
GPS源碼簡介
1.? 源碼結構
主要分為四部分,client ,service ,jni ,hardware ?
·????????client :
用于上層APP調用,API包是android.location
/frameworks/base/location/* ?????
·????????service :
/frameworks/base/services/java/com/android/server/location/
/frameworks/base/services/java/com/android/server/LocationManagerService.java
·????????JNI:
JNI層只有一個文件,起到承上啟下的作用。上層承接Framework,下層調用HAL層具體硬件抽象實現。
frameworks/base/core/jni/android_location_GpsLocationProvider.cpp
·????????hardware:
HardwareAbstract Layer 硬件抽象層,
HAL層相當于一個linux應用程序接口,通過open,close等操作,操作硬件設備。
hardware/libhardware_legacy/gps/*(hardware 接口部分)。
?2. location服務
location服務是在SystemServer.java 中啟動的,也就是系統啟動之后,在SystemServer.java中,向ServiceManager中添加服務:
try {
Slog.i(TAG, "LocationManager");
location = newLocationManagerService(context); //實例化一個LocationManagerService對象。
ServiceManager.addService(Context.LOCATION_SERVICE,location);
} catch (Throwable e) {
Slog.e(TAG, "Failure startingLocation Manager", e);
}
這時候服務就已經啟動了,但是啟動后,還得判斷服務是否可用,在SystemServer.java中判斷如下:
final LocationManagerService locationF = location;
if (locationF != null) locationF.systemReady(); //調用LocationManagerService對象的
通過 locationF.systemReady()判斷是否可用,locationF.systemReady()的調用流程如下:
a、locationF.systemReady()啟動了SystemServer.java的一個線程。
void systemReady() {
// we defer starting up theservice until the system is ready
Thread thread = newThread(null, this, "LocationManagerService");
thread.start();
}
b、在SystemServer.java的線程run函數中調用initialize()初始化。
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Looper.prepare();
mLocationHandler = newLocationWorkerHandler();
initialize();
Looper.loop();
}
c、初始化函數中,調用loadProviders() 函數Load providers。
privatevoid initialize()
{
......
loadProviders();
......
}
d、最后調用到GpsLocationProvider.isSupported()判斷是否支持GPS。
privatevoid _loadProvidersLocked() {
if (GpsLocationProvider.isSupported())
GpsLocationProvidergpsProvider = new GpsLocationProvider(mContext,this);
addProvider(gpsProvider);
}
updateProvidersLocked();
}
_loadProvidersLocked()主要完成三部分工作,判斷是否支持GPS,如果支持GPS,創建GpsLocationProvider對象,并加入到mProviders表中,最后調用updateProvidersLocked()更新GpsLocationProvider,打開或關閉GPS。
e、boolean isSupported 通過JNI方法,調用JNI層接口native_is_supported()判斷是否支持GPS。
GpsLocationProvider.java
publicstatic boolean isSupported() {
returnnative_is_supported(); // JNI調用方法,//native 是java關鍵字,表示它將由
JNI完成判斷GPS模塊是否存在
}
LocationManagerService服務啟動相關先介紹到這里,下面介紹GPS另外一個重要的API:GpsLocationProvider。
3、GpsLocationProvider
GpsLocationProvider也是一個很重要的接口,是連接framework和JNI的紐帶,創建一個線程GpsLocationProviderThread來處理上層對底層的消息命令。
在LocationManagerService中,判斷GPS可用后,會創建一個GpsLocationProvider實例,并加入到mProviders表中。
GpsLocationProvidergpsProvider = new GpsLocationProvider(mContext,this);
addProvider(gpsProvider);
在LocationManagerService的updateProvidersLocked()中,會開啟或關閉GPS,調用GpsLocationProvider的enable方法開啟、調用disable方法關閉GPS。
GpsLocationProvider的構造函數中,會創建一個線程GpsLocationProviderThread來處理上層對底層的消息命令:
mThread = newGpsLocationProviderThread();
mThread.start();
在GpsLocationProviderThread的run中:
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
initialize();
Looper.prepare();
mHandler = new ProviderHandler();
// signal when we are initialized andready to go
mInitializedLatch.countDown();
Looper.loop();
}
創建一個ProviderHandler的循環消息處理上層的消息。現在反過來看GpsLocationProvider的enable和disable方法:
publicvoid enable() {
synchronized(mHandler) {
sendMessage(ENABLE, 1, null);
}
}
publicvoid disable() {
synchronized(mHandler) {
sendMessage(ENABLE, 0, null);
}
}
從上可以看出,通過發送消息ENABLE,在消息處理里面處理ENABLE消息
privatefinal class ProviderHandler extends Handler {
@Override
publicvoid handleMessage(Message msg) {
intmessage = msg.what;
switch(message) {
caseENABLE:
if(msg.arg1 == 1) {
handleEnable();
} else {
handleDisable();
}
break;
…
}
}
handleEnable和handleDisable最后通過native_init、native_stop等調用JNI層C++代碼方法,JNI層在com_android_server_location_GpsLocationProvider.cpp文件中。
3、LocationManager
LocationManager系統服務是位置服務的核心組件,它提供了一系列方法來處理與位置相關的問題,包括查詢上一個已知位置、注冊和注銷來自某個LocationProvider的周期性的位置更新、注冊和注銷接近某個坐標時對一個已定義的Intent的觸發等。
應用程序不能直接創建LocationManager實例對象,必須通過調用Context的getSystemService方法獲取,例如:
mLocationManager =
(LocationManager)mContext.getSystemService(Context.LOCATION_SERVICE);
往下跟蹤,如何通過Context的getSystemService獲取實例的:
privateLocationManager getLocationManager() {
synchronized(sSync) {
if(sLocationManager == null) {
IBinder b =ServiceManager.getService(LOCATION_SERVICE);
ILocationManagerservice =ILocationManager.Stub.asInterface(b);
sLocationManager= new LocationManager(service);
}
}
returnsLocationManager;
}
從這里可以看到,會創建一個LocationManager實例并返回,并且LocationManager通過IBinder和AIDL接口ILocationManager和LocationManagerService通信。
獲得LocationManager服務實例后,就可以通過調用它的API了,LocationManager一些API說明:
publicboolean addGpsStatusListener(GpsStatus.Listener listener):添加一個監聽GPS狀態的監聽器。
publicvoid addProximityAlert(double latitude, double longitude,
floatradius, long expiration, PendingIntent intent):添加一個臨近警告。
publicLocation getLastKnownLocation(String provider):根據LocationProvider獲取最近一次已知的location信息
publicvoid requestLocationUpdates(String provider,
longminTime, float minDistance, LocationListener listener)通過制定的LocationProvider周期性地獲取定位信息,并處罰listener對應的觸發器。
還有其他的一些接口,就不一一介紹了。
4、JNI層
JNI層只有一個文件,起到承上啟下的作用。上層承接Framework,下層調用HAL層具體硬件抽象實現。
com_android_server_location_GpsLocationProvider.cpp。
JNI重要的回調函數:
GpsCallbackssGpsCallbacks = {
sizeof(GpsCallbacks),
location_callback,
status_callback,
sv_status_callback,
nmea_callback,
set_capabilities_callback,
acquire_wakelock_callback,
release_wakelock_callback,
create_thread_callback,
};
這組回調函數,在初始化的時候,會通過GpsInterface接口函數注冊到HAL層,在HAL層中。這組回上報。
staticconst GpsInterface* GetGpsInterface(JNIEnv* env, jobject obj) {
// thismust 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;
returnNULL;
}
returnsGpsInterface;
}
其中sGpsInterface->init(&sGpsCallbacks)將sGpsCallbacks回調函數注冊到HAL層去。
5、HAL層
GpsInterface接口是gps模塊中最重要的數據結構,它是底層驅動實現的接口,定義在gps.h中定義,然后根據具體的硬件,實現這組接口。在12007項目中,這組接口定義如下:
staticconst 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,
};
在JNI層,利用static const GpsInterface*get_gps_interface()函數獲取這組GpsInterface接口。在上述的JNI層中,通過sGpsInterface->init(&sGpsCallbacks)來注冊JNI層的回調函數,即通過loc_eng_init來注冊JNI層的回調函數。
loc_eng_init是一個非常重要的函數,在該函數中,主要作用如下:
a、注冊sGpsCallbacks回調函數
loc_eng_data.location_cb= callbacks->location_cb;
loc_eng_data.sv_status_cb= callbacks->sv_status_cb;
loc_eng_data.status_cb= callbacks->status_cb;
loc_eng_data.nmea_cb= callbacks->nmea_cb;
loc_eng_data.acquire_wakelock_cb= callbacks->acquire_wakelock_cb;
loc_eng_data.release_wakelock_cb =callbacks->release_wakelock_cb;
b、在loc_api_glue_init中創建一個RPC client通訊,獲取底層GPS數據
c、創建處理GPS數據的線程
loc_eng_data.deferred_action_thread= callbacks->create_thread_cb("loc_api", loc_eng_process_deferred_action, NULL);
loc_eng_process_deferred_action專門用來處理GPS數據。
進入loc_eng_process_deferred_action中的loc_eng_process_loc_event處理函數,分析一下position數據上報的流程:
staticvoid loc_eng_process_loc_event (rpc_loc_event_mask_type loc_event,
rpc_loc_event_payload_u_type*loc_event_payload)
{
if(loc_event & RPC_LOC_EVENT_PARSED_POSITION_REPORT)
{
loc_eng_report_position(&(loc_event_payload->rpc_loc_event_payload_u_type_u.parsed_location_report));
}
}
繼續往下跟蹤
staticvoid loc_eng_report_position (const rpc_loc_parsed_position_s_type*location_report_ptr)
{
loc_eng_data.location_cb (&location);
}
loc_eng_data.location_cb調用這個函數的時候相當于真正調的是JNI注冊到hal的函數,通過這種方式就實現了jni與hal的數據傳遞。loc_eng_data.location_cb就是JNI層的回調函數location_callback。
6、GPS數據上傳流程
應用通過GPS服務的getLastKnownLocation方法獲得最近一次已知的Location信息,這Location信息是如何從底層往上傳遞而來的呢?下面以Location為例,分析從底層數據往上傳遞,一直到應用通過getLastKnownLocation獲得最近信息的整個流程。
從上述HAL層的分析,數據通過loc_eng_data.location_cb(&location),也就是通過JNI層的回調函數location_callback將數據上報到JNI層,看一下JNI層location_callback具體代碼:
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初始化語句:
static voidandroid_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclassclazz){
method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
}
從中可以看出,通過JNI方法,將數據上報到GpsLocationProvider.reportLocation,完成了數據從C/C++層上報到Java層的過程。
分析GpsLocationProvider. reportLocation函數:
privatevoid reportLocation(int flags, double latitude, double longitude, doublealtitude,
floatspeed, float bearing, float accuracy, long timestamp){
try {
mLocationManager. reportLocation(mLocation, false);
catch (RemoteException e) {
Log.e(TAG, "RemoteException callingreportLocation");
}
}
在GpsLocationProvider. reportLocation中,調用了成員變量mLocationManager的reportLocation方法。
mLocationManager是什么呢?我們來看GpsLocationProvider的構造函數
publicGpsLocationProvider(Context context, ILocationManager locationManager) {
mContext = context;
mLocationManager = locationManager;
…
}
再看GpsLocationProvider創建實例的地方,在LocationManagerService類中創建實例GpsLocationProvider:
private void _loadProvidersLocked() {
if (GpsLocationProvider.isSupported())
GpsLocationProvider gpsProvider =new GpsLocationProvider(mContext,this);
addProvider(gpsProvider);
}
updateProvidersLocked();
}
可以看出,GpsLocationProvider中的mLocationManager是LocationManagerService的引用,所以
mLocationManager的reportLocation方法是LocationManagerService中reportLocation方法,具體定義如下:
publicvoid reportLocation(Location location, boolean passive) {
mLocationHandler.removeMessages(MESSAGE_LOCATION_CHANGED,location);
Message m = Message.obtain(mLocationHandler, MESSAGE_LOCATION_CHANGED, location);
m.arg1 = (passive ? 1 : 0);
mLocationHandler.sendMessageAtFrontOfQueue(m);
}
向mLocationHandler發了一條消息MESSAGE_LOCATION_CHANGED,mLocationHandler處理消息如下:
privateclass LocationWorkerHandler extends Handler {
@Override
publicvoid handleMessage(Message msg) {
try {
if(msg.what == MESSAGE_LOCATION_CHANGED) {
…
handleLocationChangedLocked(location, passive);
}
lastLocation = mLastKnownLocation.get(provider);
if (lastLocation == null) {
mLastKnownLocation.put(provider, new Location(location));
} else {
lastLocation.set(location);
}
}
最終將Location信息添加到mLastKnownLocation中,到這里Location信息上報流程基本結束了,再從應用層看,LocationManager.getLastKnownLocation是如何獲得Location信息的。
public Location getLastKnownLocation(String provider) {
…
return mService.getLastKnownLocation(provider);
…
}
getLastKnownLocation調用LocationManager的成員變量mService的getLastKnownLocation方法,從Context的方法getSystemService獲取LocationManager實例可知,mService是LocationManagerService的引用,所以通過LocationManagerService的getLastKnownLocation方法獲得Location信息:
public Location getLastKnownLocation(String provider) {
Location loc = _getLastKnownLocationLocked(provider);
return loc
}
private Location _getLastKnownLocationLocked(String provider) {
Location loc = mLastKnownLocation.get(provider);
return loc
}
Location信息最終是從mLastKnownLocation中獲得,而通過上面數據上報的分析可知,Location信息最終也是上報到mLastKnownLocation表中,到此,Location信息從底層上報,一直到應用層獲得Location信息的流程分析完畢。
其流程圖如下:
???
總結
以上是生活随笔為你收集整理的Android GPS 简介的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Ghost 使用详解
- 下一篇: 华为笔记本触控板手势操作_如何在笔记本电