android系统学习笔记十一
Gps??(global???Position??System?全球定位系統)和定位部分
除此之外還有利用基站(cell)定位的AGPS等設備
?定們系列統的基本架構
?主要數據來源有兩個:?GPS定位和network定位(基于cell和wifi熱點的定位)
定位部分的結構如圖
??定位系統的驅動層
?Network定位的底層驅動和適配層實際上就是RIL和wifi框架的組成部分
?Cell定位就是利用基站的cellID以及LAC實現
?Wifi則是利用熱點的相關信息?如名字?mac地址?ip地址實現
?GPS?設備分為硬GPS?和軟GPS?
???硬GPS上電就可以直接輸出NMEA?數據
???軟GPS需要主控芯片控制其運行狀態,需要主控方進行計算才能得到NMEA數據
?GPS本地實現
GPS的本地實現部分主要是GPS適配層,頭文件的路徑為:\hardware\libhardware\include\hardware
該目錄下的gps.h提供了JNI層調用的接口,該文件定義的常量,包括位置模式、狀態值、定位標志、幫助數據
//定義了標準GPS接口的結構體
typedef?struct?{
????/**?set?to?sizeof(GpsInterface)?*/
????size_t??????????size;
????/**
?????*?Opens?the?interface?and?provides?the?callback?routines
?????*?to?the?implemenation?of?this?interface.
????????初始化GPS,設置回調函數
?????*/
????int???(*init)(?GpsCallbacks*?callbacks?);
/**?Starts?navigating.?*/?
//開始導航
????int???(*start)(?void?);
/**?Stops?navigating.?*/
//停止導航
????int???(*stop)(?void?);
/**?Closes?the?interface.?*/
//關閉接口
????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);
????/**
?????*?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的定位信息
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.?*/
?????//以WGS84坐標系統表示的高度信息
????double??????????altitude;
/**?Represents?speed?in?meters?per?second.?*/
//速度??m/s
????float???????????speed;
/**?Represents?heading?in?degrees.?*/
//表示方向
????float???????????bearing;
/**?Represents?expected?accuracy?in?meters.?*/
//表示精度
????float???????????accuracy;
/**?Timestamp?for?the?location?fix.?*/
//表示時間戮
????GpsUtcTime??????timestamp;
}?GpsLocation;
當上層調用:GpsInterface.init時,會調用一個gpscallbacks結構指針,注冊到適配層
//位置信息的回調函數
typedef?void?(*?gps_location_callback)(GpsLocation*?location);
//?狀態信息的回調函數
typedef?void?(*?gps_status_callback)(GpsStatus*?status);
//SV狀態信息的回調函數
typedef?void?(*?gps_sv_status_callback)(GpsSvStatus*?sv_info);
??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的部分源代碼路徑為:\hardware\qcom\gps
GPS組件的目標文件是;libhardware_legacy.so
Gps_qemu.c文件是基于模擬器環境的GPS適配層,在編寫特定的GPS?適配層時,可以以gps_quemu.c中的大部分處理流程作為基礎進行改寫,它實現了一套NMEA解析機制,以及gps.h中的gpsInterface接口,
gpsInterface?接口比較簡單,包括啟動/停止和上報頻率等接口,
NEMA解析是核心,是基于文本塊的算法
因為是模擬,所以NMEA數據需要從一個socket接口gps_fd傳輸進來.??在獨立線程中進行解析
NMEA數據最終會解析成gps.h中定義的gpsLocation的格式
GPS?部分JNI的實現
代碼的路徑為:\frameworks\base\services\jni\com_android_server_location_GpsLocationProvider.cpp
JNI層直接與GPS驅動層打交道,它訪問適配層定義的GpaInterface?實現自已的gpscallbacks供GPS適配層調用
部分代碼如下:
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,
};
JNI實現了一個native_wait_for_event函數,上層如果需要獲得消息,則在獨立線程中調用此函數阻塞
如果上層有NMEA解析完成并回調,通過線程同步機制,使等待的native_wait_for_event的線程取得上報數據,完成一次數據上報
Xtra是部分增強型GPS的機制,可以提前從網上下載數據
定位系統的java實現
代碼路徑為:\frameworks\base\location\java\android\location
ILocationManager是android?定們系統的核心
LocationServiceManager是定位系統的服務器端,它在目錄:\frameworks\base\services\java\com\android\server下
LocationProviderProxy?mNetworkLocationProvider;
?????LocationProviderInterface?mGpsLocationProvider;
**************************************************************
2.3中的變化
**************************************************************
\frameworks\base\services\java\com\android\server\location目錄下的GpsLocationProvider.java它直接繼承
LocationProviderInterface(在2。3之前可能是LocationProviderImpl),?它提供了底層的控制接口,同時開啟一個gpsEventThread通過輪詢native_wait_for_event來取得底層上報的數據
App發出定位申請,啟動定位服務線程,此線程會在APP?framwork中調用location?provider
通過被native方法調用到JNI中,?JNI獲得gpsInterface并傳給接口一個回調函數的實現
gpsInterface就是HAL層最主要的實現
?
上層實現的思路
1、獲取GPS的Location?Provider。
?2、將此Provider傳入到requestLocationUpdates()方法,讓Android系統獲知搜索位置方式。
?3、創建實現了GpsStatus.Listener接口的對象,重寫onGpsStatusChanged()方法,向LocationManager添加次監聽器,檢測衛星狀態。(可選步驟)
Android?GPS?架構分析
Framework?層:?
?代碼路徑為:
1?\frameworks\base\location\java\android\location
?供api調用
?2?frameworks\base\location\java\com\android\internal\location
?這個目錄是framework對location服務的內部實現
3?\frameworks\base\services\java\com\android\server
??這是location服務對內部實現的一個封裝
JNI層:
?代碼路徑:
在2。2版本中
frameworks/base/core/jni/android_location_GpsLocationProvider.cpp
在2.3版式本中
\frameworks\base\services\jni\com_android_server_location_GpsLocationProvider.cpp
上層承接freanwork,下層調用HAL
HAL硬件抽象層:?
代碼路徑
?2.3?中
?\hardware\libhardware\include\hardware
/framework/base/services/jni/com_android_server_location_GpsLocationProvider.cpp
?相當于linux應用程序的一個接口,直接操作硬件設備
底層幾個重要和數據結構
1?gpsInterface?是最重要的數據結構,它是底層實現的接口,如果要porting到自已的板子上,就要實現這這些接口,
??該接口的定義在gps.h中,模擬器實現在gps_qemu.c中
?typedef?struct?{???
????size_t??????????size;????
????int???(*init)(?GpsCallbacks*?callbacks?);
????????int???(*start)(?void?);
????????int???(*stop)(?void?);
????void??(*cleanup)(?void?);
????int???(*inject_time)(GpsUtcTime?time,?int64_t?timeReference,
?????????????????????????int?uncertainty);
????int??(*inject_location)(double?latitude,?double?longitude,?float?accuracy);??
????void??(*delete_aiding_data)(GpsAidingData?flags);???
????int???(*set_position_mode)(GpsPositionMode?mode,?GpsPositionRecurrence?recurrence,
????????????uint32_t?min_interval,?uint32_t?preferred_accuracy,?uint32_t?preferred_time);
????????const?void*?(*get_extension)(const?char*?name);
}?GpsInterface;
2?gpscallbacks回調函數結構體,定義同上,實現在com_android_server_android_location_GpsLocationProvider.cpp中
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;
????//以下幾個回調函數是在2.3以后添加的回調函數
????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;
3?Gpslocation表示loaction數據信息?2.3比2.2多了個size屬性
typedef?struct?{
????//2.3之后添加
??????size_t??????????size;?
????uint16_t????????flags;????
????double??????????latitude;??
????double??????????longitude;???
????double??????????altitude;?
????float???????????speed;???
????float???????????bearing;??
????float???????????accuracy;???
????GpsUtcTime??????timestamp;
}?GpsLocation;
Gps的定位服務(locationManager)的啟動過程
LocationManager這項服務是systemServer.java?來啟動,也就是在系統啟動之后就啟動
systemServer.java?[framework/base/services/java/com/android/server]?
public?static?final?void?init2()?{
Slog.i(TAG,?"Entered?the?Android?system?server!");?
Thread?thr?=?new?ServerThread();?
thr.setName("android.server.ServerThread");?
thr.start();?
}
在ServerThread線程的run函數中LocationManager服務的代碼段如下:?
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);?
}
在run函數的后半部分,是服務對系統的反饋,就是systemReady()函數。?LocationManager服務的反饋函數如下:
final?LocationManagerService?locationF?=?location;
其中的locationF?是LocationManagerService的final類型,就是一旦賦值,不能更改。
if?(locationF?!=?null)?locationF.systemReady();
LocationManagerService代碼路徑如下:\frameworks\base\services\java\com\android\server
構造器如下:
???public?LocationManagerService(Context?context)?{
????????super();
????????mContext?=?context;
????????Resources?resources?=?context.getResources();
????????mNetworkLocationProviderPackageName?=?resources.getString(
????????????????com.android.internal.R.string.config_networkLocationProvider);
????????mGeocodeProviderPackageName?=?resources.getString(
????????????????com.android.internal.R.string.config_geocodeProvider);
????????mPackageMonitor.register(context,?true);
????????if?(LOCAL_LOGV)?{
????????????Slog.v(TAG,?"Constructed?LocationManager?Service");
????????}
????}
void?systemReady()?{
????????//?we?defer?starting?up?the?service?until?the?system?is?ready?
????????Thread?thread?=?new?Thread(null,?this,?"LocationManagerService");
????????thread.start();
????}
?在run函數中,又調用了initialize?函數
?public?void?run()
????{
????????Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
????????Looper.prepare();
????????mLocationHandler?=?new?LocationWorkerHandler();
????????initialize();//************************
????????Looper.loop();
????}
??private?void?initialize()?{
????????//?Create?a?wake?lock,?needs?to?be?done?before?calling?loadProviders()?below
????????PowerManager?powerManager?=?(PowerManager)?mContext.getSystemService(Context.POWER_SERVICE);
????????mWakeLock?=?powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,?WAKELOCK_KEY);
????????//?Load?providers
????????//重要方法
????????loadProviders();
????????//?Register?for?Network?(Wifi?or?Mobile)?updates
????????IntentFilter?intentFilter?=?new?IntentFilter();
????????intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
????????//?Register?for?Package?Manager?updates
????????intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
????????intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
????????intentFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
????????mContext.registerReceiver(mBroadcastReceiver,?intentFilter);
????????IntentFilter?sdFilter?=?new?IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
????????mContext.registerReceiver(mBroadcastReceiver,?sdFilter);
????????//?listen?for?settings?changes
????????ContentResolver?resolver?=?mContext.getContentResolver();
????????Cursor?settingsCursor?=?resolver.query(Settings.Secure.CONTENT_URI,?null,
????????????????"("?+?Settings.System.NAME?+?"=?)",
????????????????new?String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
????????????????null);
????????mSettings?=?new?ContentQueryMap(settingsCursor,?Settings.System.NAME,?true,?mLocationHandler);
????????SettingsObserver?settingsObserver?=?new?SettingsObserver();
????????mSettings.addObserver(settingsObserver);
????}
初始化函數中,最重要的便是?loadProviders()函數。
private?void?loadProviders()?{
????????synchronized?(mLock)?{?
????????????if?(sProvidersLoaded)?{?
????????????????return;?
????????????}?
????????????//?Load?providers
????????????loadProvidersLocked();?
????????????sProvidersLoaded?=?true;?
????????}?
????}
?
?private?void?loadProvidersLocked()?{
????????try?{
????????????_loadProvidersLocked();
????????}?catch?(Exception?e)?{
????????????Slog.e(TAG,?"Exception?loading?providers:",?e);
????????}
}
_loadProvidersLocked函數,?
?private?void?_loadProvidersLocked()?{
????????//?Attempt?to?load?"real"?providers?first
????????//取得GPS的接口
????????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();
????}
GpsLocationProvider.isSupported()得到了HAL層的GPS接口gpsInterface
調用到gps.cpp[hardware/libhardware_legacy/gps]中的gps_get_interface()
GpsLocationProvider的路徑為:\frameworks\base\services\java\com\android\server\location
?部分代碼如下:
???public?static?boolean?isSupported()?{
????????//調用的是本地方法
????????return?native_is_supported();
????}
函數中只有一句話,?這調用了native方法,既Jni層定義的方法。native_is_supported對應在
framework/base/services/jni/com_android_server_location_GpsLocationProvider.cpp文件中的android_location_GpsLocationProvider_is_supported方法。
?部分代碼如下;
static?jboolean?android_location_GpsLocationProvider_is_supported(JNIEnv*?env,?jclass?clazz)?{
????return?(sGpsInterface?!=?NULL?||?get_gps_interface()?!=?NULL);
}
get_gps_interface()的具體代碼如下:
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;
}
?get_gps_interface去打開模組,之后打開設備,然后通過設備區調用HAL層中的get_gps_interface(gps_device)
在gps.c(代碼路徑為:\hardware\qcom\gps\loc_api\libloc_api)中實現的gps__get_gps_interfacey調用了loc_eng.cpp
gps.c部分代碼如下:
const?GpsInterface*?gps__get_gps_interface(struct?gps_device_t*?dev)
{
????return?get_gps_interface();
}
loc_eng.cpp的部分代碼如下:
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,
};
經過以的操作我們就獲得了GPS的接口,?在locationManagerService.java中,如果找到了硬件,并取得了接口后,接著執行下一句
?GpsLocationProvider?gpsProvider?=?new?GpsLocationProvider(mContext,?this);
GpsLocationProvider的代碼路徑為:frameworks\base\services\java\com\android\server\location
?public?GpsLocationProvider(Context?context,?ILocationManager?locationManager)?{
????????mContext?=?context;
????????//mLocationManager就是第二個參數.也就是locationManagerService
????????mLocationManager?=?locationManager;
????????mNIHandler?=?new?GpsNetInitiatedHandler(context);
????????mLocation.setExtras(mLocationExtras);
....................
}
_loadProvidersLocked函數,在構造完成后,將其add到全局變量ArrayList<LocationProviderInterface>?mProviders中,備以后調用.
接著啟動了兩個線程,但是可惜的是這兩個服務都無法啟動,因為他們是通過配置文件conifg.xml?得到服務的名字,然后啟動服務的。但是在這個配置文件中,兩個服務的名字都是null
配置文件的路徑為;framework/base/core/res/res/values
部分代碼如下:
<!--?Component?name?of?the?service?providing?network?location?support.?-->
????<string?name="config_networkLocationProvider">@null</string>
????<!--?Component?name?of?the?service?providing?geocoder?API?support.?-->
????<string?name="config_geocodeProvider">@null</string>
這就是為什么在調用getFromLocationName和?getFromLocation時會提示service?not?available,2.2就存在的bug
在_loadProvidersLocked函數的最后調用的是updateProvidersLocked();也在這個類中
部分代碼如下:
?private?void?updateProvidersLocked()?{
????????boolean?changesMade?=?false;
????????for?(int?i?=?mProviders.size()?-?1;?i?>=?0;?i--)?{
????????????LocationProviderInterface?p?=?mProviders.get(i);
????????????boolean?isEnabled?=?p.isEnabled();
????????????String?name?=?p.getName();
????????????boolean?shouldBeEnabled?=?isAllowedBySettingsLocked(name);
????????????if?(isEnabled?&&?!shouldBeEnabled)?{
????????????????updateProviderListenersLocked(name,?false);
????????????????changesMade?=?true;
????????????}?else?if?(!isEnabled?&&?shouldBeEnabled)?{
????????????????updateProviderListenersLocked(name,?true);
????????????????changesMade?=?true;
????????????}
????????}
????????if?(changesMade)?{
????????????mContext.sendBroadcast(new?Intent(LocationManager.PROVIDERS_CHANGED_ACTION));
????????}
????}
在mProviders里面應該存在一個gpsProvider?和PassiveProvider,而gpsProvider是未被enable的。而passiveProvider是enable的。
這邊我們對gpsProvider進行討論,他執行的是updateProviderListenersLocked(name,true)?然后當有發生改變,就是changesMade=true時,它發送了廣播,內容是告訴大家LocationManager發生了變化,讓需要的接收者自己接收。?
?updateProviderListenersLocked(name,?false)函數的部分代碼如下:
????private?void?updateProviderListenersLocked(String?provider,?boolean?enabled)?{
????????int?listeners?=?0;
????????LocationProviderInterface?p?=?mProvidersByName.get(provider);
????????if?(p?==?null)?{
????????????return;
????????}
????????ArrayList<Receiver>?deadReceivers?=?null;
????????
????????ArrayList<UpdateRecord>?records?=?mRecordsByProvider.get(provider);
????????if?(records?!=?null)?{
????????????final?int?N?=?records.size();
????????????for?(int?i=0;?i<N;?i++)?{
????????????????UpdateRecord?record?=?records.get(i);
????????????????//?Sends?a?notification?message?to?the?receiver
????????????????if?(!record.mReceiver.callProviderEnabledLocked(provider,?enabled))?{
????????????????????if?(deadReceivers?==?null)?{
????????????????????????deadReceivers?=?new?ArrayList<Receiver>();
????????????????????}
????????????????????deadReceivers.add(record.mReceiver);
????????????????}
????????????????listeners++;
????????????}
????????}
????????if?(deadReceivers?!=?null)?{
????????????for?(int?i=deadReceivers.size()-1;?i>=0;?i--)?{
????????????????removeUpdatesLocked(deadReceivers.get(i));
????????????}
????????}
????????//如果為真則啟動gas
????????if?(enabled)?{
????????????p.enable();
????????????if?(listeners?>?0)?{
????????????????p.setMinTime(getMinTimeLocked(provider),?mTmpWorkSource);
????????????????p.enableLocationTracking(true);
????????????}
????????}?else?{
????????????p.enableLocationTracking(false);
????????????p.disable();
????????}
????}
在if(enable)中,如果enable?為真,則啟動GPS,調用p.enable()方法,該方法的實現是在
GpsLocationProvider.java類中他繼承了LocationProviderInterface
代碼路徑為:\frameworks\base\services\java\com\android\server\location
部分代碼如下:
???public?void?enable()?{
????????synchronized?(mHandler)?{
????????????sendMessage(ENABLE,?1,?null);
????????}
????}
?
???//每次進入此消息,就是清除之前所有消息發送消息交給handlerMassage處理
??private?void?sendMessage(int?message,?int?arg,?Object?obj)?{
????????//?hold?a?wake?lock?while?messages?are?pending
????????synchronized?(mWakeLock)?{
????????????mPendingMessageBits?|=?(1?<<?message);
????????????mWakeLock.acquire();
????????????mHandler.removeMessages(message);
????????????Message?m?=?Message.obtain(mHandler,?message);
????????????m.arg1?=?arg;
????????????m.obj?=?obj;
????????????mHandler.sendMessage(m);
????????}
????}
在handlerMessage?中的處理.?調用handleEnable();
?public?void?handleMessage(Message?msg)?{
????????????int?message?=?msg.what;
????????????switch?(message)?{
????????????????case?ENABLE:
????????????????????if?(msg.arg1?==?1)?{
????????????????????????handleEnable();
????????????????????}?else?{
????????????????????????handleDisable();
????????????????????}
????????????????????break;
???????}
??????handleEnable?主要作了兩件事,
????????1?調用本地方法?native_init(),初始化gps
?????????本地方法的具體實現是在com_android_server_location_GpsLocationProvider.cpp中,
??????????部分內容為下:
???????????static?jboolean?android_location_GpsLocationProvider_init(JNIEnv*?env,?jobject?obj)
{
????//取得接口,并初始化gps?
????const?GpsInterface*?interface?=?GetGpsInterface(env,?obj);
????if?(!interface)
????????return?false;
????if?(!sGpsDebugInterface)
???????sGpsDebugInterface?=?(const???GpsDebugInterface*)interface->get_extension(GPS_DEBUG_INTERFACE);
????return?true;
}
????????2?試圖啟動AGPS服務
???代碼如下:
?private?void?handleEnable()?{
????????if?(DEBUG)?Log.d(TAG,?"handleEnable");
????????if?(mEnabled)?return;
????????//調用本地方法初始化GPS
????????mEnabled?=?native_init();
????????
????????//試圖啟動AGPS服務
????????if?(mEnabled)?{
????????????mSupportsXtra?=?native_supports_xtra();
????????????if?(mSuplServerHost?!=?null)?{
????????????????native_set_agps_server(AGPS_TYPE_SUPL,?mSuplServerHost,?mSuplServerPort);
????????????}
????????????if?(mC2KServerHost?!=?null)?{
????????????????native_set_agps_server(AGPS_TYPE_C2K,?mC2KServerHost,?mC2KServerPort);
????????????}
????????}?else?{
????????????Log.w(TAG,?"Failed?to?enable?location?provider");
????????}
????}
取得接口的方法中,也調用了?get_gps_interface
代碼如下:
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;
}
Gps_qemu.c的代碼路徑為:\sdk\emulator\gps
這邊qemu_gps_init函數即是sGpsInterface->init函數,其中里面做了gps_state_init初始化,并注冊了callbacks回調函數,而這個函數也是在JNI層實現的,而且有JNI層傳下來的函數。
部分代碼為;
qemu_gps_init(GpsCallbacks*?callbacks)
{
????GpsState*??s?=?_gps_state;
????if?(!s->init)
????????gps_state_init(s);
????if?(s->fd?<?0)
????????return?-1;
????s->callbacks?=?*callbacks;
????return?0;
}
在這個主方法中首先打開串口,然后進立socket通信,然后建立線程監聽底層數據上報
static?void
gps_state_init(?GpsState*??state?)
{
????state->init???????=?1;
????state->control[0]?=?-1;
????state->control[1]?=?-1;
????state->fd?????????=?-1;
????state->fd?=?qemud_channel_open(QEMU_CHANNEL_NAME);
????if?(state->fd?<?0)?{
????????D("no?gps?emulation?detected");
????????return;
????}
????D("gps?emulation?will?read?from?'%s'?qemud?channel",?QEMU_CHANNEL_NAME?);
????if?(?socketpair(?AF_LOCAL,?SOCK_STREAM,?0,?state->control?)?<?0?)?{
????????LOGE("could?not?create?thread?control?socket?pair:?%s",?strerror(errno));
????????goto?Fail;
????}
????if?(?pthread_create(?&state->thread,?NULL,?gps_state_thread,?state?)?!=?0?)?{
????????LOGE("could?not?create?gps?thread:?%s",?strerror(errno));
????????goto?Fail;
????}
????D("gps?state?initialized");
????return;
Fail:
????gps_state_done(?state?);
}
該方法說明在初始化時調用的相關擴展接口是沒用的
static?const?void*
qemu_gps_get_extension(const?char*?name)
{
????//?no?extensions?supported
????return?NULL;
}
在2。2的時候handlerEnable還創建了一個監聽線程
而在2.3中GpsLocationProvider(路徑為:frameworks\base\services\java\com\android\server\location)
在構造函數中就創建了這個?監聽線程
構造器中的部分代碼
?mThread?=?new?GpsLocationProviderThread();
????????mThread.start();
????????while?(true)?{
????????????try?{
????????????????mInitializedLatch.await();
????????????????break;
????????????}?catch?(InterruptedException?e)?{
????????????????Thread.currentThread().interrupt();
????????????}
????????}
//run函數的部分內容
//initialize初始化函數,然后新建一個looper,新建一個providerHandler?用于處理該線程的消息
private?final?class?GpsLocationProviderThread?extends?Thread?{
????????public?GpsLocationProviderThread()?{
????????????super("GpsLocationProvider");
????????}
????????public?void?run()?{
????????????Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
????????????initialize();
????????????Looper.prepare();
????????????mHandler?=?new?ProviderHandler();
????????????//?signal?when?we?are?initialized?and?ready?to?go
????????????mInitializedLatch.countDown();
????????????Looper.loop();
????????}
}
??private?void?initialize()?{
????????//?register?our?receiver?on?our?thread?rather?than?the?main?thread
????????IntentFilter?intentFilter?=?new?IntentFilter();
????????intentFilter.addAction(ALARM_WAKEUP);
????????intentFilter.addAction(ALARM_TIMEOUT);
????????mContext.registerReceiver(mBroadcastReciever,?intentFilter);
????}
初始化主要是將線程的接收者注冊到我們的線程上,而不是注冊到主線程上。
到這邊為止我們完成了?p.enable()函數的分析。
在locationManagerService.java中,的run?()--->?initialize()--->loadProviders()----->loadProvidersLocked()
------->_loadProvidersLocked()------->updateProvidersLocked()------>updateProviderListenersLocked0
-------->調用到以下方法
private?void?updateProviderListenersLocked(String?provider,?boolean?enabled)?{
????????int?listeners?=?0;
????????LocationProviderInterface?p?=?mProvidersByName.get(provider);
????????if?(p?==?null)?{
????????????return;
????????}
????????ArrayList<Receiver>?deadReceivers?=?null;
????????
????????ArrayList<UpdateRecord>?records?=?mRecordsByProvider.get(provider);
????????if?(records?!=?null)?{
????????????final?int?N?=?records.size();
????????????for?(int?i=0;?i<N;?i++)?{
????????????????UpdateRecord?record?=?records.get(i);
????????????????//?Sends?a?notification?message?to?the?receiver
????????????????if?(!record.mReceiver.callProviderEnabledLocked(provider,?enabled))?{
????????????????????if?(deadReceivers?==?null)?{
????????????????????????deadReceivers?=?new?ArrayList<Receiver>();
????????????????????}
????????????????????deadReceivers.add(record.mReceiver);
????????????????}
????????????????listeners++;
????????????}
????????}
????????if?(deadReceivers?!=?null)?{
????????????for?(int?i=deadReceivers.size()-1;?i>=0;?i--)?{
????????????????removeUpdatesLocked(deadReceivers.get(i));
????????????}
????????}
????????
????????if?(enabled)?{
????????????p.enable();
????????????if?(listeners?>?0)?{
????????????????p.setMinTime(getMinTimeLocked(provider),?mTmpWorkSource);
????????????????p.enableLocationTracking(true);
????????????}
????????}?else?{
????????????p.enableLocationTracking(false);
????????????p.disable();
????????}
????}
enableLocationTracking在gpsLocationProvider.java中
??public?void?enableLocationTracking(boolean?enable)?{
????????//?FIXME?-?should?set?a?flag?here?to?avoid?race?conditions?with?single?shot?request
????????synchronized?(mHandler)?{
????????????sendMessage(ENABLE_TRACKING,?(enable???1?:?0),?null);
????????}
????}
??private?void?sendMessage(int?message,?int?arg,?Object?obj)?{
????????//?hold?a?wake?lock?while?messages?are?pending
????????synchronized?(mWakeLock)?{
????????????mPendingMessageBits?|=?(1?<<?message);
????????????mWakeLock.acquire();
????????????mHandler.removeMessages(message);
????????????Message?m?=?Message.obtain(mHandler,?message);
????????????m.arg1?=?arg;
????????????m.obj?=?obj;
????????????mHandler.sendMessage(m);
????????}
????}
??private?final?class?ProviderHandler?extends?Handler?{
????????@Override
????????public?void?handleMessage(Message?msg)?{
????????????int?message?=?msg.what;
????????????switch?(message)?{
????????????????case?ENABLE:
????????????????????if?(msg.arg1?==?1)?{
????????????????????????handleEnable();
????????????????????}?else?{
????????????????????????handleDisable();
????????????????????}
????????????????????break;
????????????????case?ENABLE_TRACKING:
?????????????????????//
?????????????????????handleEnableLocationTracking(msg.arg1?==?1);
????????????????????break;
}
???????}
???}
handleEnableLocationTracking?函數
?private?void?handleEnableLocationTracking(boolean?enable)?{
????????if?(enable)?{
????????????mTTFF?=?0;
????????????mLastFixTime?=?0;
????????????startNavigating(false);
????????}?else?{
????????????if?(!hasCapability(GPS_CAPABILITY_SCHEDULING))?{
????????????????mAlarmManager.cancel(mWakeupIntent);
????????????????mAlarmManager.cancel(mTimeoutIntent);
????????????}
????????????stopNavigating();
????????}
????}
startNavigating方法???開始導航
?代碼如下:
private?void?startNavigating(boolean?singleShot)?{
????????if?(!mStarted)?{
????????????if?(DEBUG)?Log.d(TAG,?"startNavigating");
????????????mStarted?=?true;
????????????mSingleShot?=?singleShot;
????????????mPositionMode?=?GPS_POSITION_MODE_STANDALONE;
?????????????if?(Settings.Secure.getInt(mContext.getContentResolver(),
????????????????????Settings.Secure.ASSISTED_GPS_ENABLED,?1)?!=?0)?{
????????????????if?(singleShot?&&?hasCapability(GPS_CAPABILITY_MSA))?{
????????????????????mPositionMode?=?GPS_POSITION_MODE_MS_ASSISTED;
????????????????}?else?if?(hasCapability(GPS_CAPABILITY_MSB))?{
????????????????????mPositionMode?=?GPS_POSITION_MODE_MS_BASED;
????????????????}
????????????}
????????????int?interval?=?(hasCapability(GPS_CAPABILITY_SCHEDULING)???mFixInterval?:?1000);
????????????//本地方法
????????????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;
????????????}
????????????//?reset?SV?count?to?zero
????????????updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE,?0);
????????????mFixRequestTime?=?System.currentTimeMillis();
????????????if?(!hasCapability(GPS_CAPABILITY_SCHEDULING))?{
????????????????//?set?timer?to?give?up?if?we?do?not?receive?a?fix?within?NO_FIX_TIMEOUT
????????????????//?and?our?fix?interval?is?not?short
????????????????if?(mFixInterval?>=?NO_FIX_TIMEOUT)?{
????????????????????mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
????????????????????????????SystemClock.elapsedRealtime()?+?NO_FIX_TIMEOUT,?mTimeoutIntent);
????????????????}
????????????}
????????}
????}
在開啟導航的這個方法中?,調用的兩個重要的本地方法
?這兩個本地方法可以在?com_android_server_location_GpsLocationProvider.cpp這個文件中找到
1?native_set_position_mode
實現代碼如下:
static?jboolean?android_location_GpsLocationProvider_set_position_mode(JNIEnv*?env,?jobject?obj,
????????jint?mode,?jint?recurrence,?jint?min_interval,?jint?preferred_accuracy,?jint?preferred_time)
{
????const?GpsInterface*?interface?=?GetGpsInterface(env,?obj);
????if?(interface)
????????//這里調用了接口的set_position_mode方法
????????return?(interface->set_position_mode(mode,?recurrence,?min_interval,?preferred_accuracy,
????????????????preferred_time)?==?0);
????else
????????return?false;
}
?該方法調用了接口的set_position_mode方法,這個方法的實現在(模擬器)的相關類中可以看到期實現
部分代碼如下;
static?int?qemu_gps_set_position_mode(GpsPositionMode?mode,?int?fix_frequency)
{
????//?FIXME?-?support?fix_frequency
????return?0;
}
2??native_start?通過向底層發送命令來啟動GPS,??這個底層就是enable/init函數中啟動的等待數據的線程?
static?int
qemu_gps_start()
{
????GpsState*??s?=?_gps_state;
????if?(!s->init)?{
????????D("%s:?called?with?uninitialized?state?!!",?__FUNCTION__);
????????return?-1;
????}
????D("%s:?called",?__FUNCTION__);
????gps_state_start(s);
????return?0;
}
static?void??gps_state_start(?GpsState*??s?)
{
????char??cmd?=?CMD_START;
????int???ret;
????do?{?ret=write(?s->control[0],?&cmd,?1?);?}
????while?(ret?<?0?&&?errno?==?EINTR);
????if?(ret?!=?1)
????????D("%s:?could?not?send?CMD_START?command:?ret=%d:?%s",
??????????__FUNCTION__,?ret,?strerror(errno));
}
???數據監聽線程
static?void*???gps_state_thread(?void*??arg?)
{
????GpsState*???state?=?(GpsState*)?arg;
????NmeaReader??reader[1];
????int?????????epoll_fd???=?epoll_create(2);
????int?????????started????=?0;
????int?????????gps_fd?????=?state->fd;
????int?????????control_fd?=?state->control[1];
????nmea_reader_init(?reader?);
????//?register?control?file?descriptors?for?polling
????epoll_register(?epoll_fd,?control_fd?);
????epoll_register(?epoll_fd,?gps_fd?);
????D("gps?thread?running");
????//?now?loop
????for?(;;)?{
????????struct?epoll_event???events[2];
????????int??????????????????ne,?nevents;
????????nevents?=?epoll_wait(?epoll_fd,?events,?2,?-1?);
????????if?(nevents?<?0)?{
????????????if?(errno?!=?EINTR)
????????????????LOGE("epoll_wait()?unexpected?error:?%s",?strerror(errno));
????????????continue;
????????}
????????D("gps?thread?received?%d?events",?nevents);
????????for?(ne?=?0;?ne?<?nevents;?ne++)?{
????????????if?((events[ne].events?&?(EPOLLERR|EPOLLHUP))?!=?0)?{
????????????????LOGE("EPOLLERR?or?EPOLLHUP?after?epoll_wait()?!?");
????????????????goto?Exit;
????????????}
????????????if?((events[ne].events?&?EPOLLIN)?!=?0)?{
????????????????int??fd?=?events[ne].data.fd;
????????????????if?(fd?==?control_fd)
????????????????{
????????????????????char??cmd?=?255;
????????????????????int???ret;
????????????????????D("gps?control?fd?event");
????????????????????do?{
????????????????????????ret?=?read(?fd,?&cmd,?1?);
????????????????????}?while?(ret?<?0?&&?errno?==?EINTR);
????????????????????if?(cmd?==?CMD_QUIT)?{
????????????????????????D("gps?thread?quitting?on?demand");
????????????????????????goto?Exit;
????????????????????}
????????????????????else?if?(cmd?==?CMD_START)?{
????????????????????????if?(!started)?{
????????????????????????????D("gps?thread?starting??location_cb=%p",?state->callbacks.location_cb);
????????????????????????????started?=?1;
????????????????????????????nmea_reader_set_callback(?reader,?state->callbacks.location_cb?);
????????????????????????}
????????????????????}
????????????????????else?if?(cmd?==?CMD_STOP)?{
????????????????????????if?(started)?{
????????????????????????????D("gps?thread?stopping");
????????????????????????????started?=?0;
????????????????????????????nmea_reader_set_callback(?reader,?NULL?);
????????????????????????}
????????????????????}
????????????????}
????????????????else?if?(fd?==?gps_fd)
????????????????{
????????????????????char??buff[32];
????????????????????D("gps?fd?event");
????????????????????for?(;;)?{
????????????????????????int??nn,?ret;
????????????????????????ret?=?read(?fd,?buff,?sizeof(buff)?);
????????????????????????if?(ret?<?0)?{
????????????????????????????if?(errno?==?EINTR)
????????????????????????????????continue;
????????????????????????????if?(errno?!=?EWOULDBLOCK)
????????????????????????????????LOGE("error?while?reading?from?gps?daemon?socket:?%s:",?strerror(errno));
????????????????????????????break;
????????????????????????}
????????????????????????D("received?%d?bytes:?%.*s",?ret,?ret,?buff);
????????????????????????for?(nn?=?0;?nn?<?ret;?nn++)
????????????????????????????nmea_reader_addc(?reader,?buff[nn]?);
????????????????????}
????????????????????D("gps?fd?event?end");
????????????????}
????????????????else
????????????????{
????????????????????LOGE("epoll_wait()?returned?unkown?fd?%d??",?fd);
????????????????}
????????????}
????????}
????}
Exit:
????return?NULL;
}
?這個監聽線程最主要的一個就是nmea_reader_set_callback(?)函數
其實就是注冊了一個回調函數,location_cb?這個回調函數就是對底層location數據上報的回調函數。
到此?
enableLocationTracking函數完成了,
也就是LocationManageService.java中
updateProviderListenersLocked的完成?
也就是updateProvidersLocked的完成,
也就是loadProviders函數的完成?
也就是?initialize的完成,
也就是run的完成,
也就是systemReady的完成
所以完了
轉載于:https://www.cnblogs.com/retacn-yue/archive/2012/09/03/2761388.html
總結
以上是生活随笔為你收集整理的android系统学习笔记十一的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hadoop安装记录(伪分布式)
- 下一篇: dropdownlist总是获取第一个值