Android13适配三方gnss

目录

概要

整体架构流程

代码结构

技术细节

1、android.location包简介

2、LocationManagerService简介

3、GnssLocationProvider简介

4、JNI层

5、native

6、hal层

6.1、定义及作用

6.2、背景

6.3、gnsshal层gps.xxx.so查找与加载过程

6.4 GPS HAL加载过程

6.5、hal层主要的结构体及接口介绍

6.5.1、GpsInterface

6.5.2、回调函数指针定义

7、其他相关接口

7.1、定位模式定义

7.2、工作模式

7.3、辅助数据(在测试GPS性能时候又是需要删除全部或部分的辅助数据)

7.4、gps芯片看处理的“能力”

7.5、GpsLocation

7.6、GpsStatus

7.7、GpsSvInfo

7.8、GpsSvStatus

7.9、GpsNiInterface

7.10、AGpsRefLocation

7.11、AGpsCallbacks

7.12、AGpsInterface

7.13、struct gps_device_t

7.14、Location信息标志位

代码流程梳理

参考:


概要

本文用于记录最近适配三方gps的过程,欢迎大家交流讨论。

整体架构流程

Android13 gnss架构如下图所示

Android系统架构可以分为五个层次:应用层,应用框架层,系统运行库层,硬件抽象层和Linux内核层。每层都有其特定的功能和作用:

1)应用层:包含系统应用和第三方应用

2)应用框架层(framework):提供API供供应用开发使用,主要由Java编写

3)系统运行层:包括C/C++程序库和Android运行时库,提供底层服务和系统调用接口

4)硬件抽象层:提供硬件访问接口,封装硬件相关细节,提高系统可移植性

5)Linux内核层:负责硬件管理,进程调度等核心功能

代码结构

1)Location Framework主要包含以下目录的代码
   a)frameworks/base/location/java/android/location/
        这里主要是用来被APP调用的,API包是android.location
   b)frameworks/base/location/java/com/android/internal/location/
        这个目录是framework对location服务的内部实现
   c)frameworks/base/services/java/com/android/server/
        SystemServer.java加载系统各种服务,重点关注location service
   d)frameworks/base/services/core/java/com/android/server/location/
        LocationManagerService.java是location服务对内部实现的一种封装
2)JNI层
   a)frameworks/base/services/core/java/com/android/server/location/gnss/hal/
        JNI层的作用是将framework和native层串联起来
3)native层
   a)frameworks/base/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
4)hal层,硬件抽象层,这部分由厂商提供

技术细节

1、android.location包简介

名称类型说明
GnssStatus用于描述Gnss的当前状态
GnssStatus.Listener接口用于接收Gnss状态改变时的通知
GnssStatus.NmeaListener接口用于接收nmea信息
LocationListener接口用于接收位置信息改变时的通知
Address用于描述地址信息
Criteria用于选择LocationProvider
Geocoder用于处理地理位置的编码
GpsSatellite用于描述GPS卫星状态
GpsStatus用于描述GPS设备的状态
Location

用于描述地址位置信息,包括经度,纬度,海拔,

方向等信息

LocationManager用于获取和调用定位服务
LocationProvider

描述location provider的超类,location provider是真

正用来获取位置信息的组件。location provider的实

现主要可以分为两类:一种依赖于GPS设备,另一种

依赖网络状态

Geofence用于描述地理上的边界,简称地址围栏
GpsMeasurement/GnssMeasurement用于描述GPS卫星的测量结果
LocationRequest用于描述请求位置服务的参数,包括QOS等

2、LocationManagerService简介

frameworks/base/services/core/java/com/android/server/location/LocationManagerService.java

类型名称说明
LocationFudgermLocationFudger转换或圆整位置信息
GeofenceManagermGeofenceManager地址围栏管理
GeocoderProxymGeocodeProvider地理信息编码代理
GnssManagerServicemGnssManagerServiceGNSS管理服务
LocationUsageLoggermLocationUsageLoggerLocation使用情况的日志
PassiveLocationProviderManagermPassiveManagerPassive provider
PowerManagermPowerManager电源管理相关

CopyOnWriteArrayList

<LocationProviderManager>  

mProviderManagers各种location provider 的管理
HashMap<Object,Receiver> mReceivers记录监听位置信息的用户
HashMap<String,ArrayList<UpdateRecord>>mRecordsByProvider记录provider
ObjectmLock作为内部实现的锁使用
LocationRequestStatisticsmRequestStatistics定位请求的统计信息

3、GnssLocationProvider简介

frameworks/base/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java

GnssLocationProvider.java定义了一系列重要的常量,后面再补充,在该文件中主要关注mGnssNative,这个最终会调用到GnssNative.java里面

4、JNI层

frameworks/base/services/core/java/com/android/server/location/gnss/hal/GnssNative.java

