Android GPS 简介
GPS源碼簡介
1.? 源碼結(jié)構(gòu)
主要分為四部分,client ,service ,jni ,hardware ?
·????????client :
用于上層APP調(diào)用,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層只有一個(gè)文件,起到承上啟下的作用。上層承接Framework,下層調(diào)用HAL層具體硬件抽象實(shí)現(xiàn)。
frameworks/base/core/jni/android_location_GpsLocationProvider.cpp
·????????hardware:
HardwareAbstract Layer 硬件抽象層,
HAL層相當(dāng)于一個(gè)linux應(yīng)用程序接口,通過open,close等操作,操作硬件設(shè)備。
hardware/libhardware_legacy/gps/*(hardware 接口部分)。
?2. location服務(wù)
location服務(wù)是在SystemServer.java 中啟動(dòng)的,也就是系統(tǒng)啟動(dòng)之后,在SystemServer.java中,向ServiceManager中添加服務(wù):
try {
Slog.i(TAG, "LocationManager");
location = newLocationManagerService(context); //實(shí)例化一個(gè)LocationManagerService對(duì)象。
ServiceManager.addService(Context.LOCATION_SERVICE,location);
} catch (Throwable e) {
Slog.e(TAG, "Failure startingLocation Manager", e);
}
這時(shí)候服務(wù)就已經(jīng)啟動(dòng)了,但是啟動(dòng)后,還得判斷服務(wù)是否可用,在SystemServer.java中判斷如下:
final LocationManagerService locationF = location;
if (locationF != null) locationF.systemReady(); //調(diào)用LocationManagerService對(duì)象的
通過 locationF.systemReady()判斷是否可用,locationF.systemReady()的調(diào)用流程如下:
a、locationF.systemReady()啟動(dòng)了SystemServer.java的一個(gè)線程。
void systemReady() {
// we defer starting up theservice until the system is ready
Thread thread = newThread(null, this, "LocationManagerService");
thread.start();
}
b、在SystemServer.java的線程run函數(shù)中調(diào)用initialize()初始化。
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Looper.prepare();
mLocationHandler = newLocationWorkerHandler();
initialize();
Looper.loop();
}
c、初始化函數(shù)中,調(diào)用loadProviders() 函數(shù)Load providers。
privatevoid initialize()
{
......
loadProviders();
......
}
d、最后調(diào)用到GpsLocationProvider.isSupported()判斷是否支持GPS。
privatevoid _loadProvidersLocked() {
if (GpsLocationProvider.isSupported())
GpsLocationProvidergpsProvider = new GpsLocationProvider(mContext,this);
addProvider(gpsProvider);
}
updateProvidersLocked();
}
_loadProvidersLocked()主要完成三部分工作,判斷是否支持GPS,如果支持GPS,創(chuàng)建GpsLocationProvider對(duì)象,并加入到mProviders表中,最后調(diào)用updateProvidersLocked()更新GpsLocationProvider,打開或關(guān)閉GPS。
e、boolean isSupported 通過JNI方法,調(diào)用JNI層接口native_is_supported()判斷是否支持GPS。
GpsLocationProvider.java
publicstatic boolean isSupported() {
returnnative_is_supported(); // JNI調(diào)用方法,//native 是java關(guān)鍵字,表示它將由
JNI完成判斷GPS模塊是否存在
}
LocationManagerService服務(wù)啟動(dòng)相關(guān)先介紹到這里,下面介紹GPS另外一個(gè)重要的API:GpsLocationProvider。
3、GpsLocationProvider
GpsLocationProvider也是一個(gè)很重要的接口,是連接framework和JNI的紐帶,創(chuàng)建一個(gè)線程GpsLocationProviderThread來處理上層對(duì)底層的消息命令。
在LocationManagerService中,判斷GPS可用后,會(huì)創(chuàng)建一個(gè)GpsLocationProvider實(shí)例,并加入到mProviders表中。
GpsLocationProvidergpsProvider = new GpsLocationProvider(mContext,this);
addProvider(gpsProvider);
在LocationManagerService的updateProvidersLocked()中,會(huì)開啟或關(guān)閉GPS,調(diào)用GpsLocationProvider的enable方法開啟、調(diào)用disable方法關(guān)閉GPS。
GpsLocationProvider的構(gòu)造函數(shù)中,會(huì)創(chuàng)建一個(gè)線程GpsLocationProviderThread來處理上層對(duì)底層的消息命令:
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();
}
創(chuàng)建一個(gè)ProviderHandler的循環(huán)消息處理上層的消息。現(xiàn)在反過來看GpsLocationProvider的enable和disable方法:
publicvoid enable() {
synchronized(mHandler) {
sendMessage(ENABLE, 1, null);
}
}
publicvoid disable() {
synchronized(mHandler) {
sendMessage(ENABLE, 0, null);
}
}
從上可以看出,通過發(fā)送消息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等調(diào)用JNI層C++代碼方法,JNI層在com_android_server_location_GpsLocationProvider.cpp文件中。
3、LocationManager
LocationManager系統(tǒng)服務(wù)是位置服務(wù)的核心組件,它提供了一系列方法來處理與位置相關(guān)的問題,包括查詢上一個(gè)已知位置、注冊和注銷來自某個(gè)LocationProvider的周期性的位置更新、注冊和注銷接近某個(gè)坐標(biāo)時(shí)對(duì)一個(gè)已定義的Intent的觸發(fā)等。
應(yīng)用程序不能直接創(chuàng)建LocationManager實(shí)例對(duì)象,必須通過調(diào)用Context的getSystemService方法獲取,例如:
mLocationManager =
(LocationManager)mContext.getSystemService(Context.LOCATION_SERVICE);
往下跟蹤,如何通過Context的getSystemService獲取實(shí)例的:
privateLocationManager getLocationManager() {
synchronized(sSync) {
if(sLocationManager == null) {
IBinder b =ServiceManager.getService(LOCATION_SERVICE);
ILocationManagerservice =ILocationManager.Stub.asInterface(b);
sLocationManager= new LocationManager(service);
}
}
returnsLocationManager;
}
從這里可以看到,會(huì)創(chuàng)建一個(gè)LocationManager實(shí)例并返回,并且LocationManager通過IBinder和AIDL接口ILocationManager和LocationManagerService通信。
獲得LocationManager服務(wù)實(shí)例后,就可以通過調(diào)用它的API了,LocationManager一些API說明:
publicboolean addGpsStatusListener(GpsStatus.Listener listener):添加一個(gè)監(jiān)聽GPS狀態(tài)的監(jiān)聽器。
publicvoid addProximityAlert(double latitude, double longitude,
floatradius, long expiration, PendingIntent intent):添加一個(gè)臨近警告。
publicLocation getLastKnownLocation(String provider):根據(jù)LocationProvider獲取最近一次已知的location信息
publicvoid requestLocationUpdates(String provider,
longminTime, float minDistance, LocationListener listener)通過制定的LocationProvider周期性地獲取定位信息,并處罰listener對(duì)應(yīng)的觸發(fā)器。
還有其他的一些接口,就不一一介紹了。
4、JNI層
JNI層只有一個(gè)文件,起到承上啟下的作用。上層承接Framework,下層調(diào)用HAL層具體硬件抽象實(shí)現(xiàn)。
com_android_server_location_GpsLocationProvider.cpp。
JNI重要的回調(diào)函數(shù):
GpsCallbackssGpsCallbacks = {
sizeof(GpsCallbacks),
location_callback,
status_callback,
sv_status_callback,
nmea_callback,
set_capabilities_callback,
acquire_wakelock_callback,
release_wakelock_callback,
create_thread_callback,
};
這組回調(diào)函數(shù),在初始化的時(shí)候,會(huì)通過GpsInterface接口函數(shù)注冊到HAL層,在HAL層中。這組回上報(bào)。
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回調(diào)函數(shù)注冊到HAL層去。
5、HAL層
GpsInterface接口是gps模塊中最重要的數(shù)據(jù)結(jié)構(gòu),它是底層驅(qū)動(dòng)實(shí)現(xiàn)的接口,定義在gps.h中定義,然后根據(jù)具體的硬件,實(shí)現(xiàn)這組接口。在12007項(xiàng)目中,這組接口定義如下:
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()函數(shù)獲取這組GpsInterface接口。在上述的JNI層中,通過sGpsInterface->init(&sGpsCallbacks)來注冊JNI層的回調(diào)函數(shù),即通過loc_eng_init來注冊JNI層的回調(diào)函數(shù)。
loc_eng_init是一個(gè)非常重要的函數(shù),在該函數(shù)中,主要作用如下:
a、注冊sGpsCallbacks回調(diào)函數(shù)
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中創(chuàng)建一個(gè)RPC client通訊,獲取底層GPS數(shù)據(jù)
c、創(chuàng)建處理GPS數(shù)據(jù)的線程
loc_eng_data.deferred_action_thread= callbacks->create_thread_cb("loc_api", loc_eng_process_deferred_action, NULL);
loc_eng_process_deferred_action專門用來處理GPS數(shù)據(jù)。
進(jìn)入loc_eng_process_deferred_action中的loc_eng_process_loc_event處理函數(shù),分析一下position數(shù)據(jù)上報(bào)的流程:
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));
}
}
繼續(xù)往下跟蹤
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調(diào)用這個(gè)函數(shù)的時(shí)候相當(dāng)于真正調(diào)的是JNI注冊到hal的函數(shù),通過這種方式就實(shí)現(xiàn)了jni與hal的數(shù)據(jù)傳遞。loc_eng_data.location_cb就是JNI層的回調(diào)函數(shù)location_callback。
6、GPS數(shù)據(jù)上傳流程
應(yīng)用通過GPS服務(wù)的getLastKnownLocation方法獲得最近一次已知的Location信息,這Location信息是如何從底層往上傳遞而來的呢?下面以Location為例,分析從底層數(shù)據(jù)往上傳遞,一直到應(yīng)用通過getLastKnownLocation獲得最近信息的整個(gè)流程。
從上述HAL層的分析,數(shù)據(jù)通過loc_eng_data.location_cb(&location),也就是通過JNI層的回調(diào)函數(shù)location_callback將數(shù)據(jù)上報(bào)到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方法,將數(shù)據(jù)上報(bào)到GpsLocationProvider.reportLocation,完成了數(shù)據(jù)從C/C++層上報(bào)到Java層的過程。
分析GpsLocationProvider. reportLocation函數(shù):
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中,調(diào)用了成員變量mLocationManager的reportLocation方法。
mLocationManager是什么呢?我們來看GpsLocationProvider的構(gòu)造函數(shù)
publicGpsLocationProvider(Context context, ILocationManager locationManager) {
mContext = context;
mLocationManager = locationManager;
…
}
再看GpsLocationProvider創(chuàng)建實(shí)例的地方,在LocationManagerService類中創(chuàng)建實(shí)例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發(fā)了一條消息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中,到這里L(fēng)ocation信息上報(bào)流程基本結(jié)束了,再從應(yīng)用層看,LocationManager.getLastKnownLocation是如何獲得Location信息的。
public Location getLastKnownLocation(String provider) {
…
return mService.getLastKnownLocation(provider);
…
}
getLastKnownLocation調(diào)用LocationManager的成員變量mService的getLastKnownLocation方法,從Context的方法getSystemService獲取LocationManager實(shí)例可知,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中獲得,而通過上面數(shù)據(jù)上報(bào)的分析可知,Location信息最終也是上報(bào)到mLastKnownLocation表中,到此,Location信息從底層上報(bào),一直到應(yīng)用層獲得Location信息的流程分析完畢。
其流程圖如下:
???
總結(jié)
以上是生活随笔為你收集整理的Android GPS 简介的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Ghost 使用详解
- 下一篇: android gps底层,Androi