重要概念
星历表(英文为Ephemeris):星历表本来是用来记录天体特定时刻的位置的。而在GNSS中,星历表则记录了卫星的一些运行参数,它使得我们通过星历表就可以计算出任意时刻的导航卫星的位置和速度。星历表包含了非常详细的卫星轨道和位置信息,所以其数据量较大,传输时间较长。为了克服这个问题,人们设计了星历表的简化集,即历书。
历书(英文为Almanac):历书也包含了卫星的位置等相关信息,不过它是星历数据的简化集,其精度较低。所以,历书数据量较小,传输时间较短
GPS空间段有至少32颗卫星组成,分布在6个轨道上,地球表面任何地方都能被至少4颗GPS卫星信号覆盖(要计算接收器的位置即XYZ坐标需要三颗卫星,而由于接收器时钟和卫星时钟的不同步,所以还需要至少一颗卫星用来计算信号传输时间)
GPS一共使用了三个频段的无线电波来传输数据,L1(民用C/A码,粗略捕获码数据,周期1ms,测距精度2m到3m),L2(军用P/Y码,精测数据,Y代表加密,周期为七天,测距精度为0.3m),L5
GPS信号主要有三部分组成:载波(L1为1574.42MHz,L2为1227.60MHz)、测距码(用来测量卫星和接收器之间距离的信号,又被称为伪随机噪声,C/A和P码)、导航电文(星历,时间)
GPS双频可以同时接收两个不同频率的载波信号,利用不同频率的电磁波在大气电离层传输所造成的延时时间不一致的原理来减少电离层带来的定位误差
AGPS:设备通过通信网络(基站/wifi)下载卫星信息,辅助加速定位,分为MSB模式(手机从AGPS位置服务器下载辅助数据,然后结合GPS卫星信号定位,在本机进行运算算出位置,适合短时间内的连续定位)和MSA模式(手机接收GPS信号,然后将这些伪距离信息传给AGPS位置服务器,服务端计算后将最终位置结果返回给手机,缺点是定位延时大,不适合高速行驶的定位)
源码简析
java层概览:
a.
Android中提供位置服务的相关模块统称为LocationProvider,如果GpsLocationProvider。位置的提供者必须实现LocationProviderInterface接口,这些接口对应的对象实例由LMS管理。Framework实现了PassiveProvider和GpsLocationProvider,运行在System_process中。
b. 系统还支持网络定位(Network Location)方法来获取位置信息。工作原理是某地区的移动通信基站或无线网络AP的位置信息都已事先获取并保存在相关服务提供商的服务器上。当手机使用网络定位时,它首先向服务器查询自己所连接或搜索到的基站位置或AP的位置,然后根据信号的强度推算自己的大致位置。相比GPS定位而言,网络定位速度快,耗电少,适用于室内和室外,但精度较GPS差。Android原生代码并不提供NetworkLocationProvider相关的功能,它一般由第三方应用厂商提供,使用百度公司提供的NetworkLocation_Baidu.apk,由于它们运行在应用程序所在的进程中,所以系统定义了ILocationProviderProxy接口使LMS能管理这些由应用程序提供的位置服务。这些应用的位置服务需要实现LocationProviderBase抽象类
c. FusedLocationProvider 内部将综合GpsLP和NetworkLP的位置信息,然后向使用者提供最符合使用者需求的数据,它运行在FusedLocationProvider.apk所在的进程中
d. 位置信息和地址信息相互转换由第三方应用提供,LMS利用GeocodeProxy和第三方应用中实现IGeocodeProvider的对象交互
LocationManagerService.java 初始化:
a.
systemRunning系统启动后调用,执行初始化工作,获取PackagerManager类(根据UID检测包名),PowerManager类(唤醒),LocationBlacklist类(黑名单),通过loadProvidersLocked函数,加载系统中所有LocationProvider
b. 先创建PassiveProvider。被动provider,假设应用程序A使用GpsLP。GpsLP检测到位置更新后将通知应用程序A。应用程序B如果使用PassiveProvider,当GpsLP更新位置后,它也会触发PassiveProvider以通知应用程序B。也就是说,PassiveProvider自己并不能更新位置信息,而是靠其他LP来触发位置更新的。特别注意,PassiveProvider的位置更新是由LMS接收到其他LP的位置更新通知后主动调用PassiveProvider的updateLocation函数来完成的。目前,PassiveProvider被SystemServer中的TwilightService使用,TwilightService将根据位置信息来计算当前时间是白天还是夜晚。另外,GpsLP也会使用PassiveProvider来接收NeworkLP的位置信息
d. 创建GpsLocationProvider, GpsLP属于真实的位置提供者,所以把它单独保存在mRealProvider中
f. config_locationProviderPackageNames存储了第三方LP的Java包名。 Android原生代码中该值只有一个,为“com.android.location.fused”。 FusedLP对应的源码路径为frameworks/base/packages/FusedLocation。加载应用程序实现的LP服务时,LMS将检查它们的签名信息以及版本信息。目的可能是想提供一种数据一致性的保护机制,举个例子。默认安装的是百度提供的NetworkLocation_baidu.apk,再安装Google的NetworkLocation.apk时,由于二者签名不一致(根据LMS相关代码工的作原理可知,百度的NetworkLP属于config_locationProviderPackageNames指定的,其签名信息将被保存。后续再安装的LP将检查其签名是否和之前保存的签名信息是否一致。 也就是说,后续的LP必须使用NetworkLocation_Baidu或FusedLP相同的签名才能被LMS加载。 而FusedLP属于Android原生应用,一般由手机厂商提供,第三方应用程序不太可能拿到其签名),根据上述信息可知,只有百度旗下或得到它授权的第三方LP才能安装和使用
e.加载NetworkLP(该LP服务由应用程序提供)、FusedLP(由FusedLocation.apk服务,属于系统提供的应用程序。 其内部将使用其他的LP)和GeocodeProvider(由第三方应用程序提供。 一般和NetworkLP位于同一个应用程序中)
备注:LMS通过LocationProviderProxy(简称LPProxy)来加载应用进程中的LocationProvider的,通过调用ServiceWatcher的start实现绑定,主要完成应用签名校验,并根据服务action查找到包名第三方服务代理,通过代理和第三方服务中LocationProvider通信,并启动Provider
f. 添加用户设置定位信息状态监听,根据设置的情况调用对应LP的enable或disable函数
GpsLocationProvider.java
a.ntp时钟同步
b.读取GPS配置文件,PROPERTIES_FILE的位置为“/etc/gps.conf”,指定AGPS LTO(Long Term Orbits)数据的下载地址。 LTO存储了GPS卫星的星历数据,AGPS使用时需要先从服务器上下载一些辅助数据,当周围没有网络时,终端可以利用事先保存的LTO数据来初始化GPS的定位
c.创建监听数据短信、WAP推送短信触发广播,当收到指定的数据短信或WAP推送短信后,checkSmsSuplInit或checkWapSuplInit函数将被调用,将短信的内容传递到GPS HAL层
d.创建ProviderHandler线程,接收来自NetworkLP的位置更新通知当GpsLP收到来自NetworkLP的位置信息后,将把它们传给GPS HAL层去处理
启动GPS调用流程:GpsLP主要通过调用native函数集中的几个函数来初始化底层GPS模块,当GPS模块启动成功后,GPSHAL层将通过JNI回调函数通知GpsLP底层GPS引擎的工作能力,比如连续定位,AGPS定位,单次定位
HAL层
对应动态库为/system/lib/gps.XXX.so,如gps.exdroid.so几大厂商都没有公开其GPSHAL层的实现,高通在其开源的QRD代码中提供了高通平台GPS HAL层模块的实现,但高通平台HAL层实现采用的是C/S架构。 GPS HAL模块仅仅将上层请求转成QMI(QC MSM Interface)消息并发送给相关服务去处理
AGPS:
原生的AGPS的处理逻辑也集中在GpsLocationProvider.java中,AGPS需要使用移动网络,所以早在GpsLP初始时,GpsLP就注册了对CONNECTIVITY_ACTION广播的监听。 该广播事件由ConnectivityService发送,并且属于Sticky的广播,收到广播后,获取网络状态及信息,并将这些信息传递到GPS HAL层,然后如果当前有可用网络,则GpsLP将获取NTP时间以及下载Xtra数据
转载自原文链接, 如需删除请联系管理员。
原文链接:Android GPS模块总结,转载请注明来源!