调用native的方法(这些是GnssHal里面的内容,agps有些内容在frameworks/base/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java下面)

名称说明
native_class_init_once类的初始化方法
native_is_supported是否支持Gps 模块 
native_init_once初始化方法
native_cleanup负责清理工作
native_start    开始导航
native_stop 停止导航
native_set_position_mode设置位置模式
native_get_internal_state获取内部状态
native_delete_aiding_data删除辅助信息
native_read_nmea 读取nmea 信息 
native_inject_location注入位置信息
native_inject_time注入时间信息
native_read_sv_status读取 SV状态 
native_get_internal_state获取内部状态
native_agps_set_idAGPS 设置 id 
native_agps_set_ref_location_cellidAGPS 设置引用位置 
native_agps_data_conn_open打开AGps 数据连接
native_agps_data_conn_closed关闭AGps 数据连接
native_agps_data_conn_failedAGps 数据连接失败
native_agps_ni_messageAGps NI(Network-initiated)消息 
native_set_agps_server设置AGPS 服务器
native_send_ni_response发送 NI响应
native_update_network_state更新网络状态
native_is_geofence_supported是否支持geofence
native_add_geofence添加geofence
native_remove_geofence删除geofence
native_resume_geofence继续使用geofence
native_pause_geofence暂停geofence

被JNI回调的方法

名称说明
reportLocation报告位置
reportStatus报告状态
reportSvStatus报告 SV状态 
reportAGpsStatus报告AGps 状态 
reportNmea报告Nmea 
setEngineCapabilities设置引擎能力
xtraDownloadRequestXTRA 下载请求
reportNiNotification报告 NI通知 
requestRefLocation请求引用位置
requestSetID请求设置 id
requestUtcTime请求Utc 时间 
reportGeofenceTransition报告Geofence转换结果
reportGeofenceStatus报告Geofence的状态
reportGeofenceAddStatus报告add Geofence的结果
reportGeofenceRemoveStatus报告removeGeofence的结果
reportGeofenceResumeStatus报告resumeGeofence的结果
reportGeofencePauseStatus报告pauseGeofence的结果

5、native

native层位于hal层之上,主要包括用C/C++编写的系统库和运行时环境。它提供底层服务和系统调用接口,同时也为Java层提供部分功能的支持。

frameworks/base/services/core/jni/com_android_server_location_GnssLocationProvider.cpp

这里主要是链接到hal层,具体如下:



static const JNINativeMethod sCoreMethods[] = {
        /* name, signature, funcPtr */
        {"native_class_init_once", "()V",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_class_init_once)},
        {"native_is_supported", "()Z",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_is_supported)},
        {"native_init_once", "(Z)V",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_init_once)},
};

static const JNINativeMethod sLocationProviderMethods[] = {
        /* name, signature, funcPtr */
        {"native_init", "()Z", reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_init)},
        {"native_cleanup", "()V",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_cleanup)},
        {"native_set_position_mode", "(IIIIIZ)Z",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_set_position_mode)},
        {"native_start", "()Z",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_start)},
        {"native_stop", "()Z", reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_stop)},
        {"native_delete_aiding_data", "(I)V",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_delete_aiding_data)},
        {"native_read_nmea", "([BI)I",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_read_nmea)},
        {"native_inject_time", "(JJI)V",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_inject_time)},
        {"native_inject_best_location", "(IDDDFFFFFFJIJD)V",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_inject_best_location)},
        {"native_inject_location", "(IDDDFFFFFFJIJD)V",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_inject_location)},
        {"native_supports_psds", "()Z",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_supports_psds)},
        {"native_inject_psds_data", "([BII)V",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_inject_psds_data)},
        {"native_agps_set_id", "(ILjava/lang/String;)V",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_agps_set_id)},
        {"native_agps_set_ref_location_cellid", "(IIIIJIII)V",
         reinterpret_cast<void*>(
                 android_location_gnss_hal_GnssNative_agps_set_reference_location_cellid)},
        {"native_set_agps_server", "(ILjava/lang/String;I)V",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_set_agps_server)},
        {"native_inject_ni_supl_message_data", "([BII)V",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_inject_ni_supl_message_data)},
        {"native_get_internal_state", "()Ljava/lang/String;",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_get_internal_state)},
        {"native_is_gnss_visibility_control_supported", "()Z",
         reinterpret_cast<void*>(
                 android_location_gnss_hal_GnssNative_is_gnss_visibility_control_supported)},
        {"native_start_sv_status_collection", "()Z",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_start_sv_status_collection)},
        {"native_stop_sv_status_collection", "()Z",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_stop_sv_status_collection)},
        {"native_start_nmea_message_collection", "()Z",
         reinterpret_cast<void*>(
                 android_location_gnss_hal_GnssNative_start_nmea_message_collection)},
        {"native_stop_nmea_message_collection", "()Z",
         reinterpret_cast<void*>(
                 android_location_gnss_hal_GnssNative_stop_nmea_message_collection)},
};

