`

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 系统相关学习笔记.zip

    Android 系统相关学习笔记.zip

    android系统模块之Contacts的学习笔记

    android系统模块之Contacts的学习笔记

    android开发学习笔记

    本人做android也有两年了,主要做智能机系统级开发,期间也承包了一些项目,对于如何学好android,以及学好android后如何开启自己的致富之门也能起到抛砖引玉的作用,欢迎大家加入,积极发言讨论,积极解决他人的...

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

    Android platform是一个用于开发移动程序的软件包,它包括了操作系统、中间件及一些关键应用。开发者能使用android SDK为Android platform开发应用,这些应用使用JAVA语言书写,运行在虚拟机Dalvik(一个专为手机程序...

    Pro Android学习:Menu

    是Pro Android学习笔记Menu系统的例子代码

    android入门学习笔记-永远不变的helloworld、初识activity

    本资源是上课时的笔记,系统的讲述了android。想学习andorid的新手可以载下来供参考使用

    Android知识系统总结+最佳学习线路图+实例+全程开发笔记

    Android知识系统总结+最佳学习线路图+实例+全程开发笔记Android知识系统总结+最佳学习线路图+实例+全程开发笔记

    Android学习笔记.doc

    Android platform是一个用于开发移动程序的软件包,它包括了操作系统、中间件及一些关键应用。开发者能使用android SDK为Android platform开发应用,这些应用使用JAVA语言书写,运行在虚拟机Dalvik(一个专为手机程序...

    android 系统笔记.zip

    操作系统:LInux、IOS、树莓派、安卓开发、微机操作系统、网络操作系统、分布式操作系统等。此外,还有嵌入式操作系统、智能操作系统等。 网络与通信:数据传输、信号处理、网络协议、网络与通信硬件、网络安全网络...

    android 学习笔记

    使用系统自带意图对象完成: Intent intent=new Intent(); intent.setAction("android.intent.action.Call"); intent.setData(Uri.parse("tel:"+i)); startActivity(Intent); 权限: &lt;uses-permission ...

    黑马程序员之android学习笔记--用户界面 View(一).docx

    黑马程序员之android学习笔记--用户界面 View(一).docx

    Android Map开发基础知识学习笔记

    本教程适用于Android Map学习的初学者,这是一本很平易近人的Android入门书籍,也是开发者及非开发者两相宜的实务书籍,它能陪伴你顺利入门,并驰骋于无限宽广的Android系统和应用领域

    Android知识系统总结

    里面包含7个常见android应用程序源代码,android学习笔记,开发入门实践,入门书籍等很有用的资料。

    第一行代码—Android第二版学习笔记

    Android 第一行代码学习笔记第一章 概述1.1安卓系统架构1.2Android四大组件1.3项目结构1.4app目录结构1.5 项目运行原理1.6 res目录详解1.7日志工具的使用第二章 活动2.1 创建基本活动2.2 使用Intent在活动之间跳转...

    Android学习笔记之——Content Providers

    之前博文《 Android学习笔记之——Android Studio的安装(3.6版本)、Java的基本语法及Android的概述 》曾经介绍过android有四大组件。本博文学习一下Content Providers(内容提供器) 目录 Android运行时 ...

    AOSP Android系统定制裁剪笔记.zip

    操作系统:LInux、IOS、树莓派、安卓开发、微机操作系统、网络操作系统、分布式操作系统等。此外,还有嵌入式操作系统、智能操作系统等。 网络与通信:数据传输、信号处理、网络协议、网络与通信硬件、网络安全网络...

    2021-学习相关-Android 局域网简易云端笔记系统源码.zip

    2021-学习相关-Android 局域网简易云端笔记系统源码.zip

    android移植到特定平台学习笔记

    android移植到Cortex-A8平台,手把手开发步骤,从安装编译器,配置环境变量,编译uboot,kernel,android文件系统详细步骤和修改的文件。最后是将镜像烧入SD卡等详细步骤!好东西不容错过

    Java基础学习笔记(印象笔记)

    Java基础学习笔记(印象笔记) Java 是一种广泛使用的面向对象编程语言,最初由 Sun Microsystems(现为 Oracle Corporation)于1995年发布。它具有简单、易学、可移植、安全和高性能等特点。 Java 是一种跨平台语言...

Global site tag (gtag.js) - Google Analytics