`

android系统学习笔记十一

阅读更多

Gps(globalPositionSystem全球定位系统)和定位部分

除此之外还有利用基站(cell)定位的AGPS等设备

定们系列统的基本架构

主要数据来源有两个:GPS定位和network定位(基于cellwifi热点的定位)

定位部分的结构如图

 

 

定位系统的驱动层

Network定位的底层驱动和适配层实际上就是RILwifi框架的组成部分

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实现自已的gpscallbacksGPS适配层调用

部分代码如下:

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

 

 

ILocationManagerandroid定们系统的核心

LocationServiceManager是定位系统的服务器端,它在目录:\frameworks\base\services\java\com\android\server下

LocationProviderProxymNetworkLocationProvider;

LocationProviderInterfacemGpsLocationProvider;

 

**************************************************************

2.3中的变化

**************************************************************

\frameworks\base\services\java\com\android\server\location目录下的GpsLocationProvider.java它直接继承

LocationProviderInterface(23之前可能是LocationProviderImpl),它提供了底层的控制接口,同时开启一个gpsEventThread通过轮询native_wait_for_event来取得底层上报的数据

 

 

 

App发出定位申请,启动定位服务线程,此线程会在APPframwork中调用locationprovider

通过被native方法调用到JNI,JNI获得gpsInterface并传给接口一个回调函数的实现

gpsInterface就是HAL层最主要的实现

 

上层实现的思路

1、获取GPSLocationProvider

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

这个目录是frameworklocation服务的内部实现

3\frameworks\base\services\java\com\android\server

这是location服务对内部实现的一个封装

JNI层:

 

代码路径:

22版本中

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.32.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;

 

其中的locationFLocationManagerServicefinal类型,就是一旦赋值,不能更改。

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_interfacegps_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>

这就是为什么在调用getFromLocationNamegetFromLocation时会提示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里面应该存在一个gpsProviderPassiveProvider,而gpsProvider是未被enable的。而passiveProviderenable的。

 

这边我们对gpsProvider进行讨论,他执行的是updateProviderListenersLockedname,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;

}

 

22的时候handlerEnable还创建了一个监听线程

而在2.3GpsLocationProvider(路径为: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的完成

所以完了

分享到:
评论

相关推荐

    第一行代码 android学习笔记 完整版

    Android学习笔记是Android开发者的必读书籍,书中涵盖了Android系统架构、Activity、Intent、资源管理等多方面的知识。本笔记对应的学习资源《第一行代码》是Android开发者的入门必读书籍,书中系统地介绍了Android...

    Android基础学习笔记

    Android基础学习笔记主要涵盖了一系列关于Android开发的基本概念和关键组件,以下是这些知识点的详细解析: 1. **Activity**: 是Android应用程序的基本单元,它代表用户在屏幕上看到的一个界面。每个Activity都必须...

    Android Studio 学习笔记-新手入门-(1)第一个案例

    这篇学习笔记将引导新手入门,通过创建第一个简单的案例来了解Android Studio的基本操作。 首先,让我们了解一下Android Studio的核心功能。它基于IntelliJ IDEA,具备代码自动补全、重构、调试等强大的开发特性。...

    Android Activity学习笔记

    Android Activity学习笔记 Android Activity是Android系统中最基本的组件之一,它负责处理用户交互和显示用户界面。本文将深入讲解Activity的生命周期、Activity之间的数据交互、Activity启动模式、Task和BackStack...

    Android学习笔记

    ### Android学习笔记 #### 1. Android概述 **1.1 Android的特性** - **应用框架**:Android提供了一个强大的应用框架,使得开发者能够轻松地重用基础组件和服务,简化了应用程序的开发流程。 - **Dalvik虚拟机**...

    Android学习新手笔记

    - Android系统基于Linux系统开发,拥有开放源码。 - Android系统框架由多个组件构成,其中包括Activity、Intent、Service、ContentProvider、View和BroadcastReceiver。 - Activity作为组件容器,主要负责用户...

    java学习细节 android学习笔记

    根据给定的信息,我们可以从Java和Android学习笔记中提取出一系列重要的知识点,下面将逐一进行详细解释。 ### Java基础知识 #### 1. 命令行基础操作 - **`javacmd`**: 这个命令是Java命令行工具的一部分,用于...

    Android+学习笔记

    ### Android学习笔记知识点详解 #### 一、简介与背景 Android作为全球最受欢迎的移动操作系统之一,自2007年谷歌发布以来,迅速占领市场并持续引领移动技术的发展。随着移动互联网的兴起和发展,Android应用开发...

    Android_学习笔记

    ### Android学习笔记——从HelloWorld开始 #### 一、Google的Android SDK介绍 自从Google发布了Android SDK以来,这款开源移动操作系统迅速吸引了众多开发者的关注。Android SDK为开发者提供了丰富的工具和API,...

    Android学习笔记.doc Android学习笔记.doc

    【Android学习笔记】 Android平台是谷歌推出的一个开放源代码的移动设备操作系统,它为开发者提供了一个全面的软件包,包括操作系统、中间件和关键应用程序。这个平台的主要目标是促进移动应用的创新和多样性,允许...

    android全程学习笔记

    Android全程学习笔记旨在提供一个详尽且全面的指南,涵盖了Android开发中的关键技术点和实践案例。以下是关于Android开发的一些核心知识点: 1. **第一个Android应用**:开发Android应用的起点通常是从创建并运行你...

    Android_学习笔记.zip

    这个"Android_学习笔记.zip"文件很可能包含了一个详细的Android开发学习路径和关键知识点的总结。下面将基于这个主题,详细讲解Android开发的一些核心概念和技术。 首先,Android是Google开发的一款开源操作系统,...

    Android 学习笔记

    这篇学习笔记主要涵盖了关于布局的一些基本概念,特别是`fill_parent`和`wrap_content`这两种尺寸指定方式,以及如何通过XML布局文件来精确控制组件的位置。 首先,`fill_parent`和`wrap_content`是Android布局中的...

    Android 系统相关学习笔记.zip

    在Android系统相关学习笔记中,我们可以深入探讨这个广泛而复杂的移动操作系统的核心概念和技术。Android以其开源性和灵活性,吸引了大量的开发者和爱好者。以下是一些关键的知识点: 1. **Android架构**:Android...

    android 很好的学习笔记

    【Android学习笔记详解】 在移动应用开发领域,Android操作系统占据着重要的地位,为开发者提供了...通过系统学习并实践其中的内容,你将能够逐步掌握Android开发的核心技能,为你的Android开发者之路打下坚实的基础。

    Android PreferenceActivity 学习笔记

    这篇学习笔记将深入探讨PreferenceActivity的使用方法、功能以及与源码相关的知识。 首先,PreferenceActivity是Android SDK提供的一种特殊类型的Activity,它允许开发者快速构建具有可配置选项的界面,类似于系统...

    Android开发学习笔记

    ### Android开发学习笔记知识点梳理 #### 一、Android概述与架构 - **定义与发布**:Android是由Google在2007年11月5日宣布的基于Linux平台的开源手机操作系统。它不仅用于智能手机,还广泛应用于平板电脑、可穿戴...

Global site tag (gtag.js) - Google Analytics