- 浏览: 261357 次
- 性别:
- 来自: 济南
文章分类
- 全部博客 (303)
- c (31)
- c++ (16)
- java (18)
- c# (1)
- python (3)
- java web (6)
- oracle (7)
- sqlserver (2)
- mysql (2)
- android (24)
- android系统 (15)
- android多媒体部分 (15)
- android游戏 (12)
- linux (26)
- javaScript (1)
- ajax (1)
- node JS (2)
- html (5)
- apache (3)
- jboss (1)
- weblogic (0)
- 通信协议 (10)
- 云计算 (1)
- 分布式 (5)
- ejb (1)
- webservice (5)
- 设计模式 (16)
- JNI (6)
- swing (13)
- 版本控制 (1)
- UML (1)
- xml (4)
- spring (5)
- hibernate (5)
- struts1 (3)
- struts2 (4)
- ibatis (0)
- tomcat (2)
- 心得体会 (1)
- css (1)
- 嵌入式 (41)
- arm体系结构 (10)
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的完成
所以完了
发表评论
-
android系统学习笔记一
2012-09-03 15:01 9081.android的系统架构(linux2.6内核) Lin ... -
android系统学习笔记二
2012-09-03 15:03 914android的linux内核和驱动程序 Androidr专 ... -
android系统学习笔记三
2012-09-03 15:05 840第四章android的底层库和程序 知识点: And ... -
android系统学习笔记四
2012-09-03 15:07 1134Android的GUI系统 AndroidGUI系统综 ... -
android系统学习笔记五
2012-09-03 15:12 2201android中的audio系统 Audo系统主要分如下几 ... -
android系统学习笔记六
2012-09-03 15:16 2221android的多媒体系统 ... -
android系统学习笔记七
2012-09-03 15:18 740Android电话部分综述 主 ... -
android系统学习八
2012-09-03 15:19 755Android的联接部分 Wifi部分 Wif ... -
android系统学习笔记九
2012-09-03 15:21 738蓝牙部分 蓝牙协议栈1.11.22.02.13.0 异步数 ... -
android系统学习笔记十二
2012-09-03 15:23 1019Android的传感器系统 ... -
Android编译系统详解(一)
2012-09-10 13:45 829+++++++++++++++++++++++++++++ ... -
android----ServiceManager
2012-09-18 00:33 4319serviceManager 在c++层如何使用servi ... -
android 自定义核心服务
2012-09-18 23:27 797native service zygote 服务 kern ... -
android系统移植学习笔记一
2012-09-21 16:08 627系统框架 applicationjava应用程序 ...
相关推荐
Android学习笔记是Android开发者的必读书籍,书中涵盖了Android系统架构、Activity、Intent、资源管理等多方面的知识。本笔记对应的学习资源《第一行代码》是Android开发者的入门必读书籍,书中系统地介绍了Android...
Android基础学习笔记主要涵盖了一系列关于Android开发的基本概念和关键组件,以下是这些知识点的详细解析: 1. **Activity**: 是Android应用程序的基本单元,它代表用户在屏幕上看到的一个界面。每个Activity都必须...
这篇学习笔记将引导新手入门,通过创建第一个简单的案例来了解Android Studio的基本操作。 首先,让我们了解一下Android Studio的核心功能。它基于IntelliJ IDEA,具备代码自动补全、重构、调试等强大的开发特性。...
Android Activity学习笔记 Android Activity是Android系统中最基本的组件之一,它负责处理用户交互和显示用户界面。本文将深入讲解Activity的生命周期、Activity之间的数据交互、Activity启动模式、Task和BackStack...
- Android系统基于Linux系统开发,拥有开放源码。 - Android系统框架由多个组件构成,其中包括Activity、Intent、Service、ContentProvider、View和BroadcastReceiver。 - Activity作为组件容器,主要负责用户...
根据给定的信息,我们可以从Java和Android学习笔记中提取出一系列重要的知识点,下面将逐一进行详细解释。 ### Java基础知识 #### 1. 命令行基础操作 - **`javacmd`**: 这个命令是Java命令行工具的一部分,用于...
### Android学习笔记知识点详解 #### 一、简介与背景 Android作为全球最受欢迎的移动操作系统之一,自2007年谷歌发布以来,迅速占领市场并持续引领移动技术的发展。随着移动互联网的兴起和发展,Android应用开发...
### Android学习笔记——从HelloWorld开始 #### 一、Google的Android SDK介绍 自从Google发布了Android SDK以来,这款开源移动操作系统迅速吸引了众多开发者的关注。Android SDK为开发者提供了丰富的工具和API,...
Android全程学习笔记旨在提供一个详尽且全面的指南,涵盖了Android开发中的关键技术点和实践案例。以下是关于Android开发的一些核心知识点: 1. **第一个Android应用**:开发Android应用的起点通常是从创建并运行你...
这个"Android_学习笔记.zip"文件很可能包含了一个详细的Android开发学习路径和关键知识点的总结。下面将基于这个主题,详细讲解Android开发的一些核心概念和技术。 首先,Android是Google开发的一款开源操作系统,...
这篇学习笔记主要涵盖了关于布局的一些基本概念,特别是`fill_parent`和`wrap_content`这两种尺寸指定方式,以及如何通过XML布局文件来精确控制组件的位置。 首先,`fill_parent`和`wrap_content`是Android布局中的...
在Android系统相关学习笔记中,我们可以深入探讨这个广泛而复杂的移动操作系统的核心概念和技术。Android以其开源性和灵活性,吸引了大量的开发者和爱好者。以下是一些关键的知识点: 1. **Android架构**:Android...
【Android学习笔记详解】 在移动应用开发领域,Android操作系统占据着重要的地位,为开发者提供了...通过系统学习并实践其中的内容,你将能够逐步掌握Android开发的核心技能,为你的Android开发者之路打下坚实的基础。
这篇学习笔记将深入探讨PreferenceActivity的使用方法、功能以及与源码相关的知识。 首先,PreferenceActivity是Android SDK提供的一种特殊类型的Activity,它允许开发者快速构建具有可配置选项的界面,类似于系统...
### Android开发学习笔记知识点梳理 #### 一、Android概述与架构 - **定义与发布**:Android是由Google在2007年11月5日宣布的基于Linux平台的开源手机操作系统。它不仅用于智能手机,还广泛应用于平板电脑、可穿戴...