static const JNINativeMethod sBatchingMethods[] = {
        /* name, signature, funcPtr */
        {"native_get_batch_size", "()I",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_get_batch_size)},
        {"native_start_batch", "(JFZ)Z",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_start_batch)},
        {"native_flush_batch", "()V",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_flush_batch)},
        {"native_stop_batch", "()Z",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_stop_batch)},
        {"native_init_batching", "()Z",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_init_batching)},
        {"native_cleanup_batching", "()V",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_cleanup_batching)},
};

static const JNINativeMethod sAntennaInfoMethods[] = {
        /* name, signature, funcPtr */
        {"native_is_antenna_info_supported", "()Z",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_is_antenna_info_supported)},
        {"native_start_antenna_info_listening", "()Z",
         reinterpret_cast<void*>(
                 android_location_gnss_hal_GnssNative_start_antenna_info_listening)},
        {"native_stop_antenna_info_listening", "()Z",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_stop_antenna_info_listening)},
};

static const JNINativeMethod sGeofenceMethods[] = {
        /* name, signature, funcPtr */
        {"native_is_geofence_supported", "()Z",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_is_geofence_supported)},
        {"native_add_geofence", "(IDDDIIII)Z",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_add_geofence)},
        {"native_remove_geofence", "(I)Z",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_remove_geofence)},
        {"native_pause_geofence", "(I)Z",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_pause_geofence)},
        {"native_resume_geofence", "(II)Z",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_resume_geofence)},
};

static const JNINativeMethod sMeasurementMethods[] = {
        /* name, signature, funcPtr */
        {"native_is_measurement_supported", "()Z",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_is_measurement_supported)},
        {"native_start_measurement_collection", "(ZZI)Z",
         reinterpret_cast<void*>(
                 android_location_gnss_hal_GnssNative_start_measurement_collection)},
        {"native_stop_measurement_collection", "()Z",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_stop_measurement_collection)},
};

static const JNINativeMethod sMeasurementCorrectionsMethods[] = {
        /* name, signature, funcPtr */
        {"native_is_measurement_corrections_supported", "()Z",
         reinterpret_cast<void*>(
                 android_location_gnss_hal_GnssNative_is_measurement_corrections_supported)},
        {"native_inject_measurement_corrections",
         "(Landroid/location/GnssMeasurementCorrections;)Z",
         reinterpret_cast<void*>(
                 android_location_gnss_hal_GnssNative_inject_measurement_corrections)},
};

static const JNINativeMethod sNavigationMessageMethods[] = {
        /* name, signature, funcPtr */
        {"native_is_navigation_message_supported", "()Z",
         reinterpret_cast<void*>(
                 android_location_gnss_hal_GnssNative_is_navigation_message_supported)},
        {"native_start_navigation_message_collection", "()Z",
         reinterpret_cast<void*>(
                 android_location_gnss_hal_GnssNative_start_navigation_message_collection)},
        {"native_stop_navigation_message_collection", "()Z",
         reinterpret_cast<void*>(
                 android_location_gnss_hal_GnssNative_stop_navigation_message_collection)},
};

static const JNINativeMethod sNetworkConnectivityMethods[] = {
        /* name, signature, funcPtr */
        {"native_is_agps_ril_supported", "()Z",
         reinterpret_cast<void*>(
                 android_location_GnssNetworkConnectivityHandler_is_agps_ril_supported)},
        {"native_update_network_state", "(ZIZZLjava/lang/String;JS)V",
         reinterpret_cast<void*>(
                 android_location_GnssNetworkConnectivityHandler_update_network_state)},
        {"native_agps_data_conn_open", "(JLjava/lang/String;I)V",
         reinterpret_cast<void*>(
                 android_location_GnssNetworkConnectivityHandler_agps_data_conn_open)},
        {"native_agps_data_conn_closed", "()V",
         reinterpret_cast<void*>(
                 android_location_GnssNetworkConnectivityHandler_agps_data_conn_closed)},
        {"native_agps_data_conn_failed", "()V",
         reinterpret_cast<void*>(
                 android_location_GnssNetworkConnectivityHandler_agps_data_conn_failed)},
};

