GPS机制分析(2)

news/2024/7/4 10:00:44

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方法较多,部分如下,

img

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


http://www.niftyadmin.cn/n/2828936.html

相关文章

数据结构思维 第四章 `LinkedList`

第四章 LinkedList 原文:Chapter 4 LinkedList 译者:飞龙 协议:CC BY-NC-SA 4.0 自豪地采用谷歌翻译 这一章展示了上一个练习的解法,并继续讨论算法分析。 4.1 MyLinkedList方法的划分 我的indexOf实现在下面。在阅读说明之前&am…

GPS机制分析(3)

1. gps打开/初始化 ​ 在Java层打开gps,其实对于gps库来说,就是执行初始化过程。 1.1 Java层分析 ​ android系统中打开GPS的方法往数据库里面写值, private void enableGps(boolean enable) { try {Settings.Secure.setLocationProviderEnabled(getContentResolver(),Loca…

转WCF中出现死锁或者超时

WCF回调中的死锁 一、服务器端死锁 对于如下服务: [ServiceContract(CallbackContract typeof(INotify))]public class DownloadService{[OperationContract]public void Download(){//开始下载操作//.....//通知下载完成var callback OperationContext.Current.G…

ConcurrentMultiMap 实现

2019独角兽企业重金招聘Python工程师标准>>> Index&#xff0c;akka用来存储对应dispatcher和actor的&#xff0c;也是Akka实现的ConcurrentMultiMap<K,V> key类型自定义&#xff0c;value是由ConcurrentSkipListSet构成的,内部其实就对ConcurrentMultiMap<…

GPS机制分析(5)

1. 概述 ​ 上面的几篇文章论述了gps的打开启动初始化等动作,万事俱备只欠东风了。这一系列文章主要讲的是Position信息如何从modem层传递到loc eng层最后一直到Java上层的。由于loc eng层到modem层是属于消息触发的&#xff0c;也就是说正常的流程是&#xff1a;modem层传上来…

GPS机制分析(6)

7. gps数据从HAL传输到Java ​ 上面UlpLocation类型的mLocation作为参数传入&#xff0c;这里传递的还是UlpLocation类型的数据&#xff0c;不是hal层使用的GpsLocation类型&#xff0c;因此我们看一下UlpLocation类型的数据转换成GpsLocation类型的数据的过程&#xff1a; h…

IPC—Android Binder (1)

IPC是Inter-Process Communication的缩写&#xff0c;含义就是跨进程通信。 多进程场景 WebView加载图片推送 原因 内存不够->内存就够了 App运行独立的虚拟机——每个进程分配运行内存是有限的——32M、64M、48M 加载一个大图片——直接OOM 如果一旦奔溃&#xff0c;…

AndroidGPS定位应用流程

AndroidGPS定位应用流程 这里先了解下应用层流程。 根据这个框架&#xff0c;GPS在应用层实现的最基本流程示例&#xff1a; public class MainActivity extends Activity {private LocationManager mLocationManager;Overrideprotected void onDestroy() {super.onDestroy…