GPS 详解
系统启动过程中,通过Systemserver启动LocationManagerService
SystemServer.java 路径 frameworks\base\services\java\com\android\server
private void startOtherServices() {
try {
Slog.i(TAG, "LocationManager");
location = newLocationManagerService(context);
ServiceManager.addService(Context.LOCATION_SERVICE, location);
} catch (Throwable e) {
reportWtf("startingLocation Manager", e);
}
}
systemserver 实例化LocationManagerService后,会调用systemrunning。
public void systemRunning() {
loadProvidersLocked(); //实例化GpsLocationProvider
mContext.getContentResolver().registerContentObserver( //监听数据库变化
Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED),true,
newContentObserver(mLocationHandler) {
@Override
public voidonChange(boolean selfChange) {
synchronized (mLock) {
updateProvidersLocked();
}
}
}, UserHandle.USER_ALL);
}
private void loadProvidersLocked() {
GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext,this,
mLocationHandler.getLooper());
}
实例化GpsLocationProvider.JAVA
该类包含了一些native方法,ui的一些操作都是通过provider 调用本地方法。进而调用hal,实现与driver的交互。
同时监听settings 数据库(settings.Secure.LOCATION_PROVIDERS_ALLOWED).
Native方法通过jni方式调用到com_android_server_location_GpsLocationProvider.cpp
路径 frameworks\base\services\core\jni
以init_native 为例。
static voidandroid_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclassclazz) {
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;
sGpsInterface = gps_device->get_gps_interface(gps_device);
}
}
}
通过open的方式获取hal层的句柄device. 通过函数指针get_gps_interface,获取hal层的系列接口指针sGpsInterface。
Gps.c 路径 hardware\qcom\gps\loc_api\libloc_api_50001
static struct hw_module_methods_tgps_module_methods = {
.open = open_gps
};
static int open_gps(const structhw_module_t* module, char const* name,
struct hw_device_t** device)
{
struct gps_device_t *dev = (struct gps_device_t *) malloc(sizeof(structgps_device_t));
if(dev == NULL)
return -1;
memset(dev, 0, sizeof(*dev));
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->common.version = 0;
dev->common.module = (struct hw_module_t*)module;
dev->get_gps_interface = gps__get_gps_interface;
*device = (struct hw_device_t*)dev;
return 0;
}
const GpsInterface* gps__get_gps_interface(structgps_device_t* dev)
{
return get_gps_interface();
}
Loc.cpp 路径hardware\qcom\gps\loc_api\libloc_api_50001
extern "C" const GpsInterface*get_gps_interface()
{
return &sLocEngInterface;
}
static const GpsInterface sLocEngInterface=
{
sizeof(GpsInterface),
loc_init,
loc_start,
loc_stop,
loc_cleanup,
loc_inject_time,
loc_inject_location,
loc_delete_aiding_data,
loc_set_position_mode,
loc_get_extension
};
如此可以看到,hal层的系列接口已经暴漏给上层,从而进行与driver交互。
如何打开gps?很简单就是更改数据库即可。以源码为例
LocationSettingsBase.java packages\apps\settings\src\com\android\settings\location
public void setLocationMode(int mode) {
Settings.Secure.putInt(getContentResolver(),Settings.Secure.LOCATION_MODE, mode);
追踪代码可知,最终替换为LOCATION_PROVIDERS_ALLOWED
}
数据库更新,LocationManagerService 检测到数据库变化调用
public voidonChange(boolean selfChange) {
synchronized (mLock) {
updateProvidersLocked();
}
}
private void updateProvidersLocked() {
updateProviderListenersLocked(name, true);
}
private voidupdateProviderListenersLocked(String provider, boolean enabled) {
LocationProviderInterface p = mProvidersByName.get(provider);
p.enable();
}
具体实现在GpsLocationProvider .java frameworks\base\services\core\java\com\android\server\location
Jni ---hal---driver 最终实现与driver交互