static const JNINativeMethod sConfigurationMethods[] = {
        /* name, signature, funcPtr */
        {"native_get_gnss_configuration_version",
         "()Lcom/android/server/location/gnss/GnssConfiguration$HalInterfaceVersion;",
         reinterpret_cast<void*>(
                 android_location_GnssConfiguration_get_gnss_configuration_version)},
        {"native_set_supl_es", "(I)Z",
         reinterpret_cast<void*>(android_location_GnssConfiguration_set_supl_es)},
        {"native_set_supl_version", "(I)Z",
         reinterpret_cast<void*>(android_location_GnssConfiguration_set_supl_version)},
        {"native_set_supl_mode", "(I)Z",
         reinterpret_cast<void*>(android_location_GnssConfiguration_set_supl_mode)},
        {"native_set_lpp_profile", "(I)Z",
         reinterpret_cast<void*>(android_location_GnssConfiguration_set_lpp_profile)},
        {"native_set_gnss_pos_protocol_select", "(I)Z",
         reinterpret_cast<void*>(android_location_GnssConfiguration_set_gnss_pos_protocol_select)},
        {"native_set_gps_lock", "(I)Z",
         reinterpret_cast<void*>(android_location_GnssConfiguration_set_gps_lock)},
        {"native_set_emergency_supl_pdn", "(I)Z",
         reinterpret_cast<void*>(android_location_GnssConfiguration_set_emergency_supl_pdn)},
        {"native_set_satellite_blocklist", "([I[I)Z",
         reinterpret_cast<void*>(android_location_GnssConfiguration_set_satellite_blocklist)},
        {"native_set_es_extension_sec", "(I)Z",
         reinterpret_cast<void*>(android_location_GnssConfiguration_set_es_extension_sec)},
};

static const JNINativeMethod sVisibilityControlMethods[] = {
        /* name, signature, funcPtr */
        {"native_enable_nfw_location_access", "([Ljava/lang/String;)Z",
         reinterpret_cast<void*>(
                 android_location_GnssVisibilityControl_enable_nfw_location_access)},
};

static const JNINativeMethod sPowerIndicationMethods[] = {
        /* name, signature, funcPtr */
        {"native_request_power_stats", "()V",
         reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_request_power_stats)},
};

int register_android_server_location_GnssLocationProvider(JNIEnv* env) {
    int res;

    res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative",
                                   sAntennaInfoMethods, NELEM(sAntennaInfoMethods));
    LOG_FATAL_IF(res < 0, "Unable to register native methods.");

    res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative",
                                   sBatchingMethods, NELEM(sBatchingMethods));
    LOG_FATAL_IF(res < 0, "Unable to register native methods.");

    res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative",
                                   sGeofenceMethods, NELEM(sGeofenceMethods));
    LOG_FATAL_IF(res < 0, "Unable to register native methods.");

    res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative",
                                   sMeasurementMethods, NELEM(sMeasurementMethods));
    LOG_FATAL_IF(res < 0, "Unable to register native methods.");

    res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative",
                                   sMeasurementCorrectionsMethods,
                                   NELEM(sMeasurementCorrectionsMethods));
    LOG_FATAL_IF(res < 0, "Unable to register native methods.");

    res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative",
                                   sNavigationMessageMethods, NELEM(sNavigationMessageMethods));
    LOG_FATAL_IF(res < 0, "Unable to register native methods.");

    res = jniRegisterNativeMethods(env,
                                   "com/android/server/location/gnss/"
                                   "GnssNetworkConnectivityHandler",
                                   sNetworkConnectivityMethods, NELEM(sNetworkConnectivityMethods));
    LOG_FATAL_IF(res < 0, "Unable to register native methods.");

    res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssConfiguration",
                                   sConfigurationMethods, NELEM(sConfigurationMethods));
    LOG_FATAL_IF(res < 0, "Unable to register native methods.");

    res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssVisibilityControl",
                                   sVisibilityControlMethods, NELEM(sVisibilityControlMethods));
    LOG_FATAL_IF(res < 0, "Unable to register native methods.");

    res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative",
                                   sPowerIndicationMethods, NELEM(sPowerIndicationMethods));
    LOG_FATAL_IF(res < 0, "Unable to register native methods.");

    res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative",
                                   sLocationProviderMethods, NELEM(sLocationProviderMethods));
    LOG_FATAL_IF(res < 0, "Unable to register native methods.");

    res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative",
                                   sCoreMethods, NELEM(sCoreMethods));
    LOG_FATAL_IF(res < 0, "Unable to register native methods.");

    return 0;
}

} /* namespace android */

int register_android_server_location_GnssLocationProvider主要是注册static const JNINativeMethod sCoreMethods[],static const JNINativeMethod sLocationProviderMethods[],static const JNINativeMethod sBatchingMethods[],static const JNINativeMethod sAntennaInfoMethods[],static const JNINativeMethod sGeofenceMethods[],static const JNINativeMethod sMeasurementMethods[],static const JNINativeMethod sMeasurementCorrectionsMethods[],static const JNINativeMethod sNavigationMessageMethods[],static const JNINativeMethod sNetworkConnectivityMethods[],static const JNINativeMethod sConfigurationMethods[],static const JNINativeMethod sVisibilityControlMethods[],static const JNINativeMethod sPowerIndicationMethods[],上述的函数均为JNI在native层中链接之后的函数变量,其中主要调用的gnsshal,gnsshal的定义为std::unique_ptr<android::gnss::GnssHal> gnssHal = nullptr,GnssHal为Gnss.h中的类,这样就链接到hal层。

