《AndroidGPS架构分析.doc》由会员分享,可在线阅读,更多相关《AndroidGPS架构分析.doc(32页珍藏版)》请在三一办公上搜索。
1、以下摘自Daniel Wood的博客:Android GPS架构分析(gps启动过程图)Gps启动过程图(基于Google Android 2.2代码)下面再贴一张从GoogleI/O大会文档里面截来的图Android GPS架构分析-previewAndroid GPS架构分析Daniel Wood 20101222转载时请注明出处和作者文章出处:作者:Daniel Wood-看Android的GPS模块有两个月了吧,终于可以写点东西出来。首先来看看GPS模块的代码结构:Framework:1.frameworks/base/location/java/android/location这里主
2、要是用来被App调用的,API包是android.location。2.frameworks/base/location/java/com/android/internal/location这个目录是Framework对Location服务的内部实现。3.frameworkservicesjavacomandroidserver这个目录只有一个文件|- LocationManagerService.java是Location服务对内部实现的一种封装。JNI:frameworks/base/core/jni/android_location_GpsLocationProvider.cppJNI层
3、只有一个文件,起到承上启下的作用。上层承接Framework,下层调用HAL层具体硬件抽象实现。HAL:Hardware Abstract Layer 硬件抽象层hardwarelibhardware_legacygpshardwarelibhardware_legacyincludehardware_legacygps.hHAL层相当于一个linux应用程序接口,通过open,close等操作,操作硬件设备。Android的源代码只实现了模拟器的gps接口,具体在文件gps_qemu.c中。在2.2版本中提供了对QCOM公司的gps的实现,在以下目录:hardwareqcom下面介绍几个重要
4、的数据结构:1. GpsInterface接口是gps模块中最重要的数据结构,它是底层驱动实现的接口,如果要porting到自己的板子上,就需要实现这些接口。该接口的定义在gps.h中,模拟器实现在gps_qemu.c中。/* Represents the standard GPS interface. */typedef struct /* Opens the interface and provides the callback routines* to the implemenation of this interface.*/int (*init)( GpsCallbacks* cal
5、lbacks );/* Starts navigating. */int (*start)( void );/* Stops navigating. */int (*stop)( void );/* Closes the interface. */void (*cleanup)( void );/* Injects the current time. */int (*inject_time)(GpsUtcTime time, int64_t timeReference,int uncertainty);/* Injects current location from another locat
6、ion provider* (typically cell ID).* latitude and longitude are measured in degrees* expected accuracy is measured in meters*/int (*inject_location)(double latitude, double longitude, float accuracy);/* Specifies that the next call to start will not use the* information defined in the flags. GPS_DELE
7、TE_ALL is passed for* a cold start.*/void (*delete_aiding_data)(GpsAidingData flags);/* fix_frequency represents the time between fixes in seconds.* Set fix_frequency to zero for a single-shot fix.*/int (*set_position_mode)(GpsPositionMode mode, int fix_frequency);/* Get a pointer to extension infor
8、mation. */const void* (*get_extension)(const char* name); GpsInterface;2. GpsCallbacks回调函数 这个是回调函数结构体,定义也在gps.h中。它们的实现是在android_location_GpsLocationProvider.cpp中,google已经实现了,我们不需要做任何动作。/* GPS callback structure. */typedef struct gps_location_callback location_cb;gps_status_callback status_cb;gps_sv_
9、status_callback sv_status_cb;gps_nmea_callback nmea_cb; GpsCallbacks;/* Callback with location information. */typedef void (* gps_location_callback)(GpsLocation* location);/* Callback with status information. */typedef void (* gps_status_callback)(GpsStatus* status);/* Callback with SV status inform
10、ation. */typedef void (* gps_sv_status_callback)(GpsSvStatus* sv_info);/* Callback for reporting NMEA sentences. */typedef void (* gps_nmea_callback)(GpsUtcTime timestamp, const char* nmea, int length);3. GpsLocation表示Locatin数据信息,底层驱动获得Location的raw信息,通常是nmea码,然后通过解析就得到了location信息。/* Represents a loc
11、ation. */typedef struct /* Contains GpsLocationFlags bits. */uint16_t flags;/* Represents latitude in degrees. */double latitude;/* Represents longitude in degrees. */double longitude;/* Represents altitude in meters above the WGS 84 reference* ellipsoid. */double altitude;/* Represents speed in met
12、ers per second. */float speed;/* Represents heading in degrees. */float bearing;/* Represents expected accuracy in meters. */float accuracy;/* Timestamp for the location fix. */GpsUtcTime timestamp; GpsLocation;Android GPS架构分析(一)Android GPS架构分析Daniel Wood 20101222转载时请注明出处和作者文章出处:作者:Daniel Wood- 介绍完了
13、主体代码结构以及重要的数据结构后,下面来看看gps的定位服务(LocationManager)的启动过程。我总是喜欢追本溯源地从源头去认识事物。因为“人之初,性本善”,从事物的本性去认识事物。LocationManager 这项服务是在SystemServer.java 中启动的,也就是系统启动之后,这个服务就已经启动了:systemServer.java frameworkbaseservicesjavacomandroidserver在SystemServer.java的init2函数中启动了一个线程来注册Android的诸多服务,如:Bluetooth Service,NetworkMa
14、nagement Service,Notification Manager等,当然也包括Location Service。SystemServer.java frameworksbaseservicesjavacomandroidserverpublic static final void init2() Slog.i(TAG, Entered the Android system server!);Thread thr = new ServerThread();thr.setName(android.server.ServerThread);thr.start();在ServerThread
15、线程的run函数中LocationManager服务的代码段如下:2.1版本try Log.i(TAG, Location Manager);ServiceManager.addService(Context.LOCATION_SERVICE, new LocationManagerService(context); catch (Throwable e) Log.e(TAG, Failure starting Location Manager, e);2.2的代码中代码段如下形式:try Slog.i(TAG, Location Manager);location = new Locatio
16、nManagerService(context);ServiceManager.addService(Context.LOCATION_SERVICE, location); catch (Throwable e) Slog.e(TAG, Failure starting Location Manager 在run函数的后半部分,是服务对系统的反馈,就是systemReady()函数。 LocationManager服务的反馈函数如下:if (locationF != null) locationF.systemReady();其中的locationF 是LocationManagerServ
17、ice的final类型,就是一旦赋值,不能更改。final LocationManagerService locationF = location;哇!locationManager这项服务的反馈机制只在2.2的代码里面才有啊。2.1中的反馈机制中并没有locationManager(当然有其他的服务反馈)。而在2.1版本中LocationManagerService的构造函数如下:LocationManagerService.java frameworksbaseservicesjavacomandroidserverpublic LocationManagerService(Context
18、 context) super();mContext = context;Thread thread = new Thread(null, this, LocationManagerService);thread.start();if (LOCAL_LOGV) Log.v(TAG, Constructed LocationManager Service);2.2版本 public LocationManagerService(Context context) super();mContext = context;if (LOCAL_LOGV) Slog.v(TAG, Constructed L
19、ocationManager Service);2.1是在构造函数的时候就启动一个自身服务线程。见构造函数。2.2是在反馈机制中通过systemReady函数启动自身服务线程。如下:void systemReady() / we defer starting up the service until the system is readyThread thread = new Thread(null, this, LocationManagerService);thread.start();通过线程run函数,调用initialize函数:public void run()Process.se
20、tThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);Looper.prepare();mLocationHandler = new LocationWorkerHandler();initialize();Looper.loop();发表于: 2010-12-22,修改于: 2010-12-24 09:37, Android GPS架构分析(二)Android GPS架构分析Daniel Wood 20101222转载时请注明出处和作者文章出处:作者:Daniel Wood-initialize函数LocationManagerService
21、.javaframeworksbaseservicesjavacomandroidserverprivate void initialize() / Create a wake lock, needs to be done before calling loadProviders() belowPowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WA
22、KE_LOCK, WAKELOCK_KEY);/ Load providersloadProviders(); .initialize函数中最重要的就是loadProviders函数了,该函数调用loadProvidersLocked,然后loadProvidersLocked函数又调用_loadProvidersLocked函数。为什么要这么折腾呢?先来看一部分的_loadProvidersLocked函数:private void _loadProvidersLocked() / Attempt to load real providers firstif (GpsLocationProv
23、ider.isSupported() / Create a gps location providerGpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);mGpsStatusProvider = gpsProvider.getGpsStatusProvider();mNetInitiatedListener = gpsProvider.getNetInitiatedListener();addProvider(gpsProvider);mGpsLocationProvider = gpsProvid
24、er; .注意这个if语句,狠重要,因为在这个语句中得到了HAL层的GPS接口GpsInterface。就是通过调用GpsLocationProvider的isSupported()函数才调用到gps.cpphardware/libhardware_legacy/gps中的gps_get_interface()。这个isSupported函数才是第一个吃螃蟹的人。(而不是JNI层的init函数,这个下面会提到)。GpsLocationProvider.cpp frameworksbaselocationjavacomandroidinternallocationpublic static bo
25、olean isSupported() return native_is_supported();然而isSupported只有一句话,果然是高手,一击必中。然后就调用native方法,也就是JNI层定义的方法。native_is_supported函数对于JNI层是android_location_GpsLocationProvider_is_supported方法。android_location_GpsLocationProvider.cpp frameworksbasecorejnistatic jboolean android_location_GpsLocationProvider
26、_is_supported(JNIEnv* env, jclass clazz) if (!sGpsInterface)sGpsInterface = gps_get_interface();return (sGpsInterface != NULL);前面已经提到JNI起到承上启下的作用,gps_get_interface函数属于HAL层的调用,在文件gps.cpp中。gps.cpp hardwarelibhardware_legacygpsconst GpsInterface*gps_get_interface()if (sGpsInterface = NULL)gps_find_hard
27、ware();return sGpsInterface;然后通过gps_find_hardware函数去得到gps接口,下面只模拟器中的gpsinterface。static voidgps_find_hardware( void )#ifdef HAVE_QEMU_GPS_HARDWAREif (qemu_check() sGpsInterface = gps_get_qemu_interface();if (sGpsInterface) LOGD(using QEMU GPS Hardware emulationn);return;#endif#ifdef HAVE_GPS_HARDWAR
28、EsGpsInterface = gps_get_hardware_interface();#endifif (!sGpsInterface)LOGD(no GPS hardware on this devicen);gps_qemu.c hardwarelibhardware_legacygpsconst GpsInterface* gps_get_qemu_interface()return &qemuGpsInterface;qemuGpsInterface的整体实现就在文件gps_qemu.c中。static const GpsInterface qemuGpsInterface =
29、qemu_gps_init,qemu_gps_start,qemu_gps_stop,qemu_gps_cleanup,qemu_gps_inject_time,qemu_gps_inject_location,qemu_gps_delete_aiding_data,qemu_gps_set_position_mode,qemu_gps_get_extension,;发表于: 2010-12-22,修改于: 2010-12-24 10:42,已浏览574次,Android GPS架构分析(三)Android GPS架构分析Daniel Wood 20101222转载时请注明出处和作者文章出处:
30、作者:Daniel Wood-在底层得到gps的接口之后, if (GpsLocationProvider.isSupported()(在文件LocationManagerService.java中调用)语句得到true,然后进行下一步操作,在这里new了一个GpsLocationProvider对象。代码如下:GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);注意GpsLocationProvider构造函数里面的两个参数:mContext, this。下面来看看GpsLocationProvi
31、der的构造函数的前面几句:public GpsLocationProvider(Context context, ILocationManager locationManager) mContext = context;mLocationManager = locationManager;mNIHandler = new GpsNetInitiatedHandler(context, this); . 在GpsLocationProvider类里面的成员变量mLocationManager是构造函数的第二个参数,就是说是LocationManagerService对象。这一点在这里先明确。接
32、着看_loadProvidersLocked函数。private void _loadProvidersLocked() / Attempt to load real providers firstif (GpsLocationProvider.isSupported() / Create a gps location providerGpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);mGpsStatusProvider = gpsProvider.getGpsStatusProvider();m
33、NetInitiatedListener = gpsProvider.getNetInitiatedListener();addProvider(gpsProvider);mGpsLocationProvider = gpsProvider;/ create a passive location provider, which is always enabledPassiveProvider passiveProvider = new PassiveProvider(this);addProvider(passiveProvider);mEnabledProviders.add(passive
34、Provider.getName();/ initialize external network location and geocoder servicesResources resources = mContext.getResources();String serviceName = resources.getString(com.android.internal.R.string.config_networkLocationProvider);if (serviceName != null) mNetworkLocationProvider =new LocationProviderP
35、roxy(mContext, LocationManager.NETWORK_PROVIDER,serviceName, mLocationHandler);addProvider(mNetworkLocationProvider);serviceName = resources.getString(com.android.internal.R.string.config_geocodeProvider);if (serviceName != null) mGeocodeProvider = new GeocoderProxy(mContext, serviceName);updateProv
36、idersLocked();在构造完GpsLocationProvider之后将其add到全局变量ArrayList mProviders中,备以后调用。在2.2中采取了一种PassiveProvider的类,而在2.1中是通过LocationProviderProxy代理类的方式。2.1中LocationProviderProxy作为GpsLocationProvider的代理作用在LocationManagerService中,而2.2中的PassiveProvider感觉这个类是个空壳。有待研究。然后启动了nerwork location和geocoder 两个service。但是可惜的
37、是这两个服务都无法启动,因为他们是通过配置文件conifg.xml frameworkbasecoreresresvalues得到服务的名字,然后启动服务的。但是在这个配置文件中,两个服务的名字都是null。conifg.xml frameworkbasecoreresresvaluesnullnull其实这也导致了,在调用GetFromLocationName和GetFromLocation两个函数时提示“Service not Available”,这个google Android 2.2的bug。_loadProvidersLocked函数的最后一句是调用updateProvidersL
38、ocked函数,仍然在LocationManagerServic.java文件中。LocationManagerServic.javaprivate void updateProvidersLocked() for (int i = mProviders.size() - 1; i = 0; i-) LocationProviderInterface p = mProviders.get(i);boolean isEnabled = p.isEnabled();String name = p.getName();boolean shouldBeEnabled = isAllowedBySett
39、ingsLocked(name);if (isEnabled & !shouldBeEnabled) updateProviderListenersLocked(name, false); else if (!isEnabled & shouldBeEnabled) updateProviderListenersLocked(name, true); 从上面_loadProvidersLocked函数的代码来看,在mProviders这个ArrayList 中有两个元素(这一点未求证),一个是gpsProvider,另一个是passiveProvider。gpsProvider是 GpsLoc
40、ationProvider类型的,它的isEnabled函数返回的是false,因为它并没有被enable。而 passiveProvider是PassiveProvider类型,它总是enable的。所以gpsProvider会调用else语句中的updateProviderListenersLocked(name, true)函数。我们主要分析这个else语句,对于passiveProvider不做分析。private void updateProviderListenersLocked(String provider, boolean enabled) int listeners = 0;LocationProviderInterface p = mProvidersByName.get(provider);if (p = null) return;Arra