android gps机制分析--之二

来源:互联网 发布:淘宝怎么用邮箱注册 编辑:程序博客网 时间:2024/06/11 04:31

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个步骤,

1, isSupported方法的判断。

2, 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之间的一个桥梁。

原创粉丝点击