1 /*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "GnssCallbackJni"
18
19 #include "GnssCallback.h"
20
21 #include <hardware_legacy/power.h>
22
23 #define WAKE_LOCK_NAME "GPS"
24
25 namespace android::gnss {
26
27 using android::hardware::gnss::V1_0::GnssLocationFlags;
28 using binder::Status;
29 using hardware::hidl_vec;
30 using hardware::Return;
31 using hardware::Void;
32
33 using GnssLocationAidl = android::hardware::gnss::GnssLocation;
34 using GnssSignalType = android::hardware::gnss::GnssSignalType;
35 using GnssLocation_V1_0 = android::hardware::gnss::V1_0::GnssLocation;
36 using GnssLocation_V2_0 = android::hardware::gnss::V2_0::GnssLocation;
37 using IGnssCallbackAidl = android::hardware::gnss::IGnssCallback;
38 using IGnssCallback_V1_0 = android::hardware::gnss::V1_0::IGnssCallback;
39 using IGnssCallback_V2_0 = android::hardware::gnss::V2_0::IGnssCallback;
40 using IGnssCallback_V2_1 = android::hardware::gnss::V2_1::IGnssCallback;
41
42 jmethodID method_reportGnssServiceDied;
43
44 namespace {
45
46 jclass class_arrayList;
47 jclass class_gnssSignalType;
48
49 jmethodID method_arrayListAdd;
50 jmethodID method_arrayListCtor;
51 jmethodID method_gnssSignalTypeCreate;
52 jmethodID method_reportLocation;
53 jmethodID method_reportStatus;
54 jmethodID method_reportSvStatus;
55 jmethodID method_reportNmea;
56 jmethodID method_setTopHalCapabilities;
57 jmethodID method_setSignalTypeCapabilities;
58 jmethodID method_setGnssYearOfHardware;
59 jmethodID method_setGnssHardwareModelName;
60 jmethodID method_requestLocation;
61 jmethodID method_requestUtcTime;
62
63 // Returns true if location has lat/long information.
hasLatLong(const GnssLocationAidl & location)64 inline bool hasLatLong(const GnssLocationAidl& location) {
65 return (location.gnssLocationFlags & hardware::gnss::GnssLocation::HAS_LAT_LONG) != 0;
66 }
67
68 // Returns true if location has lat/long information.
hasLatLong(const GnssLocation_V1_0 & location)69 inline bool hasLatLong(const GnssLocation_V1_0& location) {
70 return (static_cast<uint32_t>(location.gnssLocationFlags) & GnssLocationFlags::HAS_LAT_LONG) !=
71 0;
72 }
73
74 // Returns true if location has lat/long information.
hasLatLong(const GnssLocation_V2_0 & location)75 inline bool hasLatLong(const GnssLocation_V2_0& location) {
76 return hasLatLong(location.v1_0);
77 }
78
boolToJbool(bool value)79 inline jboolean boolToJbool(bool value) {
80 return value ? JNI_TRUE : JNI_FALSE;
81 }
82
83 // Must match the value from GnssMeasurement.java
84 const uint32_t SVID_FLAGS_HAS_BASEBAND_CN0 = (1 << 4);
85
86 } // anonymous namespace
87
88 bool isSvStatusRegistered = false;
89 bool isNmeaRegistered = false;
90
Gnss_class_init_once(JNIEnv * env,jclass & clazz)91 void Gnss_class_init_once(JNIEnv* env, jclass& clazz) {
92 method_reportLocation =
93 env->GetMethodID(clazz, "reportLocation", "(ZLandroid/location/Location;)V");
94 method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
95 method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "(I[I[F[F[F[F[F)V");
96 method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");
97
98 method_setTopHalCapabilities = env->GetMethodID(clazz, "setTopHalCapabilities", "(IZ)V");
99 method_setSignalTypeCapabilities =
100 env->GetMethodID(clazz, "setSignalTypeCapabilities", "(Ljava/util/List;)V");
101 method_setGnssYearOfHardware = env->GetMethodID(clazz, "setGnssYearOfHardware", "(I)V");
102 method_setGnssHardwareModelName =
103 env->GetMethodID(clazz, "setGnssHardwareModelName", "(Ljava/lang/String;)V");
104
105 method_requestLocation = env->GetMethodID(clazz, "requestLocation", "(ZZ)V");
106 method_requestUtcTime = env->GetMethodID(clazz, "requestUtcTime", "()V");
107 method_reportGnssServiceDied = env->GetMethodID(clazz, "reportGnssServiceDied", "()V");
108
109 jclass arrayListClass = env->FindClass("java/util/ArrayList");
110 class_arrayList = (jclass)env->NewGlobalRef(arrayListClass);
111 method_arrayListCtor = env->GetMethodID(class_arrayList, "<init>", "()V");
112 method_arrayListAdd = env->GetMethodID(class_arrayList, "add", "(Ljava/lang/Object;)Z");
113
114 jclass gnssSignalTypeClass = env->FindClass("android/location/GnssSignalType");
115 class_gnssSignalType = (jclass)env->NewGlobalRef(gnssSignalTypeClass);
116 method_gnssSignalTypeCreate =
117 env->GetStaticMethodID(class_gnssSignalType, "create",
118 "(IDLjava/lang/String;)Landroid/location/GnssSignalType;");
119 }
120
gnssSetCapabilitiesCb(const int capabilities)121 Status GnssCallbackAidl::gnssSetCapabilitiesCb(const int capabilities) {
122 ALOGD("%s: %du\n", __func__, capabilities);
123 bool isAdrCapabilityKnown = (interfaceVersion >= 3) ? true : false;
124 JNIEnv* env = getJniEnv();
125 env->CallVoidMethod(mCallbacksObj, method_setTopHalCapabilities, capabilities,
126 isAdrCapabilityKnown);
127 checkAndClearExceptionFromCallback(env, __FUNCTION__);
128 return Status::ok();
129 }
130
131 namespace {
132
translateSingleSignalType(JNIEnv * env,const GnssSignalType & signalType)133 jobject translateSingleSignalType(JNIEnv* env, const GnssSignalType& signalType) {
134 jstring jstringCodeType = env->NewStringUTF(signalType.codeType.c_str());
135 jobject signalTypeObject =
136 env->CallStaticObjectMethod(class_gnssSignalType, method_gnssSignalTypeCreate,
137 signalType.constellation, signalType.carrierFrequencyHz,
138 jstringCodeType);
139 env->DeleteLocalRef(jstringCodeType);
140 return signalTypeObject;
141 }
142
143 } // anonymous namespace
144
gnssSetSignalTypeCapabilitiesCb(const std::vector<GnssSignalType> & signalTypes)145 Status GnssCallbackAidl::gnssSetSignalTypeCapabilitiesCb(
146 const std::vector<GnssSignalType>& signalTypes) {
147 ALOGD("%s: %d signal types", __func__, (int)signalTypes.size());
148 JNIEnv* env = getJniEnv();
149 jobject arrayList = env->NewObject(class_arrayList, method_arrayListCtor);
150 for (auto& signalType : signalTypes) {
151 jobject signalTypeObject = translateSingleSignalType(env, signalType);
152 env->CallBooleanMethod(arrayList, method_arrayListAdd, signalTypeObject);
153 // Delete Local Refs
154 env->DeleteLocalRef(signalTypeObject);
155 }
156 env->CallVoidMethod(mCallbacksObj, method_setSignalTypeCapabilities, arrayList);
157 checkAndClearExceptionFromCallback(env, __FUNCTION__);
158 env->DeleteLocalRef(arrayList);
159 return Status::ok();
160 }
161
gnssStatusCb(const GnssStatusValue status)162 Status GnssCallbackAidl::gnssStatusCb(const GnssStatusValue status) {
163 JNIEnv* env = getJniEnv();
164 env->CallVoidMethod(mCallbacksObj, method_reportStatus, status);
165 checkAndClearExceptionFromCallback(env, __FUNCTION__);
166 return Status::ok();
167 }
168
gnssSvStatusCb(const std::vector<GnssSvInfo> & svInfoList)169 Status GnssCallbackAidl::gnssSvStatusCb(const std::vector<GnssSvInfo>& svInfoList) {
170 GnssCallbackHidl::gnssSvStatusCbImpl<std::vector<GnssSvInfo>, GnssSvInfo>(svInfoList);
171 return Status::ok();
172 }
173
gnssLocationCb(const hardware::gnss::GnssLocation & location)174 Status GnssCallbackAidl::gnssLocationCb(const hardware::gnss::GnssLocation& location) {
175 GnssCallbackHidl::gnssLocationCbImpl<hardware::gnss::GnssLocation>(location);
176 return Status::ok();
177 }
178
gnssNmeaCb(const int64_t timestamp,const std::string & nmea)179 Status GnssCallbackAidl::gnssNmeaCb(const int64_t timestamp, const std::string& nmea) {
180 // In AIDL v1, if no listener is registered, do not report nmea to the framework.
181 if (interfaceVersion <= 1) {
182 if (!isNmeaRegistered) {
183 return Status::ok();
184 }
185 }
186 JNIEnv* env = getJniEnv();
187 /*
188 * The Java code will call back to read these values.
189 * We do this to avoid creating unnecessary String objects.
190 */
191 GnssCallbackHidl::sNmeaString = nmea.c_str();
192 GnssCallbackHidl::sNmeaStringLength = nmea.size();
193
194 env->CallVoidMethod(mCallbacksObj, method_reportNmea, timestamp);
195 checkAndClearExceptionFromCallback(env, __FUNCTION__);
196 return Status::ok();
197 }
198
gnssAcquireWakelockCb()199 Status GnssCallbackAidl::gnssAcquireWakelockCb() {
200 acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
201 return Status::ok();
202 }
203
gnssReleaseWakelockCb()204 Status GnssCallbackAidl::gnssReleaseWakelockCb() {
205 release_wake_lock(WAKE_LOCK_NAME);
206 return Status::ok();
207 }
208
gnssSetSystemInfoCb(const GnssSystemInfo & info)209 Status GnssCallbackAidl::gnssSetSystemInfoCb(const GnssSystemInfo& info) {
210 ALOGD("%s: yearOfHw=%d, name=%s\n", __func__, info.yearOfHw, info.name.c_str());
211 JNIEnv* env = getJniEnv();
212 env->CallVoidMethod(mCallbacksObj, method_setGnssYearOfHardware, info.yearOfHw);
213 jstring jstringName = env->NewStringUTF(info.name.c_str());
214 env->CallVoidMethod(mCallbacksObj, method_setGnssHardwareModelName, jstringName);
215 if (jstringName) {
216 env->DeleteLocalRef(jstringName);
217 }
218 checkAndClearExceptionFromCallback(env, __FUNCTION__);
219 return Status::ok();
220 }
221
gnssRequestTimeCb()222 Status GnssCallbackAidl::gnssRequestTimeCb() {
223 JNIEnv* env = getJniEnv();
224 env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
225 checkAndClearExceptionFromCallback(env, __FUNCTION__);
226 return Status::ok();
227 }
228
gnssRequestLocationCb(const bool independentFromGnss,const bool isUserEmergency)229 Status GnssCallbackAidl::gnssRequestLocationCb(const bool independentFromGnss,
230 const bool isUserEmergency) {
231 JNIEnv* env = getJniEnv();
232 env->CallVoidMethod(mCallbacksObj, method_requestLocation, boolToJbool(independentFromGnss),
233 boolToJbool(isUserEmergency));
234 checkAndClearExceptionFromCallback(env, __FUNCTION__);
235 return Status::ok();
236 }
237
238 // Implementation of IGnssCallbackHidl
239
gnssNameCb(const android::hardware::hidl_string & name)240 Return<void> GnssCallbackHidl::gnssNameCb(const android::hardware::hidl_string& name) {
241 ALOGD("%s: name=%s\n", __func__, name.c_str());
242
243 JNIEnv* env = getJniEnv();
244 jstring jstringName = env->NewStringUTF(name.c_str());
245 env->CallVoidMethod(mCallbacksObj, method_setGnssHardwareModelName, jstringName);
246 if (jstringName) {
247 env->DeleteLocalRef(jstringName);
248 }
249 checkAndClearExceptionFromCallback(env, __FUNCTION__);
250
251 return Void();
252 }
253
254 const char* GnssCallbackHidl::sNmeaString = nullptr;
255 size_t GnssCallbackHidl::sNmeaStringLength = 0;
256
257 template <class T>
gnssLocationCbImpl(const T & location)258 Return<void> GnssCallbackHidl::gnssLocationCbImpl(const T& location) {
259 JNIEnv* env = getJniEnv();
260
261 jobject jLocation = translateGnssLocation(env, location);
262
263 env->CallVoidMethod(mCallbacksObj, method_reportLocation, boolToJbool(hasLatLong(location)),
264 jLocation);
265 checkAndClearExceptionFromCallback(env, __FUNCTION__);
266 env->DeleteLocalRef(jLocation);
267 return Void();
268 }
269
gnssLocationCb(const GnssLocation_V1_0 & location)270 Return<void> GnssCallbackHidl::gnssLocationCb(const GnssLocation_V1_0& location) {
271 return gnssLocationCbImpl<GnssLocation_V1_0>(location);
272 }
273
gnssLocationCb_2_0(const GnssLocation_V2_0 & location)274 Return<void> GnssCallbackHidl::gnssLocationCb_2_0(const GnssLocation_V2_0& location) {
275 return gnssLocationCbImpl<GnssLocation_V2_0>(location);
276 }
277
gnssStatusCb(const IGnssCallback_V2_0::GnssStatusValue status)278 Return<void> GnssCallbackHidl::gnssStatusCb(const IGnssCallback_V2_0::GnssStatusValue status) {
279 JNIEnv* env = getJniEnv();
280 env->CallVoidMethod(mCallbacksObj, method_reportStatus, status);
281 checkAndClearExceptionFromCallback(env, __FUNCTION__);
282 return Void();
283 }
284
285 template <>
getHasBasebandCn0DbHzFlag(const hidl_vec<IGnssCallback_V2_1::GnssSvInfo> & svStatus)286 uint32_t GnssCallbackHidl::getHasBasebandCn0DbHzFlag(
287 const hidl_vec<IGnssCallback_V2_1::GnssSvInfo>& svStatus) {
288 return SVID_FLAGS_HAS_BASEBAND_CN0;
289 }
290
291 template <>
getHasBasebandCn0DbHzFlag(const std::vector<IGnssCallbackAidl::GnssSvInfo> & svStatus)292 uint32_t GnssCallbackHidl::getHasBasebandCn0DbHzFlag(
293 const std::vector<IGnssCallbackAidl::GnssSvInfo>& svStatus) {
294 return SVID_FLAGS_HAS_BASEBAND_CN0;
295 }
296
297 template <>
getBasebandCn0DbHz(const std::vector<IGnssCallbackAidl::GnssSvInfo> & svInfoList,size_t i)298 double GnssCallbackHidl::getBasebandCn0DbHz(
299 const std::vector<IGnssCallbackAidl::GnssSvInfo>& svInfoList, size_t i) {
300 return svInfoList[i].basebandCN0DbHz;
301 }
302
303 template <>
getBasebandCn0DbHz(const hidl_vec<IGnssCallback_V2_1::GnssSvInfo> & svInfoList,size_t i)304 double GnssCallbackHidl::getBasebandCn0DbHz(
305 const hidl_vec<IGnssCallback_V2_1::GnssSvInfo>& svInfoList, size_t i) {
306 return svInfoList[i].basebandCN0DbHz;
307 }
308
309 template <>
getGnssSvInfoListSize(const IGnssCallback_V1_0::GnssSvStatus & svStatus)310 uint32_t GnssCallbackHidl::getGnssSvInfoListSize(const IGnssCallback_V1_0::GnssSvStatus& svStatus) {
311 return svStatus.numSvs;
312 }
313
314 template <>
getConstellationType(const IGnssCallback_V1_0::GnssSvStatus & svStatus,size_t i)315 uint32_t GnssCallbackHidl::getConstellationType(const IGnssCallback_V1_0::GnssSvStatus& svStatus,
316 size_t i) {
317 return static_cast<uint32_t>(svStatus.gnssSvList.data()[i].constellation);
318 }
319
320 template <>
getConstellationType(const hidl_vec<IGnssCallback_V2_1::GnssSvInfo> & svInfoList,size_t i)321 uint32_t GnssCallbackHidl::getConstellationType(
322 const hidl_vec<IGnssCallback_V2_1::GnssSvInfo>& svInfoList, size_t i) {
323 return static_cast<uint32_t>(svInfoList[i].v2_0.constellation);
324 }
325
326 template <class T_list, class T_sv_info>
gnssSvStatusCbImpl(const T_list & svStatus)327 Return<void> GnssCallbackHidl::gnssSvStatusCbImpl(const T_list& svStatus) {
328 // In HIDL or AIDL v1, if no listener is registered, do not report svInfoList to the framework.
329 if (!isSvStatusRegistered) {
330 return Void();
331 }
332
333 JNIEnv* env = getJniEnv();
334
335 uint32_t listSize = getGnssSvInfoListSize(svStatus);
336
337 jintArray svidWithFlagArray = env->NewIntArray(listSize);
338 jfloatArray cn0Array = env->NewFloatArray(listSize);
339 jfloatArray elevArray = env->NewFloatArray(listSize);
340 jfloatArray azimArray = env->NewFloatArray(listSize);
341 jfloatArray carrierFreqArray = env->NewFloatArray(listSize);
342 jfloatArray basebandCn0Array = env->NewFloatArray(listSize);
343
344 jint* svidWithFlags = env->GetIntArrayElements(svidWithFlagArray, 0);
345 jfloat* cn0s = env->GetFloatArrayElements(cn0Array, 0);
346 jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
347 jfloat* azim = env->GetFloatArrayElements(azimArray, 0);
348 jfloat* carrierFreq = env->GetFloatArrayElements(carrierFreqArray, 0);
349 jfloat* basebandCn0s = env->GetFloatArrayElements(basebandCn0Array, 0);
350
351 /*
352 * Read GNSS SV info.
353 */
354 for (size_t i = 0; i < listSize; ++i) {
355 enum ShiftWidth : uint8_t { SVID_SHIFT_WIDTH = 12, CONSTELLATION_TYPE_SHIFT_WIDTH = 8 };
356
357 const T_sv_info& info = getGnssSvInfoOfIndex(svStatus, i);
358 svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) |
359 (getConstellationType(svStatus, i) << CONSTELLATION_TYPE_SHIFT_WIDTH) |
360 static_cast<uint32_t>(info.svFlag);
361 cn0s[i] = info.cN0Dbhz;
362 elev[i] = info.elevationDegrees;
363 azim[i] = info.azimuthDegrees;
364 carrierFreq[i] = info.carrierFrequencyHz;
365 svidWithFlags[i] |= getHasBasebandCn0DbHzFlag(svStatus);
366 basebandCn0s[i] = getBasebandCn0DbHz(svStatus, i);
367 }
368
369 env->ReleaseIntArrayElements(svidWithFlagArray, svidWithFlags, 0);
370 env->ReleaseFloatArrayElements(cn0Array, cn0s, 0);
371 env->ReleaseFloatArrayElements(elevArray, elev, 0);
372 env->ReleaseFloatArrayElements(azimArray, azim, 0);
373 env->ReleaseFloatArrayElements(carrierFreqArray, carrierFreq, 0);
374 env->ReleaseFloatArrayElements(basebandCn0Array, basebandCn0s, 0);
375
376 env->CallVoidMethod(mCallbacksObj, method_reportSvStatus, static_cast<jint>(listSize),
377 svidWithFlagArray, cn0Array, elevArray, azimArray, carrierFreqArray,
378 basebandCn0Array);
379
380 env->DeleteLocalRef(svidWithFlagArray);
381 env->DeleteLocalRef(cn0Array);
382 env->DeleteLocalRef(elevArray);
383 env->DeleteLocalRef(azimArray);
384 env->DeleteLocalRef(carrierFreqArray);
385 env->DeleteLocalRef(basebandCn0Array);
386
387 checkAndClearExceptionFromCallback(env, __FUNCTION__);
388 return Void();
389 }
390
gnssNmeaCb(int64_t timestamp,const::android::hardware::hidl_string & nmea)391 Return<void> GnssCallbackHidl::gnssNmeaCb(int64_t timestamp,
392 const ::android::hardware::hidl_string& nmea) {
393 // In HIDL, if no listener is registered, do not report nmea to the framework.
394 if (!isNmeaRegistered) {
395 return Void();
396 }
397 JNIEnv* env = getJniEnv();
398 /*
399 * The Java code will call back to read these values.
400 * We do this to avoid creating unnecessary String objects.
401 */
402 sNmeaString = nmea.c_str();
403 sNmeaStringLength = nmea.size();
404
405 env->CallVoidMethod(mCallbacksObj, method_reportNmea, timestamp);
406 checkAndClearExceptionFromCallback(env, __FUNCTION__);
407 return Void();
408 }
409
gnssSetCapabilitesCb(uint32_t capabilities)410 Return<void> GnssCallbackHidl::gnssSetCapabilitesCb(uint32_t capabilities) {
411 ALOGD("%s: %du\n", __func__, capabilities);
412
413 JNIEnv* env = getJniEnv();
414 env->CallVoidMethod(mCallbacksObj, method_setTopHalCapabilities, capabilities,
415 /* isAdrCapabilityKnown= */ false);
416 checkAndClearExceptionFromCallback(env, __FUNCTION__);
417 return Void();
418 }
419
gnssSetCapabilitiesCb_2_0(uint32_t capabilities)420 Return<void> GnssCallbackHidl::gnssSetCapabilitiesCb_2_0(uint32_t capabilities) {
421 return GnssCallbackHidl::gnssSetCapabilitesCb(capabilities);
422 }
423
gnssSetCapabilitiesCb_2_1(uint32_t capabilities)424 Return<void> GnssCallbackHidl::gnssSetCapabilitiesCb_2_1(uint32_t capabilities) {
425 return GnssCallbackHidl::gnssSetCapabilitesCb(capabilities);
426 }
427
gnssAcquireWakelockCb()428 Return<void> GnssCallbackHidl::gnssAcquireWakelockCb() {
429 acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
430 return Void();
431 }
432
gnssReleaseWakelockCb()433 Return<void> GnssCallbackHidl::gnssReleaseWakelockCb() {
434 release_wake_lock(WAKE_LOCK_NAME);
435 return Void();
436 }
437
gnssRequestTimeCb()438 Return<void> GnssCallbackHidl::gnssRequestTimeCb() {
439 JNIEnv* env = getJniEnv();
440 env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
441 checkAndClearExceptionFromCallback(env, __FUNCTION__);
442 return Void();
443 }
444
gnssRequestLocationCb(const bool independentFromGnss)445 Return<void> GnssCallbackHidl::gnssRequestLocationCb(const bool independentFromGnss) {
446 return GnssCallbackHidl::gnssRequestLocationCb_2_0(independentFromGnss, /* isUserEmergency= */
447 false);
448 }
449
gnssRequestLocationCb_2_0(const bool independentFromGnss,const bool isUserEmergency)450 Return<void> GnssCallbackHidl::gnssRequestLocationCb_2_0(const bool independentFromGnss,
451 const bool isUserEmergency) {
452 JNIEnv* env = getJniEnv();
453 env->CallVoidMethod(mCallbacksObj, method_requestLocation, boolToJbool(independentFromGnss),
454 boolToJbool(isUserEmergency));
455 checkAndClearExceptionFromCallback(env, __FUNCTION__);
456 return Void();
457 }
458
gnssSetSystemInfoCb(const IGnssCallback_V2_0::GnssSystemInfo & info)459 Return<void> GnssCallbackHidl::gnssSetSystemInfoCb(const IGnssCallback_V2_0::GnssSystemInfo& info) {
460 ALOGD("%s: yearOfHw=%d\n", __func__, info.yearOfHw);
461
462 JNIEnv* env = getJniEnv();
463 env->CallVoidMethod(mCallbacksObj, method_setGnssYearOfHardware, info.yearOfHw);
464 checkAndClearExceptionFromCallback(env, __FUNCTION__);
465 return Void();
466 }
467
468 } // namespace android::gnss