6、hal层

6.1、定义及作用

HAL全称hardware abstract layer,即硬件抽象层,它是对底层硬件驱动进行了一层封装,向framework层提供调用驱动的通用接口,厂家只要按照HAL规范,实现相应接口,并且以共享库的形式存放在特定目录下,那么我上层只要加载这个共享库并找到相应的模块对应的设备的指针,一旦拿到真个设备的指针就可以操作底层硬件。

6.2、背景

那么为什么google会增加这一层(HAL)呢,我们知道手机行业竞争是很激烈的,特别是手机厂商为了追求手机的个性化,而往往这些个性化的东西类似控制算法或者图像算法往往是跟底层硬件打交道的,如果放在内核空间的Linux层,那么这些算法就要遵循GUN Lisence协议进行开源,而如果将这些算法放到android用户空间,而android代码是遵循Apache Lisence协议可以公开也可以不公开代码,如果一旦代码公开,这些厂商势必损失利益,因此可以说,google为了维护各个厂家的利益,设计了这么一个硬件抽象层。也不难理解android源码是开放而不是开源的。

6.3、gnsshal层gps.xxx.so查找与加载过程

函数调用流程大致如下:

hw_get_module 实际是调用 hw_get_module_by_class 并将 id 作为入参传递;
在 hw_get_module_by_class 中会构建一个prop_name即 ro.hardware.%s 其中%s用参数id代替;
这里是 ro.hardware.gps。load函数的主要工作是通过dlopen来打开目标模块共享库,打开成功后,使用dlsym来得到hw_module_t的指针。至此,我们终于得到了表示硬件模块的hw_module_t的指针,有了这个指针,就可以对硬件模块进行操作了。HAL是如何查找和加载模块共享库的过程就分析完了,最终还是通过dlopen和dlsym拿到了模块的hw_module_t的指针,就可以为所欲为了。

6.4 GPS HAL加载过程

通过dlsym调用到hw_get_module得到GPS模块的hw_module_t指针,并将其保存在module变量中,hw_module_t结构体定义定义如下:

struct hw_module_t HAL_MODULE_INFO_SYM = {
    .tag = HARDWARE_MODULE_TAG,
    .module_api_version = 1,
    .hal_api_version = 0,
    .id = GPS_HARDWARE_MODULE_ID,
    .name = "这里自己定义",
    .author = "这里自己定义",
    .methods = &gps_module_methods, //自定义的函数指针,这里既是获取hw_device_t的入口了
};

接着调用GPS模块自定义的hw_module_t的methods中的open函数,获取hw_device_t指针。上面的代码中我们看到,GPS模块的hw_module_t的methods成员的值为gps_module_methods,其定义如下:

static struct hw_module_methods_t gps_module_methods = {
    .open = open_gps
};

open_gps的内容各厂商大致相同,具体如下:

static int open_gps(const struct hw_module_t* module, char const* name,
        struct hw_device_t** device)
{
    //为gps_device_t分配内存空间
    struct gps_device_t *dev = (struct gps_device_t *) malloc(sizeof(struct gps_device_t));
 
    if(dev == NULL)
        return -1;
 
    memset(dev, 0, sizeof(*dev));
    //为gps_device_t的common成员变量赋值
    dev->common.tag = HARDWARE_DEVICE_TAG;
    dev->common.version = 0;
    dev->common.module = (struct hw_module_t*)module;
    //通过下面的函数就能得到GPS模块所有interface,这个是关键
    dev->get_gps_interface = gps__get_gps_interface;
    //将gps_device_t指针强转为hw_device_t指针,赋给device
    *device = (struct hw_device_t*)dev;
    return 0;
}

我们看到open_gps创建了gps_device_t结构体,初始化完成后,将其转为hw_device_t。所以module->methods->open得到实际上是gps_device_t结构体指针。这里我们可以理解为gps_device_t是hw_device_t的子类,将子类对象转为父类对象返回。

6.5、hal层主要的结构体及接口介绍
6.5.1、GpsInterface

Android GPS最主要的数据结构体,我们最主要的移植工作就是实现其中的函数

/** Represents the standard GPS interface. */
typedef struct {
    /** set to sizeof(GpsInterface) */
    size_t          size;
    /*Opens the interface and provides the callback routines 初始化callbacks 为JNI传下来的 
   在此会使用callbacks中的create_thread_cb 来创建一个线程处理函数一直循环,等待任务处理*/
    int   (*init)( GpsCallbacks* callbacks );              

    /** Starts navigating. 开始定位*/
    int   (*start)( void );

    /** Stops navigating. 停止定位*/
    int   (*stop)( void );

    /** Closes the interface. 关闭接口*/
    void  (*cleanup)( void );

    /** Injects the current time. 注入当前时间*/
    int   (*inject_time)(GpsUtcTime time, int64_t timeReference,
                         int uncertainty);

    /** Injects current location from another location provider 注入位置信息*/
    int  (*inject_location)(double latitude, double longitude, float accuracy);

    /*删除全部or部分辅助数据 在性能测试时候使用*/
    void  (*delete_aiding_data)(GpsAidingData flags);

    /*设置定位模式 与GPS工作模式等等*/
    int   (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
            uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);

    /*自行添加的 接口 AGpsInterface接口通过次函数获得*/
    const void* (*get_extension)(const char* name);
} GpsInterface;
6.5.2、回调函数指针定义
/* Callback with location information. 告知上层位置信息*/
typedef void (* gps_location_callback)(GpsLocation* location);

/** Callback with status information.GPS状态信息回调*/
typedef void (* gps_status_callback)(GpsStatus* status);

/** Callback with SV status information.卫星状态信息回调 */
typedef void (* gps_sv_status_callback)(GpsSvStatus* sv_info);

/** Callback for reporting NMEA sentences. 向上层传递NEMA数据*/
typedef void (* gps_nmea_callback)(GpsUtcTime timestamp, const char* nmea, int length);

/** Callback to inform framework of the GPS engine's capabilities.告知上层次GPS能实现那些功能 */
typedef void (* gps_set_capabilities)(uint32_t capabilities);

/** Callback utility for acquiring the GPS wakelock.gps上锁 让gps功能不会被suspend*/
typedef void (* gps_acquire_wakelock)();

/** Callback utility for releasing the GPS wakelock. 释放锁*/
typedef void (* gps_release_wakelock)();

/** Callback for creating a thread that can call into the Java framework code.thread create 
在次线程处理函数中通常会由一个无限的循环,去等待上层的请求,并应答*/
typedef pthread_t (* gps_create_thread)(const char* name, void (*start)(void *), void* arg);



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;
} GpsCallbacks;

这些函数在Gnss.cpp文件中实现,我们无需做修改。

7、其他相关接口

7.1、定位模式定义
/** Requested operational mode for GPS operation. */
typedef uint32_t GpsPositionMode;
// IMPORTANT: Note that the following values must match
// constants in GpsLocationProvider.java.
/** Mode for running GPS standalone (no assistance). */
#define GPS_POSITION_MODE_STANDALONE    0    //纯GPS 使用卫星定位
/** AGPS MS-Based mode. */
#define GPS_POSITION_MODE_MS_BASED      1    //基于用户终端的A-GPS
/** AGPS MS-Assisted mode. */
#define GPS_POSITION_MODE_MS_ASSISTED   2    //基于用户终端辅助A-GPS
7.2、工作模式
/** Requested recurrence mode for GPS operation. */
typedef uint32_t GpsPositionRecurrence;
// IMPORTANT: Note that the following values must match
// constants in GpsLocationProvider.java.
/** Receive GPS fixes on a recurring basis at a specified period. */
#define GPS_POSITION_RECURRENCE_PERIODIC    0//周期性的
/** Request a single shot GPS fix. */
#define GPS_POSITION_RECURRENCE_SINGLE      1//单次工作
7.3、辅助数据(在测试GPS性能时候又是需要删除全部或部分的辅助数据)
/** Flags used to specify which aiding data to delete
    when calling delete_aiding_data(). */
typedef uint16_t GpsAidingData;
// IMPORTANT: Note that the following values must match
// constants in GpsLocationProvider.java.
#define GPS_DELETE_EPHEMERIS        0x0001
#define GPS_DELETE_ALMANAC          0x0002
#define GPS_DELETE_POSITION         0x0004
#define GPS_DELETE_TIME             0x0008
#define GPS_DELETE_IONO             0x0010
#define GPS_DELETE_UTC              0x0020
#define GPS_DELETE_HEALTH           0x0040
#define GPS_DELETE_SVDIR            0x0080
#define GPS_DELETE_SVSTEER          0x0100
#define GPS_DELETE_SADATA           0x0200
#define GPS_DELETE_RTI              0x0400
#define GPS_DELETE_CELLDB_INFO      0x8000
#define GPS_DELETE_ALL              0xFFFF
7.4、gps芯片看处理的“能力”
/** Flags for the gps_set_capabilities callback. */

/** GPS HAL schedules fixes for GPS_POSITION_RECURRENCE_PERIODIC mode.
    If this is not set, then the framework will use 1000ms for min_interval
    and will start and call start() and stop() to schedule the GPS.
 */
#define GPS_CAPABILITY_SCHEDULING       0x0000001  
/** GPS supports MS-Based AGPS mode */  
#define GPS_CAPABILITY_MSB              0x0000002  
/** GPS supports MS-Assisted AGPS mode */  
#define GPS_CAPABILITY_MSA              0x0000004  
/** GPS supports single-shot fixes */  
#define GPS_CAPABILITY_SINGLE_SHOT      0x0000008  
/** GPS supports on demand time injection */  
#define GPS_CAPABILITY_ON_DEMAND_TIME   0x0000010  
/** GPS supports Geofencing  */  
#define GPS_CAPABILITY_GEOFENCING       0x0000020  
/** GPS supports Measurements */  
#define GPS_CAPABILITY_MEASUREMENTS     0x0000040  
/** GPS supports Navigation Messages */  
#define GPS_CAPABILITY_NAV_MESSAGES     0x0000080  
7.5、GpsLocation

GPS位置信息的结构体,包含经纬度,高度,速度,方位角等

<pre name="code" class="cpp">/** Represents a location. */  
typedef struct {  
    /** set to sizeof(GpsLocation) */  
    size_t          size;  
    /** Contains GpsLocationFlags bits. */  
    uint16_t        flags;  
    /** Represents latitude in degrees. */  
    double          latitude;  
    /** Represents longitude in degrees. */  
    double          longitude;  
    /** Represents altitude in meters above the WGS 84 reference 
     * ellipsoid. */  
    double          altitude;  
    /** Represents speed in meters per second. */  
    float           speed;  
    /** Represents heading in degrees. */  
    float           bearing;  
    /** Represents expected accuracy in meters. */  
    float           accuracy;  
    /** Timestamp for the location fix. */  
    GpsUtcTime      timestamp;  
} GpsLocation; 
7.6、GpsStatus

表示GPS的当前状态,只有两个成员一个是表示结构体大小的成员,另一个是表示GPS状态的类型GpsStatusValue

typedef struct {  
    /** set to sizeof(GpsStatus) */  
    size_t          size;  
    GpsStatusValue status;  
} GpsStatus; 


/** GPS status event values. */
typedef uint16_t GpsStatusValue;
// IMPORTANT: Note that the following values must match
// constants in GpsLocationProvider.java.
/** GPS status unknown. */
#define GPS_STATUS_NONE             0/** GPS has begun navigating. */
#define GPS_STATUS_SESSION_BEGIN    1/** GPS has stopped navigating. */
#define GPS_STATUS_SESSION_END      2/** GPS has powered on but is not navigating. */
#define GPS_STATUS_ENGINE_ON        3/** GPS is powered off. */
#define GPS_STATUS_ENGINE_OFF       4
7.7、GpsSvInfo


表示当前的卫星信息,有卫星编号,信号强度,卫星仰望角方位角等

<pre name="code" class="cpp">/** Represents SV information. */  
typedef struct {  
    /** set to sizeof(GpsSvInfo) */  
    size_t          size;  
    /** Pseudo-random number for the SV. */  
    int     prn;  
    /** Signal to noise ratio. */  
    float   snr;  
    /** Elevation of SV in degrees. */  
    float   elevation;  
    /** Azimuth of SV in degrees. */  
    float   azimuth;  
} GpsSvInfo;  
7.8、GpsSvStatus

表示卫星状态,包含了GpsSvInfo结构,可见卫星数,星历时间,年历时间,与用来定位的卫星的卫星构成的一个掩码

<pre name="code" class="cpp">/** Represents SV status. */  
typedef struct {  
    /** set to sizeof(GpsSvStatus) */  
    size_t          size;  
  
    /** Number of SVs currently visible. */  
    int         num_svs;  
  
    /** Contains an array of SV information. */  
    GpsSvInfo   sv_list[GPS_MAX_SVS];  
  
    /** Represents a bit mask indicating which SVs 
     * have ephemeris data. 
     */  
    uint32_t    ephemeris_mask;  
  
    /** Represents a bit mask indicating which SVs 
     * have almanac data. 
     */  
    uint32_t    almanac_mask;  
  
    /** 
     * Represents a bit mask indicating which SVs 
     * were used for computing the most recent position fix. 
     */  
    uint32_t    used_in_fix_mask;  
} GpsSvStatus; 
7.9、GpsNiInterface

网络端发起的定位接口结构体

/** 
 * Extended interface for Network-initiated (NI) support. 
 */  
typedef struct  
{  
    /** set to sizeof(GpsNiInterface) */  
    size_t          size;  
  
   /** Registers the callbacks for HAL to use. */  
   void (*init) (GpsNiCallbacks *callbacks);  
  
   /** Sends a response to HAL. */  
   void (*respond) (int notif_id, GpsUserResponseType user_response);  
} GpsNiInterface;  
7.10、AGpsRefLocation

定义AGPS相关的cell ID和mac地址

/* 2G and 3G */
/* In 3G lac is discarded */
typedef struct {
    uint16_t type;
    uint16_t mcc;
    uint16_t mnc;
    uint16_t lac;
    uint32_t cid;
} AGpsRefLocationCellID;

typedef struct {
    uint8_t mac[6];
} AGpsRefLocationMac;

/** Represents ref locations */
typedef struct {
    uint16_t type;
    union {
        AGpsRefLocationCellID   cellID;
        AGpsRefLocationMac      mac;
    } u;
} AGpsRefLocation;
/** Represents the status of AGPS. */
typedef struct {
    /** set to sizeof(AGpsStatus) */
    size_t          size;


    AGpsType        type;
    AGpsStatusValue status;
} AGpsStatus

Agps状态事件标志
<pre name="code" class="cpp">/** AGPS status event values. */  
typedef uint16_t AGpsStatusValue;  
/** GPS requests data connection for AGPS. */  
#define GPS_REQUEST_AGPS_DATA_CONN  1  
/** GPS releases the AGPS data connection. */  
#define GPS_RELEASE_AGPS_DATA_CONN  2  
/** AGPS data connection initiated */  
#define GPS_AGPS_DATA_CONNECTED     3  
/** AGPS data connection completed */  
#define GPS_AGPS_DATA_CONN_DONE     4  
/** AGPS data connection failed */  
#define GPS_AGPS_DATA_CONN_FAILED   5  
7.11、AGpsCallbacks
/** Callback with AGPS status information.
 *  Can only be called from a thread created by create_thread_cb.
 */
typedef void (* agps_status_callback)(AGpsStatus* status);

/** Callback structure for the AGPS interface. */
typedef struct {
    agps_status_callback status_cb;
    gps_create_thread create_thread_cb;
} AGpsCallbacks;
7.12、AGpsInterface
/** Extended interface for AGPS support. */
typedef struct {
    /** set to sizeof(AGpsInterface) */
    size_t          size;

    /**
     * Opens the AGPS interface and provides the callback routines
     * to the implemenation of this interface.
     */
    void  (*init)( AGpsCallbacks* callbacks );
    /**
     * Notifies that a data connection is available and sets 
     * the name of the APN to be used for SUPL.
     */
    int  (*data_conn_open)( const char* apn );
    /**
     * Notifies that the AGPS data connection has been closed.
     */
    int  (*data_conn_closed)();
    /**
     * Notifies that a data connection is not available for AGPS. 
     */
    int  (*data_conn_failed)();
    /**
     * Sets the hostname and port for the AGPS server.
     */
    int  (*set_server)( AGpsType type, const char* hostname, int port );
} AGpsInterface
7.13、struct gps_device_t

定义描述gps设备类型

struct gps_device_t {
    struct hw_device_t common;

    /**
     * Set the provided lights to the provided values.
     *
     * Returns: 0 on succes, error code on failure.
     */
    const GpsInterface* (*get_gps_interface)(struct gps_device_t* dev);   
};

上层会通过动态库,获得此结构,等到GpsInterface从而打通APP到GPS device的全部通信。

7.14、Location信息标志位

表明位置信息中哪些信息是可获得的

<pre name="code" class="cpp">/** Flags to indicate which values are valid in a GpsLocation. */  
typedef uint16_t GpsLocationFlags;  
// IMPORTANT: Note that the following values must match  
// constants in GpsLocationProvider.java.  
/** GpsLocation has valid latitude and longitude. */  
#define GPS_LOCATION_HAS_LAT_LONG   0x0001  
/** GpsLocation has valid altitude. */  
#define GPS_LOCATION_HAS_ALTITUDE   0x0002  
/** GpsLocation has valid speed. */  
#define GPS_LOCATION_HAS_SPEED      0x0004  
/** GpsLocation has valid bearing. */  
#define GPS_LOCATION_HAS_BEARING    0x0008  
/** GpsLocation has valid accuracy. */  
#define GPS_LOCATION_HAS_ACCURACY   0x0010  

代码流程梳理

本章节只补充部分代码调用流程

这个是初始化流程

这个是把接收到的硬件数据回调到上层

参考:

Android-GnssHal层gps.xxx.so查找与加载过程分析_android gnss hal-CSDN博客

android硬件抽象层(HAL)详解_hal层-CSDN博客

浅析Android 11 Gnss定位流程_registergnssstatuscallback-CSDN博客

基于android 的GPS 移植——主要结构体及接口介绍_android gps架构分析详解-CSDN博客

Android GPS学习笔记(2)—重要结构体及接口_gps.h-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值