目录
7.3、辅助数据(在测试GPS性能时候又是需要删除全部或部分的辅助数据)
概要
本文用于记录最近适配三方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
类型 | 名称 | 说明 |
LocationFudger | mLocationFudger | 转换或圆整位置信息 |
GeofenceManager | mGeofenceManager | 地址围栏管理 |
GeocoderProxy | mGeocodeProvider | 地理信息编码代理 |
GnssManagerService | mGnssManagerService | GNSS管理服务 |
LocationUsageLogger | mLocationUsageLogger | Location使用情况的日志 |
PassiveLocationProviderManager | mPassiveManager | Passive provider |
PowerManager | mPowerManager | 电源管理相关 |
CopyOnWriteArrayList <LocationProviderManager> | mProviderManagers | 各种location provider 的管理 |
HashMap<Object,Receiver> | mReceivers | 记录监听位置信息的用户 |
HashMap<String,ArrayList<UpdateRecord>> | mRecordsByProvider | 记录provider |
Object | mLock | 作为内部实现的锁使用 |
LocationRequestStatistics | mRequestStatistics | 定位请求的统计信息 |
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_id | AGPS 设置 id |
native_agps_set_ref_location_cellid | AGPS 设置引用位置 |
native_agps_data_conn_open | 打开AGps 数据连接 |
native_agps_data_conn_closed | 关闭AGps 数据连接 |
native_agps_data_conn_failed | AGps 数据连接失败 |
native_agps_ni_message | AGps 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 | 设置引擎能力 |
xtraDownloadRequest | XTRA 下载请求 |
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博客