• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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