AndroidLocationService分析

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

AndroidLocationService分析
由于各种原因,⽼师希望我学习Android系统源码以应对可能参与的项⽬。

我只好深⼊曹营,刺探军情了。

定位服务是⼿机上最常⽤的功能之⼀,据说也是相对⽐较简单的服务,所以从这⾥⼊⼿。

其他系统服务的架构都是类似的。

明⽩其中⼀个之后,再去理解其他的会容易得多。

下⾯以 Android 源码为基础,⼤致分析了 Android 系统中定位服务的架构和实现。

版本是6.0.1。

⼀. 应⽤层:
1.在App中调⽤位置服务
在Android App中使⽤定位服务,要先向系统请求⼀个LocationManager实例,
LocationManager mLocationManager = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE);
然后⽤Criteria对其进⾏设置,获取⼀个provider,provider有3种基本定位类型 network/gps/passive
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
...
String provider = mLocationManager.getBestProvider(criteria, true);
(1)LocationManager利⽤provider直接获取⼀个最新的位置信息
Location location = mLocationManager.getLastKnownLocation(provider);
(2)使⽤事件绑定的⽅式,获取更新的位置信息
LocationListener{
...
public void onLocationChanged(Location location)
}
⼆.框架层
2.LocationManager类的实现(/frameworks/base/location/java/android/location/LocationManager.java)
其代码的主要作⽤是访问系统位置服务LocationManagerService
关键成员
private final ILocationManager mService;
构造器
public LocationManager(Context context, ILocationManager service);
ILocationManager与系统服务通信的接⼝
mService=Service;
如getProviders⽅法,实际是通过mService成员请求系统服务响应这个⽅法
public List<String> getProviders(boolean enabledOnly) {
...
return mService.getProviders(null, enabledOnly);
}
3.接⼝定义(/frameworks/base/location/java/android/location/ILocationManager.aidl)
通过aidl定义通信接⼝,与系统位置服务进⾏进程间通信icp(涉及binder)
4.LocationManagerService的实现(/frameworks/base/services/core/java/com/android/server/LocationManagerService.java)
系统位置服务的实现,包括实现LocationManager调⽤的接⼝

public List<String> getProviders(Criteria criteria, boolean enabledOnly)
public Location getLastLocation(LocationRequest request, String packageName)
...
在LocationManagerService中主要是有两种定位⽅式,⼀种通过⽹络,⼀种通过GPS模块。

通过GPS模块定位的是GpsLocationProvider。

5.GpsLocationProvider(frameworks/base/services/core/java/com/android/server/location/GpsLocationProvider.java)
核⼼的涉及定位的⽅法是native的,通过JNI与HAL层C++语⾔函数交互
如这个注⼊⼀条位置信息的函数,接下来主要以他为线索。

private native void native_inject_location(double latitude, double longitude, float accuracy);
三、硬件抽象层(HAL)
6.GpsLocationProvider 本地⽅法在HAL层的实现
(/frameworks/base/services/core/jni/com_android_server_location_GpsLocationProvider.cpp)
#include "hardware/hardware.h"
#include "hardware/gps.h" //这⾥的hardware⽬录为/hardware/libhardware/include/hardware/
...
上⾯第5点中native_inject_location⽅法对应的实现
static void android_location_GpsLocationProvider_inject_location(JNIEnv* /* env */,
jobject /* obj */, jdouble latitude, jdouble longitude, jfloat accuracy)
{
if (sGpsInterface)
sGpsInterface->inject_location(latitude, longitude, accuracy);
}
可以看出这⾥是通过sGpsInterface调⽤下⼀层函数去实现,他是⼀个GpsInterface结构体指针,
static const GpsInterface* sGpsInterface = NULL;
GpsInterface结构体定义在gps.h中
结构体包含函数指针,则sGpsInterface引⽤的实例包含函数的具体实现
err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&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;
//在这⾥获得了device提供的具体的sGpsInterface
sGpsInterface = gps_device->get_gps_interface(gps_device);
}
}
7.上⾯提到的gps.h(/hardware/libhardware/include/hardware/gps.h)
GpsInterface的定义
typedef struct {
...
/** Injects the current time. */
int (*inject_time)(GpsUtcTime time, int64_t timeReference,
int uncertainty);
/** Injects current location from another location 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);
...
} GpsInterface;
四、⾼通的⼀个实现
硬件⼚商主要的⼯作室引⽤gps.h, 实现⼀个gps.c,把GpsInterface等内容实现了。

这⾥分析⼀下⾼通的⼀个实现。

8.gps.c(/hardware/qcom/gps/loc_api/libloc_api_50001/gps.c)
#include <hardware/gps.h>
...
extern const GpsInterface* get_gps_interface(); //外部函数
const GpsInterface* gps__get_gps_interface(struct gps_device_t* dev)
{
return get_gps_interface();
//在⾼通的实现中,第6点中的gps_device->get_gps_interface()调⽤的函数来⾃于此,此处 //返回的函数指针是⼀个外部函数,该外部函数实际在9.2中实现
}
...
//dev结构体
struct gps_device_t *dev = (struct gps_device_t *) malloc(sizeof(struct gps_device_t)); ...
//给dev结构体get_gps_interface的函数指针指向前⾯⾼通实现的函数。

dev->get_gps_interface = gps__get_gps_interface;
9.loc.cpp(/hardware/qcom/gps/loc_api/libloc_api_50001/loc.cpp)
9.1
//这⾥定义的静态函数,供同⼀个⽂件⾥的sLocEngInterface使⽤
static int loc_init(GpsCallbacks* callbacks);
static int loc_start();
static int loc_inject_time(GpsUtcTime time, int64_t timeReference, int uncertainty);
static int loc_inject_location(double latitude, double longitude, float accuracy);
...
//在gps.h中的GpsInterface,在这⾥被实现成了sLocEngInterface
static const GpsInterface sLocEngInterface =
{
sizeof(GpsInterface),
loc_init,
loc_start,
loc_inject_time,
loc_inject_location,
...
};
9.2
// for gps.c
extern "C" const GpsInterface* get_gps_interface(){
...
}
9.3
这个⽂件⾥的静态函数的具体实现
static int loc_inject_location(double latitude, double longitude, float accuracy)
{
ENTRY_LOG();
int ret_val = 0;
ret_val = loc_eng_inject_location(loc_afw_data, latitude, longitude, accuracy);
//这⾥⼜是依靠调⽤其它函数,还要继续深挖到 loc_eng,在第10点
EXIT_LOG(%d, ret_val);
return ret_val;
}
10.loc_eng.cpp(/hardware/qcom/gps/loc_api/libloc_api_50001/loc_eng.cpp)
int loc_eng_inject_location(loc_eng_data_s_type &loc_eng_data, double latitude,
double longitude, float accuracy)
{
ENTRY_LOG_CALLFLOW();
INIT_CHECK(loc_eng_data.adapter, return -1);
LocEngAdapter* adapter = loc_eng_data.adapter;
if(adapter->mSupportsPositionInjection)
{
adapter->sendMsg(new LocEngInjectLocation(adapter, latitude, longitude,
accuracy));
//这⾥发出了消息
}
EXIT_LOG(%d, 0);
return 0;
}
再往下就得是Linux kernel⾥⾯GPS模块的写的驱动程序了,应该通过UART,传送基本的数据和控制命令,我就没去看了。

第⼀次看Android源码,简单分析,⽔平有限,如有错漏,还请包涵。

相关文档
最新文档