Gps(globalPositionSystem全球定位系统)和定位部分
除此之外还有利用基站(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接口的结构体
typedefstruct{
/**settosizeof(GpsInterface)*/
size_tsize;
/**
*Openstheinterfaceandprovidesthecallbackroutines
*totheimplemenationofthisinterface.
初始化GPS,设置回调函数
*/
int(*init)(GpsCallbacks*callbacks);
/**Startsnavigating.*/
//开始导航
int(*start)(void);
/**Stopsnavigating.*/
//停止导航
int(*stop)(void);
/**Closestheinterface.*/
//关闭接口
void(*cleanup)(void);
/**Injectsthecurrenttime.*/
//设请求频率
int(*inject_time)(GpsUtcTimetime,int64_ttimeReference,
intuncertainty);
/**Injectscurrentlocationfromanotherlocationprovider
*(typicallycellID).
*latitudeandlongitudearemeasuredindegrees
*expectedaccuracyismeasuredinmeters
*/
int(*inject_location)(doublelatitude,doublelongitude,floataccuracy);
/**
*Specifiesthatthenextcalltostartwillnotusethe
*informationdefinedintheflags.GPS_DELETE_ALLispassedfor
*acoldstart.
*/
//删除帮助信息
void(*delete_aiding_data)(GpsAidingDataflags);
/**
*min_intervalrepresentsthetimebetweenfixesinmilliseconds.
*preferred_accuracyrepresentstherequestedfixaccuracyinmeters.
*preferred_timerepresentstherequestedtimetofirstfixinmilliseconds.
*/
//设置位置模式
int(*set_position_mode)(GpsPositionModemode,GpsPositionRecurrencerecurrence,
uint32_tmin_interval,uint32_tpreferred_accuracy,uint32_tpreferred_time);
/**Getapointertoextensioninformation.*/
//获得扩展消息的指针
constvoid*(*get_extension)(constchar*name);
}GpsInterface;
//表示GPS的定位信息
typedefstruct{
/**settosizeof(GpsLocation)*/
size_tsize;
/**ContainsGpsLocationFlagsbits.*/
//标志位
uint16_tflags;
/**Representslatitudeindegrees.*/
//表示纬度
doublelatitude;
/**Representslongitudeindegrees.*/
//表示经度
doublelongitude;
/**RepresentsaltitudeinmetersabovetheWGS84reference
*ellipsoid.*/
//以WGS84坐标系统表示的高度信息
doublealtitude;
/**Representsspeedinmeterspersecond.*/
//速度m/s
floatspeed;
/**Representsheadingindegrees.*/
//表示方向
floatbearing;
/**Representsexpectedaccuracyinmeters.*/
//表示精度
floataccuracy;
/**Timestampforthelocationfix.*/
//表示时间戮
GpsUtcTimetimestamp;
}GpsLocation;
当上层调用:GpsInterface.init时,会调用一个gpscallbacks结构指针,注册到适配层
//位置信息的回调函数
typedefvoid(*gps_location_callback)(GpsLocation*location);
//状态信息的回调函数
typedefvoid(*gps_status_callback)(GpsStatus*status);
//SV状态信息的回调函数
typedefvoid(*gps_sv_status_callback)(GpsSvStatus*sv_info);
typedefstruct{
/**settosizeof(GpsCallbacks)*/
size_tsize;
gps_location_callbacklocation_cb;
gps_status_callbackstatus_cb;
gps_sv_status_callbacksv_status_cb;
gps_nmea_callbacknmea_cb;
gps_set_capabilitiesset_capabilities_cb;
gps_acquire_wakelockacquire_wakelock_cb;
gps_release_wakelockrelease_wakelock_cb;
gps_create_threadcreate_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适配层调用
部分代码如下:
GpsCallbackssGpsCallbacks={
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下
LocationProviderProxymNetworkLocationProvider;
LocationProviderInterfacemGpsLocationProvider;
**************************************************************
2.3中的变化
**************************************************************
\frameworks\base\services\java\com\android\server\location目录下的GpsLocationProvider.java它直接继承
LocationProviderInterface(在2。3之前可能是LocationProviderImpl),它提供了底层的控制接口,同时开启一个gpsEventThread通过轮询native_wait_for_event来取得底层上报的数据
App发出定位申请,启动定位服务线程,此线程会在APPframwork中调用locationprovider
通过被native方法调用到JNI中,JNI获得gpsInterface并传给接口一个回调函数的实现
gpsInterface就是HAL层最主要的实现
上层实现的思路
1、获取GPS的LocationProvider。
2、将此Provider传入到requestLocationUpdates()方法,让Android系统获知搜索位置方式。
3、创建实现了GpsStatus.Listener接口的对象,重写onGpsStatusChanged()方法,向LocationManager添加次监听器,检测卫星状态。(可选步骤)
AndroidGPS架构分析
Framework层:
代码路径为:
1\frameworks\base\location\java\android\location
供api调用
2frameworks\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应用程序的一个接口,直接操作硬件设备
底层几个重要和数据结构
1gpsInterface是最重要的数据结构,它是底层实现的接口,如果要porting到自已的板子上,就要实现这这些接口,
该接口的定义在gps.h中,模拟器实现在gps_qemu.c中
typedefstruct{
size_tsize;
int(*init)(GpsCallbacks*callbacks);
int(*start)(void);
int(*stop)(void);
void(*cleanup)(void);
int(*inject_time)(GpsUtcTimetime,int64_ttimeReference,
intuncertainty);
int(*inject_location)(doublelatitude,doublelongitude,floataccuracy);
void(*delete_aiding_data)(GpsAidingDataflags);
int(*set_position_mode)(GpsPositionModemode,GpsPositionRecurrencerecurrence,
uint32_tmin_interval,uint32_tpreferred_accuracy,uint32_tpreferred_time);
constvoid*(*get_extension)(constchar*name);
}GpsInterface;
2gpscallbacks回调函数结构体,定义同上,实现在com_android_server_android_location_GpsLocationProvider.cpp中
typedefstruct{
size_tsize;
gps_location_callbacklocation_cb;
gps_status_callbackstatus_cb;
gps_sv_status_callbacksv_status_cb;
gps_nmea_callbacknmea_cb;
//以下几个回调函数是在2.3以后添加的回调函数
gps_set_capabilitiesset_capabilities_cb;
gps_acquire_wakelockacquire_wakelock_cb;
gps_release_wakelockrelease_wakelock_cb;
gps_create_threadcreate_thread_cb;
}GpsCallbacks;
3Gpslocation表示loaction数据信息2.3比2.2多了个size属性
typedefstruct{
//2.3之后添加
size_tsize;
uint16_tflags;
doublelatitude;
doublelongitude;
doublealtitude;
floatspeed;
floatbearing;
floataccuracy;
GpsUtcTimetimestamp;
}GpsLocation;
Gps的定位服务(locationManager)的启动过程
LocationManager这项服务是systemServer.java来启动,也就是在系统启动之后就启动
systemServer.java[framework/base/services/java/com/android/server]
publicstaticfinalvoidinit2(){
Slog.i(TAG,"EnteredtheAndroidsystemserver!");
Threadthr=newServerThread();
thr.setName("android.server.ServerThread");
thr.start();
}
在ServerThread线程的run函数中LocationManager服务的代码段如下:
try{
Slog.i(TAG,"LocationManager");
location=newLocationManagerService(context);
ServiceManager.addService(Context.LOCATION_SERVICE,location);
}catch(Throwablee){
Slog.e(TAG,"FailurestartingLocationManager",e);
}
在run函数的后半部分,是服务对系统的反馈,就是systemReady()函数。LocationManager服务的反馈函数如下:
finalLocationManagerServicelocationF=location;
其中的locationF是LocationManagerService的final类型,就是一旦赋值,不能更改。
if(locationF!=null)locationF.systemReady();
LocationManagerService代码路径如下:\frameworks\base\services\java\com\android\server
构造器如下:
publicLocationManagerService(Contextcontext){
super();
mContext=context;
Resourcesresources=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,"ConstructedLocationManagerService");
}
}
voidsystemReady(){
//wedeferstartinguptheserviceuntilthesystemisready
Threadthread=newThread(null,this,"LocationManagerService");
thread.start();
}
在run函数中,又调用了initialize函数
publicvoidrun()
{
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Looper.prepare();
mLocationHandler=newLocationWorkerHandler();
initialize();//************************
Looper.loop();
}
privatevoidinitialize(){
//Createawakelock,needstobedonebeforecallingloadProviders()below
PowerManagerpowerManager=(PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
mWakeLock=powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,WAKELOCK_KEY);
//Loadproviders
//重要方法
loadProviders();
//RegisterforNetwork(WifiorMobile)updates
IntentFilterintentFilter=newIntentFilter();
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
//RegisterforPackageManagerupdates
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
intentFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
mContext.registerReceiver(mBroadcastReceiver,intentFilter);
IntentFiltersdFilter=newIntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
mContext.registerReceiver(mBroadcastReceiver,sdFilter);
//listenforsettingschanges
ContentResolverresolver=mContext.getContentResolver();
CursorsettingsCursor=resolver.query(Settings.Secure.CONTENT_URI,null,
"("+Settings.System.NAME+"=?)",
newString[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
null);
mSettings=newContentQueryMap(settingsCursor,Settings.System.NAME,true,mLocationHandler);
SettingsObserversettingsObserver=newSettingsObserver();
mSettings.addObserver(settingsObserver);
}
初始化函数中,最重要的便是loadProviders()函数。
privatevoidloadProviders(){
synchronized(mLock){
if(sProvidersLoaded){
return;
}
//Loadproviders
loadProvidersLocked();
sProvidersLoaded=true;
}
}
privatevoidloadProvidersLocked(){
try{
_loadProvidersLocked();
}catch(Exceptione){
Slog.e(TAG,"Exceptionloadingproviders:",e);
}
}
_loadProvidersLocked函数,
privatevoid_loadProvidersLocked(){
//Attempttoload"real"providersfirst
//取得GPS的接口
if(GpsLocationProvider.isSupported()){
//Createagpslocationprovider
GpsLocationProvidergpsProvider=newGpsLocationProvider(mContext,this);
mGpsStatusProvider=gpsProvider.getGpsStatusProvider();
mNetInitiatedListener=gpsProvider.getNetInitiatedListener();
addProvider(gpsProvider);
mGpsLocationProvider=gpsProvider;
}
//createapassivelocationprovider,whichisalwaysenabled
PassiveProviderpassiveProvider=newPassiveProvider(this);
addProvider(passiveProvider);
mEnabledProviders.add(passiveProvider.getName());
//initializeexternalnetworklocationandgeocoderservices
if(mNetworkLocationProviderPackageName!=null){
mNetworkLocationProvider=
newLocationProviderProxy(mContext,LocationManager.NETWORK_PROVIDER,
mNetworkLocationProviderPackageName,mLocationHandler);
addProvider(mNetworkLocationProvider);
}
if(mGeocodeProviderPackageName!=null){
mGeocodeProvider=newGeocoderProxy(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
部分代码如下:
publicstaticbooleanisSupported(){
//调用的是本地方法
returnnative_is_supported();
}
函数中只有一句话,这调用了native方法,既Jni层定义的方法。native_is_supported对应在
framework/base/services/jni/com_android_server_location_GpsLocationProvider.cpp文件中的android_location_GpsLocationProvider_is_supported方法。
部分代码如下;
staticjbooleanandroid_location_GpsLocationProvider_is_supported(JNIEnv*env,jclassclazz){
return(sGpsInterface!=NULL||get_gps_interface()!=NULL);
}
get_gps_interface()的具体代码如下:
staticconstGpsInterface*get_gps_interface(){
interr;
hw_module_t*module;
constGpsInterface*interface=NULL;
err=hw_get_module(GPS_HARDWARE_MODULE_ID,(hw_module_tconst**)&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);
}
}
returninterface;
}
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部分代码如下:
constGpsInterface*gps__get_gps_interface(structgps_device_t*dev)
{
returnget_gps_interface();
}
loc_eng.cpp的部分代码如下:
staticconstGpsInterfacesLocEngInterface=
{
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中,如果找到了硬件,并取得了接口后,接着执行下一句
GpsLocationProvidergpsProvider=newGpsLocationProvider(mContext,this);
GpsLocationProvider的代码路径为:frameworks\base\services\java\com\android\server\location
publicGpsLocationProvider(Contextcontext,ILocationManagerlocationManager){
mContext=context;
//mLocationManager就是第二个参数.也就是locationManagerService
mLocationManager=locationManager;
mNIHandler=newGpsNetInitiatedHandler(context);
mLocation.setExtras(mLocationExtras);
....................
}
_loadProvidersLocked函数,在构造完成后,将其add到全局变量ArrayList<LocationProviderInterface>mProviders中,备以后调用.
接着启动了两个线程,但是可惜的是这两个服务都无法启动,因为他们是通过配置文件conifg.xml得到服务的名字,然后启动服务的。但是在这个配置文件中,两个服务的名字都是null
配置文件的路径为;framework/base/core/res/res/values
部分代码如下:
<!--Componentnameoftheserviceprovidingnetworklocationsupport.-->
<stringname="config_networkLocationProvider">@null</string>
<!--ComponentnameoftheserviceprovidinggeocoderAPIsupport.-->
<stringname="config_geocodeProvider">@null</string>
这就是为什么在调用getFromLocationName和getFromLocation时会提示servicenotavailable,2.2就存在的bug
在_loadProvidersLocked函数的最后调用的是updateProvidersLocked();也在这个类中
部分代码如下:
privatevoidupdateProvidersLocked(){
booleanchangesMade=false;
for(inti=mProviders.size()-1;i>=0;i--){
LocationProviderInterfacep=mProviders.get(i);
booleanisEnabled=p.isEnabled();
Stringname=p.getName();
booleanshouldBeEnabled=isAllowedBySettingsLocked(name);
if(isEnabled&&!shouldBeEnabled){
updateProviderListenersLocked(name,false);
changesMade=true;
}elseif(!isEnabled&&shouldBeEnabled){
updateProviderListenersLocked(name,true);
changesMade=true;
}
}
if(changesMade){
mContext.sendBroadcast(newIntent(LocationManager.PROVIDERS_CHANGED_ACTION));
}
}
在mProviders里面应该存在一个gpsProvider和PassiveProvider,而gpsProvider是未被enable的。而passiveProvider是enable的。
这边我们对gpsProvider进行讨论,他执行的是updateProviderListenersLocked(name,true)然后当有发生改变,就是changesMade=true时,它发送了广播,内容是告诉大家LocationManager发生了变化,让需要的接收者自己接收。
updateProviderListenersLocked(name,false)函数的部分代码如下:
privatevoidupdateProviderListenersLocked(Stringprovider,booleanenabled){
intlisteners=0;
LocationProviderInterfacep=mProvidersByName.get(provider);
if(p==null){
return;
}
ArrayList<Receiver>deadReceivers=null;
ArrayList<UpdateRecord>records=mRecordsByProvider.get(provider);
if(records!=null){
finalintN=records.size();
for(inti=0;i<N;i++){
UpdateRecordrecord=records.get(i);
//Sendsanotificationmessagetothereceiver
if(!record.mReceiver.callProviderEnabledLocked(provider,enabled)){
if(deadReceivers==null){
deadReceivers=newArrayList<Receiver>();
}
deadReceivers.add(record.mReceiver);
}
listeners++;
}
}
if(deadReceivers!=null){
for(inti=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
部分代码如下:
publicvoidenable(){
synchronized(mHandler){
sendMessage(ENABLE,1,null);
}
}
//每次进入此消息,就是清除之前所有消息发送消息交给handlerMassage处理
privatevoidsendMessage(intmessage,intarg,Objectobj){
//holdawakelockwhilemessagesarepending
synchronized(mWakeLock){
mPendingMessageBits|=(1<<message);
mWakeLock.acquire();
mHandler.removeMessages(message);
Messagem=Message.obtain(mHandler,message);
m.arg1=arg;
m.obj=obj;
mHandler.sendMessage(m);
}
}
在handlerMessage中的处理.调用handleEnable();
publicvoidhandleMessage(Messagemsg){
intmessage=msg.what;
switch(message){
caseENABLE:
if(msg.arg1==1){
handleEnable();
}else{
handleDisable();
}
break;
}
handleEnable主要作了两件事,
1调用本地方法native_init(),初始化gps
本地方法的具体实现是在com_android_server_location_GpsLocationProvider.cpp中,
部分内容为下:
staticjbooleanandroid_location_GpsLocationProvider_init(JNIEnv*env,jobjectobj)
{
//取得接口,并初始化gps
constGpsInterface*interface=GetGpsInterface(env,obj);
if(!interface)
returnfalse;
if(!sGpsDebugInterface)
sGpsDebugInterface=(constGpsDebugInterface*)interface->get_extension(GPS_DEBUG_INTERFACE);
returntrue;
}
2试图启动AGPS服务
代码如下:
privatevoidhandleEnable(){
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,"Failedtoenablelocationprovider");
}
}
取得接口的方法中,也调用了get_gps_interface
代码如下:
staticconstGpsInterface*GetGpsInterface(JNIEnv*env,jobjectobj){
//thismustbesetbeforecallingintotheHALlibrary
if(!mCallbacksObj)
mCallbacksObj=env->NewGlobalRef(obj);
if(!sGpsInterface){
sGpsInterface=get_gps_interface();
if(!sGpsInterface||sGpsInterface->init(&sGpsCallbacks)!=0){
sGpsInterface=NULL;
returnNULL;
}
}
returnsGpsInterface;
}
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;
return0;
}
在这个主方法中首先打开串口,然后进立socket通信,然后建立线程监听底层数据上报
staticvoid
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("nogpsemulationdetected");
return;
}
D("gpsemulationwillreadfrom'%s'qemudchannel",QEMU_CHANNEL_NAME);
if(socketpair(AF_LOCAL,SOCK_STREAM,0,state->control)<0){
LOGE("couldnotcreatethreadcontrolsocketpair:%s",strerror(errno));
gotoFail;
}
if(pthread_create(&state->thread,NULL,gps_state_thread,state)!=0){
LOGE("couldnotcreategpsthread:%s",strerror(errno));
gotoFail;
}
D("gpsstateinitialized");
return;
Fail:
gps_state_done(state);
}
该方法说明在初始化时调用的相关扩展接口是没用的
staticconstvoid*
qemu_gps_get_extension(constchar*name)
{
//noextensionssupported
returnNULL;
}
在2。2的时候handlerEnable还创建了一个监听线程
而在2.3中GpsLocationProvider(路径为:frameworks\base\services\java\com\android\server\location)
在构造函数中就创建了这个监听线程
构造器中的部分代码
mThread=newGpsLocationProviderThread();
mThread.start();
while(true){
try{
mInitializedLatch.await();
break;
}catch(InterruptedExceptione){
Thread.currentThread().interrupt();
}
}
//run函数的部分内容
//initialize初始化函数,然后新建一个looper,新建一个providerHandler用于处理该线程的消息
privatefinalclassGpsLocationProviderThreadextendsThread{
publicGpsLocationProviderThread(){
super("GpsLocationProvider");
}
publicvoidrun(){
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
initialize();
Looper.prepare();
mHandler=newProviderHandler();
//signalwhenweareinitializedandreadytogo
mInitializedLatch.countDown();
Looper.loop();
}
}
privatevoidinitialize(){
//registerourreceiveronourthreadratherthanthemainthread
IntentFilterintentFilter=newIntentFilter();
intentFilter.addAction(ALARM_WAKEUP);
intentFilter.addAction(ALARM_TIMEOUT);
mContext.registerReceiver(mBroadcastReciever,intentFilter);
}
初始化主要是将线程的接收者注册到我们的线程上,而不是注册到主线程上。
到这边为止我们完成了p.enable()函数的分析。
在locationManagerService.java中,的run()--->initialize()--->loadProviders()----->loadProvidersLocked()
------->_loadProvidersLocked()------->updateProvidersLocked()------>updateProviderListenersLocked0
-------->调用到以下方法
privatevoidupdateProviderListenersLocked(Stringprovider,booleanenabled){
intlisteners=0;
LocationProviderInterfacep=mProvidersByName.get(provider);
if(p==null){
return;
}
ArrayList<Receiver>deadReceivers=null;
ArrayList<UpdateRecord>records=mRecordsByProvider.get(provider);
if(records!=null){
finalintN=records.size();
for(inti=0;i<N;i++){
UpdateRecordrecord=records.get(i);
//Sendsanotificationmessagetothereceiver
if(!record.mReceiver.callProviderEnabledLocked(provider,enabled)){
if(deadReceivers==null){
deadReceivers=newArrayList<Receiver>();
}
deadReceivers.add(record.mReceiver);
}
listeners++;
}
}
if(deadReceivers!=null){
for(inti=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中
publicvoidenableLocationTracking(booleanenable){
//FIXME-shouldsetaflagheretoavoidraceconditionswithsingleshotrequest
synchronized(mHandler){
sendMessage(ENABLE_TRACKING,(enable?1:0),null);
}
}
privatevoidsendMessage(intmessage,intarg,Objectobj){
//holdawakelockwhilemessagesarepending
synchronized(mWakeLock){
mPendingMessageBits|=(1<<message);
mWakeLock.acquire();
mHandler.removeMessages(message);
Messagem=Message.obtain(mHandler,message);
m.arg1=arg;
m.obj=obj;
mHandler.sendMessage(m);
}
}
privatefinalclassProviderHandlerextendsHandler{
@Override
publicvoidhandleMessage(Messagemsg){
intmessage=msg.what;
switch(message){
caseENABLE:
if(msg.arg1==1){
handleEnable();
}else{
handleDisable();
}
break;
caseENABLE_TRACKING:
//
handleEnableLocationTracking(msg.arg1==1);
break;
}
}
}
handleEnableLocationTracking函数
privatevoidhandleEnableLocationTracking(booleanenable){
if(enable){
mTTFF=0;
mLastFixTime=0;
startNavigating(false);
}else{
if(!hasCapability(GPS_CAPABILITY_SCHEDULING)){
mAlarmManager.cancel(mWakeupIntent);
mAlarmManager.cancel(mTimeoutIntent);
}
stopNavigating();
}
}
startNavigating方法开始导航
代码如下:
privatevoidstartNavigating(booleansingleShot){
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;
}elseif(hasCapability(GPS_CAPABILITY_MSB)){
mPositionMode=GPS_POSITION_MODE_MS_BASED;
}
}
intinterval=(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_modefailedinstartNavigating()");
return;
}
//本地方法
if(!native_start()){
mStarted=false;
Log.e(TAG,"native_startfailedinstartNavigating()");
return;
}
//resetSVcounttozero
updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE,0);
mFixRequestTime=System.currentTimeMillis();
if(!hasCapability(GPS_CAPABILITY_SCHEDULING)){
//settimertogiveupifwedonotreceiveafixwithinNO_FIX_TIMEOUT
//andourfixintervalisnotshort
if(mFixInterval>=NO_FIX_TIMEOUT){
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime()+NO_FIX_TIMEOUT,mTimeoutIntent);
}
}
}
}
在开启导航的这个方法中,调用的两个重要的本地方法
这两个本地方法可以在com_android_server_location_GpsLocationProvider.cpp这个文件中找到
1native_set_position_mode
实现代码如下:
staticjbooleanandroid_location_GpsLocationProvider_set_position_mode(JNIEnv*env,jobjectobj,
jintmode,jintrecurrence,jintmin_interval,jintpreferred_accuracy,jintpreferred_time)
{
constGpsInterface*interface=GetGpsInterface(env,obj);
if(interface)
//这里调用了接口的set_position_mode方法
return(interface->set_position_mode(mode,recurrence,min_interval,preferred_accuracy,
preferred_time)==0);
else
returnfalse;
}
该方法调用了接口的set_position_mode方法,这个方法的实现在(模拟器)的相关类中可以看到期实现
部分代码如下;
staticintqemu_gps_set_position_mode(GpsPositionModemode,intfix_frequency)
{
//FIXME-supportfix_frequency
return0;
}
2native_start通过向底层发送命令来启动GPS,这个底层就是enable/init函数中启动的等待数据的线程
staticint
qemu_gps_start()
{
GpsState*s=_gps_state;
if(!s->init){
D("%s:calledwithuninitializedstate!!",__FUNCTION__);
return-1;
}
D("%s:called",__FUNCTION__);
gps_state_start(s);
return0;
}
staticvoidgps_state_start(GpsState*s)
{
charcmd=CMD_START;
intret;
do{ret=write(s->control[0],&cmd,1);}
while(ret<0&&errno==EINTR);
if(ret!=1)
D("%s:couldnotsendCMD_STARTcommand:ret=%d:%s",
__FUNCTION__,ret,strerror(errno));
}
数据监听线程
staticvoid*gps_state_thread(void*arg)
{
GpsState*state=(GpsState*)arg;
NmeaReaderreader[1];
intepoll_fd=epoll_create(2);
intstarted=0;
intgps_fd=state->fd;
intcontrol_fd=state->control[1];
nmea_reader_init(reader);
//registercontrolfiledescriptorsforpolling
epoll_register(epoll_fd,control_fd);
epoll_register(epoll_fd,gps_fd);
D("gpsthreadrunning");
//nowloop
for(;;){
structepoll_eventevents[2];
intne,nevents;
nevents=epoll_wait(epoll_fd,events,2,-1);
if(nevents<0){
if(errno!=EINTR)
LOGE("epoll_wait()unexpectederror:%s",strerror(errno));
continue;
}
D("gpsthreadreceived%devents",nevents);
for(ne=0;ne<nevents;ne++){
if((events[ne].events&(EPOLLERR|EPOLLHUP))!=0){
LOGE("EPOLLERRorEPOLLHUPafterepoll_wait()!?");
gotoExit;
}
if((events[ne].events&EPOLLIN)!=0){
intfd=events[ne].data.fd;
if(fd==control_fd)
{
charcmd=255;
intret;
D("gpscontrolfdevent");
do{
ret=read(fd,&cmd,1);
}while(ret<0&&errno==EINTR);
if(cmd==CMD_QUIT){
D("gpsthreadquittingondemand");
gotoExit;
}
elseif(cmd==CMD_START){
if(!started){
D("gpsthreadstartinglocation_cb=%p",state->callbacks.location_cb);
started=1;
nmea_reader_set_callback(reader,state->callbacks.location_cb);
}
}
elseif(cmd==CMD_STOP){
if(started){
D("gpsthreadstopping");
started=0;
nmea_reader_set_callback(reader,NULL);
}
}
}
elseif(fd==gps_fd)
{
charbuff[32];
D("gpsfdevent");
for(;;){
intnn,ret;
ret=read(fd,buff,sizeof(buff));
if(ret<0){
if(errno==EINTR)
continue;
if(errno!=EWOULDBLOCK)
LOGE("errorwhilereadingfromgpsdaemonsocket:%s:",strerror(errno));
break;
}
D("received%dbytes:%.*s",ret,ret,buff);
for(nn=0;nn<ret;nn++)
nmea_reader_addc(reader,buff[nn]);
}
D("gpsfdeventend");
}
else
{
LOGE("epoll_wait()returnedunkownfd%d?",fd);
}
}
}
}
Exit:
returnNULL;
}
这个监听线程最主要的一个就是nmea_reader_set_callback()函数
其实就是注册了一个回调函数,location_cb这个回调函数就是对底层location数据上报的回调函数。
到此
enableLocationTracking函数完成了,
也就是LocationManageService.java中
updateProviderListenersLocked的完成
也就是updateProvidersLocked的完成,
也就是loadProviders函数的完成
也就是initialize的完成,
也就是run的完成,
也就是systemReady的完成
所以完了