1. 概述
在android系统中,GPS对应的系统服务为LocationManagerService,本文主要论述LocationManagerService服务的启动以及初始化过程。
SystemServer.java的startOtherServices方法中添加LocationManagerService方法的代码如下,
location = new LocationManagerService(context);
ServiceManager.addService(Context.LOCATION_SERVICE, location);
apk中获取gps服务代理的代码如下,
mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
当然, LocationManager只是系统服务的一个代理。
添加gps服务到系统之后, SystemServer.java的startOtherServices方法中
locationF.systemRunning();
调用LocationManagerService的systemRunning方法,完成LocationManagerService服务的初始化。
2. 回调方法的实现
当然在调用systemRunning之前,在添加到系统过程中,会调用LocationManagerService的构造方法,构造方法如下,
mContext = context; //传入系统服务进程上下文
systemRunning方法中会调用loadProvidersLocked方法,
loadProvidersLocked();
updateProvidersLocked();
loadProvidersLocked方法主要是添加设备上支持的GPS定位Provider,
if (GpsLocationProvider.isSupported()) {
// Create a gps location provider
GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this,
mLocationHandler.getLooper());
mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
mNetInitiatedListener = gpsProvider.getNetInitiatedListener();
addProviderLocked(gpsProvider);
mRealProviders.put(LocationManager.GPS_PROVIDER, gpsProvider);
mGpsMeasurementsProvider = gpsProvider.getGpsMeasurementsProvider();
mGpsNavigationMessageProvider = gpsProvider.getGpsNavigationMessageProvider();
mGpsGeofenceProxy = gpsProvider.getGpsGeofenceProxy();
}
设备如果支持GpsLocationProvider,就会新建GpsLocationProvider对象,然后添加到mProviders和mProvidersByName等list中。
在这里分为3个步骤:
-
isSupported方法的判断。
-
updateProvidersLocked方法。
在这个章节,主要论述回调方法的实现以及isSupported方法,下个章节论述updateProvidersLocked方法。
在GpsLocationProvider的构造方法和isSupported之前,会调用class_init_native方法,
static { class_init_native(); }
该方法是一个native方法,
private static native void class_init_native();
GpsLocationProvider.java对应的C/C++文件为com_android_server_location_GpsLocationProvider.cpp。
2.1 Framework调用JNI层方法
GpsLocationProvider.java中调用的native方法较多,部分如下,
com_android_server_location_GpsLocationProvider.cpp的sMethods中详细的列举了对应的native方法,部分如下,
{"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native},
{"native_is_supported", "()Z", (void*)android_location_GpsLocationProvider_is_supported},
{"native_is_agps_ril_supported", "()Z", (void*)android_location_GpsLocationProvider_is_agps_ril_supported},
•••
这样Java上层就可以通过JNI调用natvie的方法了。
2.2 JNI层调用Framework方法
com_android_server_location_GpsLocationProvider还定义着对GpsLocationProvide.java的回调方法。部分定义如下,
static jmethodID method_reportLocation;
static jmethodID method_reportStatus;
static jmethodID method_reportSvStatus;
•••
这些回调方法都在android_location_GpsLocationProvider_class_init_native方法中进行赋值,部分代码如下,
method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");
•••
因此,method_reportLocation 对应GpsLocationProvide.java的reportLocation方法。
这样com_android_server_location_GpsLocationProvider就可以回调Java方法了。
2.3 JNI层调用gps库方法
com_android_server_location_GpsLocationProvider的class_init_native方法中获取gps.so库中的sGpsInterface结构代码如下,
hw_module_t* module;
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;
sGpsInterface = gps_device->get_gps_interface(gps_device);
}
}
首先调用hw_get_module方法加载gps相关的so库,获取hw_module_t结构体。
然后利用该结构体打开so库,获取hw_device_t结构体,
最后利用hw_device_t结构体获取GpsInterface结构体。
这样,com_android_server_location_GpsLocationProvider就可以通过GpsInterface结构体调用so库中的方法了。
根据 HAL 加载so文章分析,
GpsInterface结构体指向hardware\qcom\gps\loc_api\libloc_api_50001中loc.cpp的sLocEngInterface。除了GpsInterface结构体之外,so库中还定义了其他大量的结构体(包含回调方法以及变量供上层调用),因此com_android_server_location_GpsLocationProvider还需要获取,
static const GpsInterface* sGpsInterface = NULL;
static const GpsXtraInterface* sGpsXtraInterface = NULL;
static const AGpsInterface* sAGpsInterface = NULL;
static const GpsNiInterface* sGpsNiInterface = NULL;
static const GpsDebugInterface* sGpsDebugInterface = NULL;
static const AGpsRilInterface* sAGpsRilInterface = NULL;
static const GpsGeofencingInterface* sGpsGeofencingInterface = NULL;
static const GpsMeasurementInterface* sGpsMeasurementInterface = NULL;
static const GpsNavigationMessageInterface* sGpsNavigationMessageInterface = NULL;
static const GnssConfigurationInterface* sGnssConfigurationInterface = NULL;
这些结构体都通过GpsInterface的get_extension方法获取,不同方法只是以字符区分,
sGpsXtraInterface = (const GpsXtraInterface*)sGpsInterface->get_extension(GPS_XTRA_INTERFACE);
•••
这些字符都定义在gps.h文件中,
#define GPS_XTRA_INTERFACE "gps-xtra"
#define GPS_DEBUG_INTERFACE "gps-debug"
#define AGPS_INTERFACE "agps"
•••
loc.cpp的loc_get_extension方法如下,
const void* loc_get_extension(const char* name)
{
ENTRY_LOG();
const void* ret_val = NULL;
LOC_LOGD("%s:%d] For Interface = %s\n",__func__, __LINE__, name);
if (strcmp(name, GPS_XTRA_INTERFACE) == 0)
{
ret_val = &sLocEngXTRAInterface;
}
else if (strcmp(name, AGPS_INTERFACE) == 0)
{
ret_val = &sLocEngAGpsInterface;
}
•••
EXIT_LOG(%p, ret_val);
return ret_val;
}
根据不同的字符返回不同的结构体。
这些结构体和GpsInterface完全一样,在gps.h文件中定义,然后在loc.cpp中实现。
这样, com_android_server_location_GpsLocationProvider就可以通过这些结构体调用so库中的方法了。
2.4 gps库调用JNI层方法
com_android_server_location_GpsLocationProvider.cpp中定义了一些gps库调回调的结构体,
例如sGpsCallbacks,主要是gps库中上传数据的信息,定义如下,
GpsCallbacks sGpsCallbacks = {
sizeof(GpsCallbacks),
location_callback,
status_callback,
sv_status_callback,
nmea_callback,
set_capabilities_callback,
acquire_wakelock_callback,
release_wakelock_callback,
create_thread_callback,
request_utc_time_callback,
};
这些结构体在gps库中也都有对应的结构体,相当于JNI到so库中的一个转换。
都是通过android_location_GpsLocationProvider_init方法中调用gps库中sGpsInterface/ sGpsXtraInterface
等结构体的init方法传递到so库中。部分代码如下,
if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
return JNI_FALSE;
if (sGpsXtraInterface && sGpsXtraInterface->init(&sGpsXtraCallbacks) != 0)
sGpsXtraInterface = NULL;
if (sAGpsInterface)
sAGpsInterface->init(&sAGpsCallbacks);
•••
gps库中gps.h对应的GpsCallbacks定义如下,
typedef struct {
/** set to sizeof(GpsCallbacks) */
size_t size;
gps_location_callback location_cb;
gps_status_callback status_cb;
gps_sv_status_callback sv_status_cb;
gps_nmea_callback nmea_cb;
gps_set_capabilities set_capabilities_cb;
gps_acquire_wakelock acquire_wakelock_cb;
gps_release_wakelock release_wakelock_cb;
gps_create_thread create_thread_cb;
gps_request_utc_time request_utc_time_cb;
} GpsCallbacks;
因此,gps库中调用location_cb方法就是相当于调用JNI的location_callback方法,其他的结构体方法也完全相同,都是一一对应。
这样,gps库就可以回调JNI层的方法了。
最后,GpsLocationProvider的isSupported也是一个native方法,
public static boolean isSupported() {
return native_is_supported();
}
JNI中的android_location_GpsLocationProvider_is_supported方法如下,
static jboolean android_location_GpsLocationProvider_is_supported(
JNIEnv* /* env */, jclass /* clazz */)
{
return (sGpsInterface != NULL) ? JNI_TRUE : JNI_FALSE;
}
如果可以打开so库,获取sGpsInterface结构体就说明支持GPS,否则就不支持。
小结:
主要论述了Java层,JNI层以及so库的回调方法的实现,这样就打通了架构中方法的互相调用。其实, com_android_server_location_GpsLocationProvide只是Framework和HAL之间的一个桥梁。