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 "GnssCallbckJni"
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 GnssLocation_V1_0 = android::hardware::gnss::V1_0::GnssLocation;
35 using GnssLocation_V2_0 = android::hardware::gnss::V2_0::GnssLocation;
36 using IGnssCallbackAidl = android::hardware::gnss::IGnssCallback;
37 using IGnssCallback_V1_0 = android::hardware::gnss::V1_0::IGnssCallback;
38 using IGnssCallback_V2_0 = android::hardware::gnss::V2_0::IGnssCallback;
39 using IGnssCallback_V2_1 = android::hardware::gnss::V2_1::IGnssCallback;
40
41 jmethodID method_reportGnssServiceDied;
42
43 namespace {
44
45 jmethodID method_reportLocation;
46 jmethodID method_reportStatus;
47 jmethodID method_reportSvStatus;
48 jmethodID method_reportNmea;
49 jmethodID method_setTopHalCapabilities;
50 jmethodID method_setGnssYearOfHardware;
51 jmethodID method_setGnssHardwareModelName;
52 jmethodID method_requestLocation;
53 jmethodID method_requestUtcTime;
54
55 // Returns true if location has lat/long information.
hasLatLong(const GnssLocationAidl & location)56 inline bool hasLatLong(const GnssLocationAidl& location) {
57 return (location.gnssLocationFlags & hardware::gnss::GnssLocation::HAS_LAT_LONG) != 0;
58 }
59
60 // Returns true if location has lat/long information.
hasLatLong(const GnssLocation_V1_0 & location)61 inline bool hasLatLong(const GnssLocation_V1_0& location) {
62 return (static_cast<uint32_t>(location.gnssLocationFlags) & GnssLocationFlags::HAS_LAT_LONG) !=
63 0;
64 }
65
66 // Returns true if location has lat/long information.
hasLatLong(const GnssLocation_V2_0 & location)67 inline bool hasLatLong(const GnssLocation_V2_0& location) {
68 return hasLatLong(location.v1_0);
69 }
70
boolToJbool(bool value)71 inline jboolean boolToJbool(bool value) {
72 return value ? JNI_TRUE : JNI_FALSE;
73 }
74
75 // Must match the value from GnssMeasurement.java
76 const uint32_t SVID_FLAGS_HAS_BASEBAND_CN0 = (1 << 4);
77
78 } // anonymous namespace
79
80 bool isSvStatusRegistered = false;
81 bool isNmeaRegistered = false;
82
Gnss_class_init_once(JNIEnv * env,jclass & clazz)83 void Gnss_class_init_once(JNIEnv* env, jclass& clazz) {
84 method_reportLocation =
85 env->GetMethodID(clazz, "reportLocation", "(ZLandroid/location/Location;)V");
86 method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
87 method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "(I[I[F[F[F[F[F)V");
88 method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");
89
90 method_setTopHalCapabilities = env->GetMethodID(clazz, "setTopHalCapabilities", "(I)V");
91 method_setGnssYearOfHardware = env->GetMethodID(clazz, "setGnssYearOfHardware", "(I)V");
92 method_setGnssHardwareModelName =
93 env->GetMethodID(clazz, "setGnssHardwareModelName", "(Ljava/lang/String;)V");
94
95 method_requestLocation = env->GetMethodID(clazz, "requestLocation", "(ZZ)V");
96 method_requestUtcTime = env->GetMethodID(clazz, "requestUtcTime", "()V");
97 method_reportGnssServiceDied = env->GetMethodID(clazz, "reportGnssServiceDied", "()V");
98 }
99
gnssSetCapabilitiesCb(const int capabilities)100 Status GnssCallbackAidl::gnssSetCapabilitiesCb(const int capabilities) {
101 ALOGD("GnssCallbackAidl::%s: %du\n", __func__, capabilities);
102 JNIEnv* env = getJniEnv();
103 env->CallVoidMethod(mCallbacksObj, method_setTopHalCapabilities, capabilities);
104 checkAndClearExceptionFromCallback(env, __FUNCTION__);
105 return Status::ok();
106 }
107
gnssStatusCb(const GnssStatusValue status)108 Status GnssCallbackAidl::gnssStatusCb(const GnssStatusValue status) {
109 JNIEnv* env = getJniEnv();
110 env->CallVoidMethod(mCallbacksObj, method_reportStatus, status);
111 checkAndClearExceptionFromCallback(env, __FUNCTION__);
112 return Status::ok();
113 }
114
gnssSvStatusCb(const std::vector<GnssSvInfo> & svInfoList)115 Status GnssCallbackAidl::gnssSvStatusCb(const std::vector<GnssSvInfo>& svInfoList) {
116 GnssCallbackHidl::gnssSvStatusCbImpl<std::vector<GnssSvInfo>, GnssSvInfo>(svInfoList);
117 return Status::ok();
118 }
119
gnssLocationCb(const hardware::gnss::GnssLocation & location)120 Status GnssCallbackAidl::gnssLocationCb(const hardware::gnss::GnssLocation& location) {
121 GnssCallbackHidl::gnssLocationCbImpl<hardware::gnss::GnssLocation>(location);
122 return Status::ok();
123 }
124
gnssNmeaCb(const int64_t timestamp,const std::string & nmea)125 Status GnssCallbackAidl::gnssNmeaCb(const int64_t timestamp, const std::string& nmea) {
126 // In AIDL v1, if no listener is registered, do not report nmea to the framework.
127 if (getInterfaceVersion() <= 1) {
128 if (!isNmeaRegistered) {
129 return Status::ok();
130 }
131 }
132 JNIEnv* env = getJniEnv();
133 /*
134 * The Java code will call back to read these values.
135 * We do this to avoid creating unnecessary String objects.
136 */
137 GnssCallbackHidl::sNmeaString = nmea.c_str();
138 GnssCallbackHidl::sNmeaStringLength = nmea.size();
139
140 env->CallVoidMethod(mCallbacksObj, method_reportNmea, timestamp);
141 checkAndClearExceptionFromCallback(env, __FUNCTION__);
142 return Status::ok();
143 }
144
gnssAcquireWakelockCb()145 Status GnssCallbackAidl::gnssAcquireWakelockCb() {
146 acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
147 return Status::ok();
148 }
149
gnssReleaseWakelockCb()150 Status GnssCallbackAidl::gnssReleaseWakelockCb() {
151 release_wake_lock(WAKE_LOCK_NAME);
152 return Status::ok();
153 }
154
gnssSetSystemInfoCb(const GnssSystemInfo & info)155 Status GnssCallbackAidl::gnssSetSystemInfoCb(const GnssSystemInfo& info) {
156 ALOGD("%s: yearOfHw=%d, name=%s\n", __func__, info.yearOfHw, info.name.c_str());
157 JNIEnv* env = getJniEnv();
158 env->CallVoidMethod(mCallbacksObj, method_setGnssYearOfHardware, info.yearOfHw);
159 jstring jstringName = env->NewStringUTF(info.name.c_str());
160 env->CallVoidMethod(mCallbacksObj, method_setGnssHardwareModelName, jstringName);
161 if (jstringName) {
162 env->DeleteLocalRef(jstringName);
163 }
164 checkAndClearExceptionFromCallback(env, __FUNCTION__);
165 return Status::ok();
166 }
167
gnssRequestTimeCb()168 Status GnssCallbackAidl::gnssRequestTimeCb() {
169 JNIEnv* env = getJniEnv();
170 env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
171 checkAndClearExceptionFromCallback(env, __FUNCTION__);
172 return Status::ok();
173 }
174
gnssRequestLocationCb(const bool independentFromGnss,const bool isUserEmergency)175 Status GnssCallbackAidl::gnssRequestLocationCb(const bool independentFromGnss,
176 const bool isUserEmergency) {
177 JNIEnv* env = getJniEnv();
178 env->CallVoidMethod(mCallbacksObj, method_requestLocation, boolToJbool(independentFromGnss),
179 boolToJbool(isUserEmergency));
180 checkAndClearExceptionFromCallback(env, __FUNCTION__);
181 return Status::ok();
182 }
183
184 // Implementation of IGnssCallbackHidl
185
gnssNameCb(const android::hardware::hidl_string & name)186 Return<void> GnssCallbackHidl::gnssNameCb(const android::hardware::hidl_string& name) {
187 ALOGD("%s: name=%s\n", __func__, name.c_str());
188
189 JNIEnv* env = getJniEnv();
190 jstring jstringName = env->NewStringUTF(name.c_str());
191 env->CallVoidMethod(mCallbacksObj, method_setGnssHardwareModelName, jstringName);
192 if (jstringName) {
193 env->DeleteLocalRef(jstringName);
194 }
195 checkAndClearExceptionFromCallback(env, __FUNCTION__);
196
197 return Void();
198 }
199
200 const char* GnssCallbackHidl::sNmeaString = nullptr;
201 size_t GnssCallbackHidl::sNmeaStringLength = 0;
202
203 template <class T>
gnssLocationCbImpl(const T & location)204 Return<void> GnssCallbackHidl::gnssLocationCbImpl(const T& location) {
205 JNIEnv* env = getJniEnv();
206
207 jobject jLocation = translateGnssLocation(env, location);
208
209 env->CallVoidMethod(mCallbacksObj, method_reportLocation, boolToJbool(hasLatLong(location)),
210 jLocation);
211 checkAndClearExceptionFromCallback(env, __FUNCTION__);
212 env->DeleteLocalRef(jLocation);
213 return Void();
214 }
215
gnssLocationCb(const GnssLocation_V1_0 & location)216 Return<void> GnssCallbackHidl::gnssLocationCb(const GnssLocation_V1_0& location) {
217 return gnssLocationCbImpl<GnssLocation_V1_0>(location);
218 }
219
gnssLocationCb_2_0(const GnssLocation_V2_0 & location)220 Return<void> GnssCallbackHidl::gnssLocationCb_2_0(const GnssLocation_V2_0& location) {
221 return gnssLocationCbImpl<GnssLocation_V2_0>(location);
222 }
223
gnssStatusCb(const IGnssCallback_V2_0::GnssStatusValue status)224 Return<void> GnssCallbackHidl::gnssStatusCb(const IGnssCallback_V2_0::GnssStatusValue status) {
225 JNIEnv* env = getJniEnv();
226 env->CallVoidMethod(mCallbacksObj, method_reportStatus, status);
227 checkAndClearExceptionFromCallback(env, __FUNCTION__);
228 return Void();
229 }
230
231 template <>
getHasBasebandCn0DbHzFlag(const hidl_vec<IGnssCallback_V2_1::GnssSvInfo> & svStatus)232 uint32_t GnssCallbackHidl::getHasBasebandCn0DbHzFlag(
233 const hidl_vec<IGnssCallback_V2_1::GnssSvInfo>& svStatus) {
234 return SVID_FLAGS_HAS_BASEBAND_CN0;
235 }
236
237 template <>
getHasBasebandCn0DbHzFlag(const std::vector<IGnssCallbackAidl::GnssSvInfo> & svStatus)238 uint32_t GnssCallbackHidl::getHasBasebandCn0DbHzFlag(
239 const std::vector<IGnssCallbackAidl::GnssSvInfo>& svStatus) {
240 return SVID_FLAGS_HAS_BASEBAND_CN0;
241 }
242
243 template <>
getBasebandCn0DbHz(const std::vector<IGnssCallbackAidl::GnssSvInfo> & svInfoList,size_t i)244 double GnssCallbackHidl::getBasebandCn0DbHz(
245 const std::vector<IGnssCallbackAidl::GnssSvInfo>& svInfoList, size_t i) {
246 return svInfoList[i].basebandCN0DbHz;
247 }
248
249 template <>
getBasebandCn0DbHz(const hidl_vec<IGnssCallback_V2_1::GnssSvInfo> & svInfoList,size_t i)250 double GnssCallbackHidl::getBasebandCn0DbHz(
251 const hidl_vec<IGnssCallback_V2_1::GnssSvInfo>& svInfoList, size_t i) {
252 return svInfoList[i].basebandCN0DbHz;
253 }
254
255 template <>
getGnssSvInfoListSize(const IGnssCallback_V1_0::GnssSvStatus & svStatus)256 uint32_t GnssCallbackHidl::getGnssSvInfoListSize(const IGnssCallback_V1_0::GnssSvStatus& svStatus) {
257 return svStatus.numSvs;
258 }
259
260 template <>
getConstellationType(const IGnssCallback_V1_0::GnssSvStatus & svStatus,size_t i)261 uint32_t GnssCallbackHidl::getConstellationType(const IGnssCallback_V1_0::GnssSvStatus& svStatus,
262 size_t i) {
263 return static_cast<uint32_t>(svStatus.gnssSvList.data()[i].constellation);
264 }
265
266 template <>
getConstellationType(const hidl_vec<IGnssCallback_V2_1::GnssSvInfo> & svInfoList,size_t i)267 uint32_t GnssCallbackHidl::getConstellationType(
268 const hidl_vec<IGnssCallback_V2_1::GnssSvInfo>& svInfoList, size_t i) {
269 return static_cast<uint32_t>(svInfoList[i].v2_0.constellation);
270 }
271
272 template <class T_list, class T_sv_info>
gnssSvStatusCbImpl(const T_list & svStatus)273 Return<void> GnssCallbackHidl::gnssSvStatusCbImpl(const T_list& svStatus) {
274 // In HIDL or AIDL v1, if no listener is registered, do not report svInfoList to the framework.
275 if (!isSvStatusRegistered) {
276 return Void();
277 }
278
279 JNIEnv* env = getJniEnv();
280
281 uint32_t listSize = getGnssSvInfoListSize(svStatus);
282
283 jintArray svidWithFlagArray = env->NewIntArray(listSize);
284 jfloatArray cn0Array = env->NewFloatArray(listSize);
285 jfloatArray elevArray = env->NewFloatArray(listSize);
286 jfloatArray azimArray = env->NewFloatArray(listSize);
287 jfloatArray carrierFreqArray = env->NewFloatArray(listSize);
288 jfloatArray basebandCn0Array = env->NewFloatArray(listSize);
289
290 jint* svidWithFlags = env->GetIntArrayElements(svidWithFlagArray, 0);
291 jfloat* cn0s = env->GetFloatArrayElements(cn0Array, 0);
292 jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
293 jfloat* azim = env->GetFloatArrayElements(azimArray, 0);
294 jfloat* carrierFreq = env->GetFloatArrayElements(carrierFreqArray, 0);
295 jfloat* basebandCn0s = env->GetFloatArrayElements(basebandCn0Array, 0);
296
297 /*
298 * Read GNSS SV info.
299 */
300 for (size_t i = 0; i < listSize; ++i) {
301 enum ShiftWidth : uint8_t { SVID_SHIFT_WIDTH = 12, CONSTELLATION_TYPE_SHIFT_WIDTH = 8 };
302
303 const T_sv_info& info = getGnssSvInfoOfIndex(svStatus, i);
304 svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) |
305 (getConstellationType(svStatus, i) << CONSTELLATION_TYPE_SHIFT_WIDTH) |
306 static_cast<uint32_t>(info.svFlag);
307 cn0s[i] = info.cN0Dbhz;
308 elev[i] = info.elevationDegrees;
309 azim[i] = info.azimuthDegrees;
310 carrierFreq[i] = info.carrierFrequencyHz;
311 svidWithFlags[i] |= getHasBasebandCn0DbHzFlag(svStatus);
312 basebandCn0s[i] = getBasebandCn0DbHz(svStatus, i);
313 }
314
315 env->ReleaseIntArrayElements(svidWithFlagArray, svidWithFlags, 0);
316 env->ReleaseFloatArrayElements(cn0Array, cn0s, 0);
317 env->ReleaseFloatArrayElements(elevArray, elev, 0);
318 env->ReleaseFloatArrayElements(azimArray, azim, 0);
319 env->ReleaseFloatArrayElements(carrierFreqArray, carrierFreq, 0);
320 env->ReleaseFloatArrayElements(basebandCn0Array, basebandCn0s, 0);
321
322 env->CallVoidMethod(mCallbacksObj, method_reportSvStatus, static_cast<jint>(listSize),
323 svidWithFlagArray, cn0Array, elevArray, azimArray, carrierFreqArray,
324 basebandCn0Array);
325
326 env->DeleteLocalRef(svidWithFlagArray);
327 env->DeleteLocalRef(cn0Array);
328 env->DeleteLocalRef(elevArray);
329 env->DeleteLocalRef(azimArray);
330 env->DeleteLocalRef(carrierFreqArray);
331 env->DeleteLocalRef(basebandCn0Array);
332
333 checkAndClearExceptionFromCallback(env, __FUNCTION__);
334 return Void();
335 }
336
gnssNmeaCb(int64_t timestamp,const::android::hardware::hidl_string & nmea)337 Return<void> GnssCallbackHidl::gnssNmeaCb(int64_t timestamp,
338 const ::android::hardware::hidl_string& nmea) {
339 // In HIDL, if no listener is registered, do not report nmea to the framework.
340 if (!isNmeaRegistered) {
341 return Void();
342 }
343 JNIEnv* env = getJniEnv();
344 /*
345 * The Java code will call back to read these values.
346 * We do this to avoid creating unnecessary String objects.
347 */
348 sNmeaString = nmea.c_str();
349 sNmeaStringLength = nmea.size();
350
351 env->CallVoidMethod(mCallbacksObj, method_reportNmea, timestamp);
352 checkAndClearExceptionFromCallback(env, __FUNCTION__);
353 return Void();
354 }
355
gnssSetCapabilitesCb(uint32_t capabilities)356 Return<void> GnssCallbackHidl::gnssSetCapabilitesCb(uint32_t capabilities) {
357 ALOGD("%s: %du\n", __func__, capabilities);
358
359 JNIEnv* env = getJniEnv();
360 env->CallVoidMethod(mCallbacksObj, method_setTopHalCapabilities, capabilities);
361 checkAndClearExceptionFromCallback(env, __FUNCTION__);
362 return Void();
363 }
364
gnssSetCapabilitiesCb_2_0(uint32_t capabilities)365 Return<void> GnssCallbackHidl::gnssSetCapabilitiesCb_2_0(uint32_t capabilities) {
366 return GnssCallbackHidl::gnssSetCapabilitesCb(capabilities);
367 }
368
gnssSetCapabilitiesCb_2_1(uint32_t capabilities)369 Return<void> GnssCallbackHidl::gnssSetCapabilitiesCb_2_1(uint32_t capabilities) {
370 return GnssCallbackHidl::gnssSetCapabilitesCb(capabilities);
371 }
372
gnssAcquireWakelockCb()373 Return<void> GnssCallbackHidl::gnssAcquireWakelockCb() {
374 acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
375 return Void();
376 }
377
gnssReleaseWakelockCb()378 Return<void> GnssCallbackHidl::gnssReleaseWakelockCb() {
379 release_wake_lock(WAKE_LOCK_NAME);
380 return Void();
381 }
382
gnssRequestTimeCb()383 Return<void> GnssCallbackHidl::gnssRequestTimeCb() {
384 JNIEnv* env = getJniEnv();
385 env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
386 checkAndClearExceptionFromCallback(env, __FUNCTION__);
387 return Void();
388 }
389
gnssRequestLocationCb(const bool independentFromGnss)390 Return<void> GnssCallbackHidl::gnssRequestLocationCb(const bool independentFromGnss) {
391 return GnssCallbackHidl::gnssRequestLocationCb_2_0(independentFromGnss, /* isUserEmergency= */
392 false);
393 }
394
gnssRequestLocationCb_2_0(const bool independentFromGnss,const bool isUserEmergency)395 Return<void> GnssCallbackHidl::gnssRequestLocationCb_2_0(const bool independentFromGnss,
396 const bool isUserEmergency) {
397 JNIEnv* env = getJniEnv();
398 env->CallVoidMethod(mCallbacksObj, method_requestLocation, boolToJbool(independentFromGnss),
399 boolToJbool(isUserEmergency));
400 checkAndClearExceptionFromCallback(env, __FUNCTION__);
401 return Void();
402 }
403
gnssSetSystemInfoCb(const IGnssCallback_V2_0::GnssSystemInfo & info)404 Return<void> GnssCallbackHidl::gnssSetSystemInfoCb(const IGnssCallback_V2_0::GnssSystemInfo& info) {
405 ALOGD("%s: yearOfHw=%d\n", __func__, info.yearOfHw);
406
407 JNIEnv* env = getJniEnv();
408 env->CallVoidMethod(mCallbacksObj, method_setGnssYearOfHardware, info.yearOfHw);
409 checkAndClearExceptionFromCallback(env, __FUNCTION__);
410 return Void();
411 }
412
413 } // namespace android::gnss