接着上篇分析(Android GNSS 模块分析(二)Framework 层),继续往下分析 JNI 层的实现,其实在 JNI 层相对来说就比较简单了,这一层主要就是起到承上启下的过渡作用,那么可以从三点去了解下这一层的实现。
LocationManagerService 分析 JNI 层实现
1、JNI 代码的初始化
2、与 HAL 层的通信
3、与 Framework 层的通信
分析第一部分:JNI 代码的初始化
GNSS JNI 初始化时调用顺序
class_init_native
native_is_supported
native_is_supported
native_init_once
native_init
native_cleanup
native_is_gnss_visibility_control_supported
native_init
native_supports_psds
native_set_agps_server
这是我从开机启动时,在 JNI 层添加日志所打印的开机启动时 JNI 层函数调用的顺序。配合上层 LocationManagerService 服务的初始化,可以分析上层与底层通信的流程。
1.1 class_init_native()
在上层 GnssLocationProvider 初始化的时候,就会调用静态代码块中的 class_init_native() 方法进行 JNI 层初步初始化。
(frameworks/base/services/core/jni/com_android_server_location_GnssLocationProvider.cpp)
主要工作有两步:调用 android_location_GnssLocationProvider_set_gps_service_handle();缓存 JNI 方法和类对象。
android_location_GnssLocationProvider_set_gps_service_handle() 主要就是去初始化 gnssHal,连接底层的Hal 对象。
1.2 native_init_once(true)
在 GnssLocationProvider 的初始化过程中,初始化 JNI 的方法集中在 handleInitialize() 中。先调用 native_init_once(true) 完成 JNI 层的初始化。内容较多,逐步分析
1.2.1 重新调用 android_location_GnssLocationProvider_set_gps_service_handle() 方法,再去获取一次 gnssHal 服务。
1.2.2 调用 linkToDeath() 给 gnssHal 服务注册释放监听。通过 GnssDeathRecipient 回调。最终会调用 method_reportGnssServiceDied 方法通知到上层,底层服务已经挂了
1.2.3 通过 gnssHal->getExtensionXtra() 获取 Hal 层的 IGnssXtra 实现对象,IGnssXtra 是 Hal 层实现的 Hidl 服务端。是否实现取决于底层是否支持 psds 服务。保存到 gnssXtraIface 变量中。
1.2.4 通过 gnssHal->getExtensionAGnssRil() 获取 Hal 层的 IAGnssRil_V1_0 / IAGnssRil_V2_0 实现对象。Hal 层是否实现取决于底层是否支持 agps_ril 服务。保存到 agnssRilIface 变量中。
1.2.5 通过 gnssHal->getExtensionAGnss() 获取 Hal 层的 IAGnss_V1_0 / IAGnss_V2_0 实现对象。获取的是 Hal 层实现 IAGnss.hal 的服务端。 保存到 agnssIface 变量中。
1.2.6 通过 gnssHal->getExtensionGnssNavigationMessage() 获取 Hal 层 IGnssNavigationMessage 实现对象。是 Hal 层实现 IGnssNavigationMessage.hal 的服务端。保存到 gnssNavigationMessageIface 变量中。
1.2.7 通过 gnssHal->getExtensionGnssMeasurement() 获取到 Hal 层 IGnssMeasurement_V1_0 / IGnssMeasurement_V1_1 / IGnssMeasurement_V2_0 实现对象。是 Hal 层实现 IGnssMeasurement.hal 的服务端。保存到 gnssMeasurementIface 变量中
1.2.8 通过 gnssHal_V2_0->getExtensionMeasurementCorrections() 获取到 Hal 层 IMeasurementCorrections 实现对象。是 Hal 层实现 IMeasurementCorrections.hal 的服务端。保存到 gnssCorrectionsIface 变量中。此 hidl 接口是框架中独立的接口,属于 [email protected] 中的接口。这个库在 [email protected] 中使用,其他的 hidl 版本没有使用。
1.2.9 通过 gnssHal->getExtensionGnssDebug() 获取到 Hal 层 IGnssDebug 实现对象。是 Hal 层实现 IGnssDebug.hal 的服务端。保存到 gnssDebugIface 变量中。
1.2.10 通过 gnssHal->getExtensionGnssNi() 获取到 Hal 层 IGnssNi 实现对象。是 Hal 层实现 IGnssNi.hal 的服务端。保存到 gnssNiIface 变量中。
1.2.11 通过 gnssHal->getExtensionGnssConfiguration() 获取到 Hal 层 IGnssConfiguration 实现对象。是 Hal 层实现 IGnssConfiguration.hal 的服务端。保存到 gnssConfigurationIface 变量中。
1.2.12 通过 gnssHal->getExtensionGnssGeofencing() 获取到 Hal 层 IGnssGeofencing 实现对象。是 Hal 层实现 IGnssGeofencing.hal 的服务端。保存到 gnssGeofencingIface 变量中。
1.2.13 通过 gnssHal->getExtensionGnssBatching() 获取到 Hal 层 IGnssBatching 实现对象。是 Hal 层实现 IGnssBatching.hal 的服务端。保存到 gnssBatchingIface 变量中。
1.2.14 通过 gnssHal->getExtensionVisibilityControl() 获取 Hal 层 IGnssVisibilityControl 实现对象。是 Hal 层实现 IGnssVisibilityControl.hal 的服务端。保存到 gnssVisibilityControlIface 变量中。IGnssVisibilityControl.hal hidl 接口是框架中独立的接口,属于 [email protected] 中的接口。这个库是在 [email protected] 中使用,其他 hidl 版本没有使用。
native_init_once() 这里获取底层服务的同时,其实也是初始化获取底层是否支持这类服务。后续会给这些服务添加 callback 回调对象。用于完成提供服务。
下表先简单描述下 HAL 接口层的功能,以提供的 HAL 封装文件展开
Hal 服务 | 功能 | 关联类(callback、数据封装类) | 接口版本 | hidl 库 |
---|---|---|---|---|
IGnss.hal | 标准的GNSS(全球卫星导航系统)接口,实现基本的 GNSS 服务功能封装 | IGnssCallback.hal | 1.0 \ 1.1 \ 2.0 | [email protected] \ [email protected] \ [email protected] |
IGnssXtra.hal | XTRA 服务。高通 gpsOneXTRA 的援助技术在公司的改进中扩展了 gps 芯片组,允许通过互联网连接下载辅助 gps。芯片组为更精确的位置发现提供了更高的灵敏度,尤其是在通常难以找到 GPS 信号的位置。gpsOneXTRA 帮助提供了独立的性能,并简化了 GNSS 的帮助交付 GNSS 引擎,可以使第一次定位时间TTFF提高18到30秒。但是 gpsOneXTRA 需要每天或几天更新一次数据。该数据可以通过网络从 XTRA 服务器上获取。(3条消息) 【驱动】GNSS驱动:gpsOneXTRA 援助技术郭老二的博客-CSDN博客gpsonextra | IGnssXtraCallback.hal | 1.0 | [email protected] |
IAGnssRil.hal | AGNSS RIL 支持的扩展接口。2.0 继承 1.0 的 hal 服务 | IAGnssRilCallback.hal | 1.0 \ 2.0 | [email protected] \ [email protected] |
IAGnss.hal | AGNSS 支持的扩展接口 | IAGnssCallback.hal | 1.0 \ 2.0 | [email protected] \ [email protected] |
IGnssNavigationMessage.hal | 支持GNSS导航消息报告的扩展接口。上层注册回调之后,底层就会通过回调上报信息,无需请求。提供 close() 关闭接口 | IGnssNavigationMessageCallback.hal | 1.0 | [email protected] |
IGnssMeasurement.hal | GNSS测量支持的扩展接口。上层注册回调之后,底层就会通过回调上报信息,无需请求。提供 close() 关闭接口 | IGnssMeasurementCallback.hal | 1.0 \ 1.1 \ 2.0 | [email protected] \ [email protected] \ [email protected] |
IMeasurementCorrections.hal | 支持测量修正的 hidl 接口 | IMeasurementCorrectionsCallback.hal | 其他hidl 接口 | [email protected] |
IGnssDebug.hal | 支持 Debug 的扩展接口 | 1.0 \ 2.0 | [email protected] \ [email protected] | |
IGnssNi.hal | 网络初始化(NI)支持的扩展接口。结果会通过回调提供到上层 | IGnssNiCallback.hal | 1.0 | [email protected] |
IGnssConfiguration.hal | 将GNSS配置信息从平台传递到HAL的接口 | 1.0 \ 1.1 \ 2.0 | [email protected] \ [email protected] \ [email protected] | |
IGnssGeofencing.hal | GNSS geofence支持的扩展接口 | IGnssGeofenceCallback.hal | 1.0 | [email protected] |
IGnssBatching.hal | GNSS批处理支持的扩展接口。 | IGnssBatchingCallback.hal | 1.0 \ 2.0 | |
IGnssVisibilityControl.hal | GNSS位置报告权限和通知接口 | IGnssVisibilityControlCallback.hal | [email protected] |
1.3 native_init()
上层调用 native_init_once() 后,会调用 native_init() 函数。native_init() 函数 对应 JNI 层的 android_location_GnssLocationProvider_init() 方法。这个函数实际上完成的是对之前拿到的底层的 Hal 功能对象添加 callback 回调。
1.4 native_cleanup()
这里进行回调注册成功之后,会调用 native_cleanup() 将 GNSS 底层服务的注册给清除,这里走一次注册的流程,确保后续 GNSS 提供服务时流程能够正常
1.5 native_is_gnss_visibility_control_supported()
判断底层是否支持 IGnssVisibilityControl 的 Hal 服务。这里是返回的 true,标识在初始化的时候是有赋值的。
1.6 native_init()
流程走到 handleInitialize() 的最后,会调用 updateEnabled() 函数,判断当前用户是否打开了 GNSS 功能设置,从而调用 handleEnable() 去开启 GNSS 服务。流程中会先调用 native_init() 去进行 Hal 层回调接口的初始化。
1.7 native_supports_psds()
初始化 Hal 层回调接口之后,会去调用 native_supports_psds() 判断下底层是否支持 PSDS IGnssXtra 的 Hal 服务。这里返回的是 true,说明底层在初始化的时候是成功赋值的
1.8 native_set_agps_server()
这里的调用是给底层 AGnss.hal 服务设置一个 Server 服务端,这个服务端可以是 SUPL,也可以是 C2K 服务。底层是支持 AGNSS Hal 服务的。SUPL(安全用户面定位)采用用户平面的数据承载来传输定位辅助信息,并在移动终端和网络之间携带定位技术相关的协议。SUPL的目的是代替或补充移动网络中的现有定位标准——基于控制平面信令定位
这些就是 GNSS 初始化过程中与底层通信的流程
分析第二部分 HAL 层的通信
* 获取 Hal 对象以及获取 Hal 层所支持的服务对象
* 设置 Hal 回调对象
2.1 获取 Hal 对象
(frameworks/base/services/core/jni/com_android_server_location_GnssLocationProvider.cpp)
GnssLocationProvider 开始加载到内存的时候,就加载了 JNI 层的流程,在 class_init_native() 中调用了上面的函数去获取 Hal 服务。由于 Hal 是 在 init 阶段通过 rc 文件拉起的,Hal 服务已经准备就绪,如果支持的话,这里能直接拿到 Hal 服务对象。
2.2 获取 Hal 层所支持的服务对象
通过 Google 原生定义的 GNSS 模块的 hidl 文件(hardware/interfaces/gnss)可以发现,HIDL 接口定义的服务有很多,在 Hal 层中实现。那么在 JNI 层会通过 Hal 对象去拿到对应的底层服务对象。这部分在上一节 1.2 中有描述。拿到对象后,Framework 层下发数据时,直接通过对应的服务类对象,调用到底层。这部分调用在
2.3 设置 Hal 回调对象
上面拿到 Hal 层具体的服务对象后,还需要给这些不同的服务对象设置回调,用于 Hal 层的消息返回。
Hal 服务对象回调的注册是在 android_location_GnssLocationProvider_init() 完成的,这个函数对应上层的 native_init(),通过之前的分析可知,上层每一次调用 requestLocationUpdates() 函数请求位置信息调用时,都会触发这个回调注册。
static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject obj) {
ALOGD("--test-- id = %ld, native_init",debug_test++);
/*
* This must be set before calling into the HAL library.
*/
if (!mCallbacksObj)
mCallbacksObj = env->NewGlobalRef(obj);
/*
* Fail if the main interface fails to initialize
*/
if (gnssHal == nullptr) {
ALOGE("Unable to initialize GNSS HAL.");
return JNI_FALSE;
}
Return<bool> result = false;
// Set top level IGnss.hal callback.
sp<IGnssCallback> gnssCbIface = new GnssCallback();
if (gnssHal_V2_0 != nullptr) {
result = gnssHal_V2_0->setCallback_2_0(gnssCbIface);
} else if (gnssHal_V1_1 != nullptr) {
result = gnssHal_V1_1->setCallback_1_1(gnssCbIface);
} else {
result = gnssHal->setCallback(gnssCbIface);
}
if (!result.isOk() || !result) {
ALOGE("SetCallback for IGnss interface failed.");
return JNI_FALSE;
}
// Set IGnssXtra.hal callback.
if (gnssXtraIface == nullptr) {
ALOGI("Unable to initialize IGnssXtra interface.");
} else {
sp<IGnssXtraCallback> gnssXtraCbIface = new GnssXtraCallback();
result = gnssXtraIface->setCallback(gnssXtraCbIface);
if (!result.isOk() || !result) {
gnssXtraIface = nullptr;
ALOGI("SetCallback for IGnssXtra interface failed.");
}
}
// Set IAGnss.hal callback.
Return<void> agnssStatus;
if (agnssIface_V2_0 != nullptr) {
sp<IAGnssCallback_V2_0> aGnssCbIface = new AGnssCallback_V2_0();
agnssStatus = agnssIface_V2_0->setCallback(aGnssCbIface);
} else if (agnssIface != nullptr) {
sp<IAGnssCallback_V1_0> aGnssCbIface = new AGnssCallback_V1_0();
agnssStatus = agnssIface->setCallback(aGnssCbIface);
} else {
ALOGI("Unable to initialize IAGnss interface.");
}
if (!agnssStatus.isOk()) {
ALOGI("SetCallback for IAGnss interface failed.");
}
// Set IGnssGeofencing.hal callback.
sp<IGnssGeofenceCallback> gnssGeofencingCbIface = new GnssGeofenceCallback();
if (gnssGeofencingIface != nullptr) {
auto status = gnssGeofencingIface->setCallback(gnssGeofencingCbIface);
if (!status.isOk()) {
ALOGI("SetCallback for IGnssGeofencing interface failed.");
}
} else {
ALOGI("Unable to initialize IGnssGeofencing interface.");
}
// Set IGnssNi.hal callback.
sp<IGnssNiCallback> gnssNiCbIface = new GnssNiCallback();
if (gnssNiIface != nullptr) {
auto status = gnssNiIface->setCallback(gnssNiCbIface);
if (!status.isOk()) {
ALOGI("SetCallback for IGnssNi interface failed.");
}
} else {
ALOGI("Unable to initialize IGnssNi interface.");
}
// Set IAGnssRil.hal callback.
sp<IAGnssRilCallback> aGnssRilCbIface = new AGnssRilCallback();
if (agnssRilIface != nullptr) {
auto status = agnssRilIface->setCallback(aGnssRilCbIface);
if (!status.isOk()) {
ALOGI("SetCallback for IAGnssRil interface failed.");
}
} else {
ALOGI("Unable to initialize IAGnssRil interface.");
}
// Set IGnssVisibilityControl.hal callback.
if (gnssVisibilityControlIface != nullptr) {
sp<IGnssVisibilityControlCallback> gnssVisibilityControlCbIface =
new GnssVisibilityControlCallback();
result = gnssVisibilityControlIface->setCallback(gnssVisibilityControlCbIface);
if (!result.isOk() || !result) {
ALOGI("SetCallback for IGnssVisibilityControl interface failed.");
}
}
// Set IMeasurementCorrections.hal callback.
if (gnssCorrectionsIface != nullptr) {
sp<IMeasurementCorrectionsCallback> gnssCorrectionsIfaceCbIface =
new MeasurementCorrectionsCallback();
result = gnssCorrectionsIface->setCallback(gnssCorrectionsIfaceCbIface);
if (!result.isOk() || !result) {
ALOGI("SetCallback for IMeasurementCorrections interface failed.");
}
}
return JNI_TRUE;
}
分析第三部分 Framework 层的通信
3.1 HAL 层通过 JNI 层注册的回调对象,将数据信息回调到 JNI 层,然后再由 JNI 层与 Framework 层函数的绑定通知到上层。
Hal 层的数据通过回调到 JNI 层时,JNI 层需要将数据通知到上层,那么需要绑定 HAL 回调信息与 Framework 层的对应函数,这部分早在初始化的 android_location_GnssLocationProvider_class_init_native() 完成。
static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
ALOGD("--test-- id = %ld, class_init_native",debug_test++);
// Initialize the top level gnss HAL handle.
android_location_GnssLocationProvider_set_gps_service_handle();
// Cache methodIDs and class IDs.
method_reportLocation = env->GetMethodID(clazz, "reportLocation",
"(ZLandroid/location/Location;)V");
method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "(I[I[F[F[F[F)V");
method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V");
method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");
method_setTopHalCapabilities = env->GetMethodID(clazz, "setTopHalCapabilities", "(I)V");
method_setGnssYearOfHardware = env->GetMethodID(clazz, "setGnssYearOfHardware", "(I)V");
method_setGnssHardwareModelName = env->GetMethodID(clazz, "setGnssHardwareModelName",
"(Ljava/lang/String;)V");
method_psdsDownloadRequest = env->GetMethodID(clazz, "psdsDownloadRequest", "()V");
method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",
"(IIIIILjava/lang/String;Ljava/lang/String;II)V");
method_requestLocation = env->GetMethodID(clazz, "requestLocation", "(ZZ)V");
method_requestRefLocation = env->GetMethodID(clazz, "requestRefLocation", "()V");
method_requestSetID = env->GetMethodID(clazz, "requestSetID", "(I)V");
method_requestUtcTime = env->GetMethodID(clazz, "requestUtcTime", "()V");
method_reportGeofenceTransition = env->GetMethodID(clazz, "reportGeofenceTransition",
"(ILandroid/location/Location;IJ)V");
method_reportGeofenceStatus = env->GetMethodID(clazz, "reportGeofenceStatus",
"(ILandroid/location/Location;)V");
method_reportGeofenceAddStatus = env->GetMethodID(clazz, "reportGeofenceAddStatus",
"(II)V");
method_reportGeofenceRemoveStatus = env->GetMethodID(clazz, "reportGeofenceRemoveStatus",
"(II)V");
method_reportGeofenceResumeStatus = env->GetMethodID(clazz, "reportGeofenceResumeStatus",
"(II)V");
method_reportGeofencePauseStatus = env->GetMethodID(clazz, "reportGeofencePauseStatus",
"(II)V");
method_reportMeasurementData = env->GetMethodID(
clazz,
"reportMeasurementData",
"(Landroid/location/GnssMeasurementsEvent;)V");
method_reportNavigationMessages = env->GetMethodID(
clazz,
"reportNavigationMessage",
"(Landroid/location/GnssNavigationMessage;)V");
method_reportLocationBatch = env->GetMethodID(
clazz,
"reportLocationBatch",
"([Landroid/location/Location;)V");
method_reportGnssServiceDied = env->GetMethodID(clazz, "reportGnssServiceDied", "()V");
method_reportNfwNotification = env->GetMethodID(clazz, "reportNfwNotification",
"(Ljava/lang/String;BLjava/lang/String;BLjava/lang/String;BZZ)V");
method_isInEmergencySession = env->GetMethodID(clazz, "isInEmergencySession", "()Z");
method_setSubHalMeasurementCorrectionsCapabilities = env->GetMethodID(clazz,
"setSubHalMeasurementCorrectionsCapabilities", "(I)V");
jclass measCorrClass = env->FindClass("android/location/GnssMeasurementCorrections");
method_correctionsGetLatitudeDegrees = env->GetMethodID(
measCorrClass,"getLatitudeDegrees", "()D");
method_correctionsGetLongitudeDegrees = env->GetMethodID(
measCorrClass, "getLongitudeDegrees", "()D");
method_correctionsGetAltitudeMeters = env->GetMethodID(
measCorrClass, "getAltitudeMeters", "()D");
method_correctionsGetHorPosUncMeters = env->GetMethodID(
measCorrClass, "getHorizontalPositionUncertaintyMeters", "()D");
method_correctionsGetVerPosUncMeters = env->GetMethodID(
measCorrClass, "getVerticalPositionUncertaintyMeters", "()D");
method_correctionsGetToaGpsNanosecondsOfWeek = env->GetMethodID(
measCorrClass, "getToaGpsNanosecondsOfWeek", "()J");
method_correctionsGetSingleSatCorrectionList = env->GetMethodID(
measCorrClass, "getSingleSatelliteCorrectionList", "()Ljava/util/List;");
jclass corrListClass = env->FindClass("java/util/List");
method_listSize = env->GetMethodID(corrListClass, "size", "()I");
method_correctionListGet = env->GetMethodID(corrListClass, "get", "(I)Ljava/lang/Object;");
jclass singleSatCorrClass = env->FindClass("android/location/GnssSingleSatCorrection");
method_correctionSatFlags = env->GetMethodID(
singleSatCorrClass, "getSingleSatelliteCorrectionFlags", "()I");
method_correctionSatConstType = env->GetMethodID(
singleSatCorrClass, "getConstellationType", "()I");
method_correctionSatId= env->GetMethodID(
singleSatCorrClass, "getSatelliteId", "()I");
method_correctionSatCarrierFreq = env->GetMethodID(
singleSatCorrClass, "getCarrierFrequencyHz", "()F");
method_correctionSatIsLosProb = env->GetMethodID(
singleSatCorrClass,"getProbabilityLineOfSight", "()F");
method_correctionSatEpl = env->GetMethodID(
singleSatCorrClass, "getExcessPathLengthMeters", "()F");
method_correctionSatEplUnc = env->GetMethodID(
singleSatCorrClass, "getExcessPathLengthUncertaintyMeters", "()F");
method_correctionSatRefPlane = env->GetMethodID(
singleSatCorrClass, "getReflectingPlane", "()Landroid/location/GnssReflectingPlane;");
jclass refPlaneClass = env->FindClass("android/location/GnssReflectingPlane");
method_correctionPlaneLatDeg = env->GetMethodID(refPlaneClass, "getLatitudeDegrees", "()D");
method_correctionPlaneLngDeg = env->GetMethodID(refPlaneClass, "getLongitudeDegrees", "()D");
method_correctionPlaneAltDeg = env->GetMethodID(refPlaneClass, "getAltitudeMeters", "()D");
method_correctionPlaneAzimDeg = env->GetMethodID(refPlaneClass, "getAzimuthDegrees", "()D");
jclass gnssMeasurementsEventClass = env->FindClass("android/location/GnssMeasurementsEvent");
class_gnssMeasurementsEvent= (jclass) env->NewGlobalRef(gnssMeasurementsEventClass);
method_gnssMeasurementsEventCtor = env->GetMethodID(
class_gnssMeasurementsEvent,
"<init>",
"(Landroid/location/GnssClock;[Landroid/location/GnssMeasurement;)V");
jclass gnssMeasurementClass = env->FindClass("android/location/GnssMeasurement");
class_gnssMeasurement = (jclass) env->NewGlobalRef(gnssMeasurementClass);
method_gnssMeasurementCtor = env->GetMethodID(class_gnssMeasurement, "<init>", "()V");
jclass locationClass = env->FindClass("android/location/Location");
class_location = (jclass) env->NewGlobalRef(locationClass);
method_locationCtor = env->GetMethodID(class_location, "<init>", "(Ljava/lang/String;)V");
jclass gnssNavigationMessageClass = env->FindClass("android/location/GnssNavigationMessage");
class_gnssNavigationMessage = (jclass) env->NewGlobalRef(gnssNavigationMessageClass);
method_gnssNavigationMessageCtor = env->GetMethodID(class_gnssNavigationMessage, "<init>", "()V");
jclass gnssClockClass = env->FindClass("android/location/GnssClock");
class_gnssClock = (jclass) env->NewGlobalRef(gnssClockClass);
method_gnssClockCtor = env->GetMethodID(class_gnssClock, "<init>", "()V");
jclass gnssConfiguration_halInterfaceVersionClass =
env->FindClass("com/android/server/location/GnssConfiguration$HalInterfaceVersion");
class_gnssConfiguration_halInterfaceVersion =
(jclass) env->NewGlobalRef(gnssConfiguration_halInterfaceVersionClass);
method_halInterfaceVersionCtor =
env->GetMethodID(class_gnssConfiguration_halInterfaceVersion, "<init>", "(II)V");
}
以上基本就是 JNI 层所完成的事情了。
如果文中有错,烦请告知作者,必当有则改之,无则加勉。在此,小弟先行告谢!
联系作者: