1 /*
2  * Copyright (C) 2021 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 before <log/log.h> to overwrite the default value.
18 #define LOG_TAG "GnssAntInfoCbJni"
19 
20 #include "GnssAntennaInfoCallback.h"
21 #include "Utils.h"
22 
23 namespace android::gnss {
24 
25 using android::hardware::hidl_vec;
26 using android::hardware::Return;
27 using android::hardware::Void;
28 using binder::Status;
29 
30 using IGnssAntennaInfoCallbackAidl = android::hardware::gnss::IGnssAntennaInfoCallback;
31 using IGnssAntennaInfoCallback_V2_1 = android::hardware::gnss::V2_1::IGnssAntennaInfoCallback;
32 
33 namespace {
34 jclass class_gnssAntennaInfoBuilder;
35 jclass class_phaseCenterOffset;
36 jclass class_sphericalCorrections;
37 jclass class_arrayList;
38 jclass class_doubleArray;
39 
40 jmethodID method_reportAntennaInfo;
41 jmethodID method_gnssAntennaInfoBuilderCtor;
42 jmethodID method_phaseCenterOffsetCtor;
43 jmethodID method_sphericalCorrectionsCtor;
44 jmethodID method_arrayListCtor;
45 jmethodID method_arrayListAdd;
46 jmethodID method_gnssAntennaInfoBuilderSetCarrierFrequencyMHz;
47 jmethodID method_gnssAntennaInfoBuilderSetPhaseCenterOffset;
48 jmethodID method_gnssAntennaInfoBuilderSetPhaseCenterVariationCorrections;
49 jmethodID method_gnssAntennaInfoBuilderSetSignalGainCorrections;
50 jmethodID method_gnssAntennaInfoBuilderBuild;
51 } // anonymous namespace
52 
GnssAntennaInfo_class_init_once(JNIEnv * env,jclass & clazz)53 void GnssAntennaInfo_class_init_once(JNIEnv* env, jclass& clazz) {
54     method_reportAntennaInfo = env->GetMethodID(clazz, "reportAntennaInfo", "(Ljava/util/List;)V");
55     jclass gnssAntennaInfoBuilder = env->FindClass("android/location/GnssAntennaInfo$Builder");
56     class_gnssAntennaInfoBuilder = (jclass)env->NewGlobalRef(gnssAntennaInfoBuilder);
57     method_gnssAntennaInfoBuilderCtor =
58             env->GetMethodID(class_gnssAntennaInfoBuilder, "<init>", "()V");
59     method_gnssAntennaInfoBuilderSetCarrierFrequencyMHz =
60             env->GetMethodID(class_gnssAntennaInfoBuilder, "setCarrierFrequencyMHz",
61                              "(D)Landroid/location/GnssAntennaInfo$Builder;");
62     method_gnssAntennaInfoBuilderSetPhaseCenterOffset =
63             env->GetMethodID(class_gnssAntennaInfoBuilder, "setPhaseCenterOffset",
64                              "(Landroid/location/GnssAntennaInfo$PhaseCenterOffset;)"
65                              "Landroid/location/GnssAntennaInfo$Builder;");
66     method_gnssAntennaInfoBuilderSetPhaseCenterVariationCorrections =
67             env->GetMethodID(class_gnssAntennaInfoBuilder, "setPhaseCenterVariationCorrections",
68                              "(Landroid/location/GnssAntennaInfo$SphericalCorrections;)"
69                              "Landroid/location/GnssAntennaInfo$Builder;");
70     method_gnssAntennaInfoBuilderSetSignalGainCorrections =
71             env->GetMethodID(class_gnssAntennaInfoBuilder, "setSignalGainCorrections",
72                              "(Landroid/location/GnssAntennaInfo$SphericalCorrections;)"
73                              "Landroid/location/GnssAntennaInfo$Builder;");
74     method_gnssAntennaInfoBuilderBuild = env->GetMethodID(class_gnssAntennaInfoBuilder, "build",
75                                                           "()Landroid/location/GnssAntennaInfo;");
76 
77     jclass phaseCenterOffsetClass =
78             env->FindClass("android/location/GnssAntennaInfo$PhaseCenterOffset");
79     class_phaseCenterOffset = (jclass)env->NewGlobalRef(phaseCenterOffsetClass);
80     method_phaseCenterOffsetCtor = env->GetMethodID(class_phaseCenterOffset, "<init>", "(DDDDDD)V");
81 
82     jclass sphericalCorrectionsClass =
83             env->FindClass("android/location/GnssAntennaInfo$SphericalCorrections");
84     class_sphericalCorrections = (jclass)env->NewGlobalRef(sphericalCorrectionsClass);
85     method_sphericalCorrectionsCtor =
86             env->GetMethodID(class_sphericalCorrections, "<init>", "([[D[[D)V");
87 
88     jclass arrayListClass = env->FindClass("java/util/ArrayList");
89     class_arrayList = (jclass)env->NewGlobalRef(arrayListClass);
90     method_arrayListCtor = env->GetMethodID(class_arrayList, "<init>", "()V");
91     method_arrayListAdd = env->GetMethodID(class_arrayList, "add", "(Ljava/lang/Object;)Z");
92 
93     jclass doubleArrayClass = env->FindClass("[D");
94     class_doubleArray = (jclass)env->NewGlobalRef(doubleArrayClass);
95 }
96 
gnssAntennaInfoCb(const std::vector<IGnssAntennaInfoCallbackAidl::GnssAntennaInfo> & gnssAntennaInfos)97 binder::Status GnssAntennaInfoCallbackAidl::gnssAntennaInfoCb(
98         const std::vector<IGnssAntennaInfoCallbackAidl::GnssAntennaInfo>& gnssAntennaInfos) {
99     GnssAntennaInfoCallbackUtil::translateAndReportGnssAntennaInfo(gnssAntennaInfos);
100     return Status::ok();
101 }
102 
gnssAntennaInfoCb(const hidl_vec<IGnssAntennaInfoCallback_V2_1::GnssAntennaInfo> & gnssAntennaInfos)103 Return<void> GnssAntennaInfoCallback_V2_1::gnssAntennaInfoCb(
104         const hidl_vec<IGnssAntennaInfoCallback_V2_1::GnssAntennaInfo>& gnssAntennaInfos) {
105     GnssAntennaInfoCallbackUtil::translateAndReportGnssAntennaInfo(gnssAntennaInfos);
106     return Void();
107 }
108 
109 template <template <class...> class T_vector, class T_info>
translate2dDoubleArray(JNIEnv * env,const T_vector<T_info> & array)110 jobjectArray GnssAntennaInfoCallbackUtil::translate2dDoubleArray(JNIEnv* env,
111                                                                  const T_vector<T_info>& array) {
112     jsize numRows = array.size();
113     if (numRows == 0) {
114         // Empty array
115         return NULL;
116     }
117     jsize numCols = array[0].row.size();
118     if (numCols <= 1) {
119         // phi angle separation is computed as 180.0 / (numColumns - 1), so can't be < 2.
120         return NULL;
121     }
122 
123     // Allocate array of double arrays
124     jobjectArray returnArray = env->NewObjectArray(numRows, class_doubleArray, NULL);
125 
126     // Create each double array
127     for (uint8_t i = 0; i < numRows; i++) {
128         jdoubleArray doubleArray = env->NewDoubleArray(numCols);
129         env->SetDoubleArrayRegion(doubleArray, (jsize)0, numCols, array[i].row.data());
130         env->SetObjectArrayElement(returnArray, (jsize)i, doubleArray);
131         env->DeleteLocalRef(doubleArray);
132     }
133     return returnArray;
134 }
135 
136 template <template <class...> class T_vector, class T_info>
translateAllGnssAntennaInfos(JNIEnv * env,const T_vector<T_info> & gnssAntennaInfos)137 jobject GnssAntennaInfoCallbackUtil::translateAllGnssAntennaInfos(
138         JNIEnv* env, const T_vector<T_info>& gnssAntennaInfos) {
139     jobject arrayList = env->NewObject(class_arrayList,
140                                        method_arrayListCtor); // Create new ArrayList instance
141 
142     for (auto gnssAntennaInfo : gnssAntennaInfos) {
143         jobject gnssAntennaInfoObject = translateSingleGnssAntennaInfo(env, gnssAntennaInfo);
144 
145         env->CallBooleanMethod(arrayList, method_arrayListAdd,
146                                gnssAntennaInfoObject); // Add the antennaInfo to the ArrayList
147 
148         // Delete Local Refs
149         env->DeleteLocalRef(gnssAntennaInfoObject);
150     }
151     return arrayList;
152 }
153 
154 template <class T>
translatePhaseCenterOffset(JNIEnv * env,const T & gnssAntennaInfo)155 jobject GnssAntennaInfoCallbackUtil::translatePhaseCenterOffset(JNIEnv* env,
156                                                                 const T& gnssAntennaInfo) {
157     jobject phaseCenterOffset =
158             env->NewObject(class_phaseCenterOffset, method_phaseCenterOffsetCtor,
159                            gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.x,
160                            gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.xUncertainty,
161                            gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.y,
162                            gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.yUncertainty,
163                            gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.z,
164                            gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.zUncertainty);
165 
166     return phaseCenterOffset;
167 }
168 
169 template <>
translatePhaseCenterVariationCorrections(JNIEnv * env,const IGnssAntennaInfoCallbackAidl::GnssAntennaInfo & gnssAntennaInfo)170 jobject GnssAntennaInfoCallbackUtil::translatePhaseCenterVariationCorrections(
171         JNIEnv* env, const IGnssAntennaInfoCallbackAidl::GnssAntennaInfo& gnssAntennaInfo) {
172     if (gnssAntennaInfo.phaseCenterVariationCorrectionMillimeters.empty() ||
173         gnssAntennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters.empty()) {
174         return NULL;
175     }
176 
177     jobjectArray phaseCenterVariationCorrectionsArray =
178             translate2dDoubleArray(env, gnssAntennaInfo.phaseCenterVariationCorrectionMillimeters);
179     jobjectArray phaseCenterVariationCorrectionsUncertaintiesArray =
180             translate2dDoubleArray(env,
181                                    gnssAntennaInfo
182                                            .phaseCenterVariationCorrectionUncertaintyMillimeters);
183 
184     if (phaseCenterVariationCorrectionsArray == NULL ||
185         phaseCenterVariationCorrectionsUncertaintiesArray == NULL) {
186         env->DeleteLocalRef(phaseCenterVariationCorrectionsArray);
187         env->DeleteLocalRef(phaseCenterVariationCorrectionsUncertaintiesArray);
188         return NULL;
189     }
190 
191     jobject phaseCenterVariationCorrections =
192             env->NewObject(class_sphericalCorrections, method_sphericalCorrectionsCtor,
193                            phaseCenterVariationCorrectionsArray,
194                            phaseCenterVariationCorrectionsUncertaintiesArray);
195 
196     env->DeleteLocalRef(phaseCenterVariationCorrectionsArray);
197     env->DeleteLocalRef(phaseCenterVariationCorrectionsUncertaintiesArray);
198 
199     return phaseCenterVariationCorrections;
200 }
201 
202 template <>
translatePhaseCenterVariationCorrections(JNIEnv * env,const IGnssAntennaInfoCallback_V2_1::GnssAntennaInfo & gnssAntennaInfo)203 jobject GnssAntennaInfoCallbackUtil::translatePhaseCenterVariationCorrections(
204         JNIEnv* env, const IGnssAntennaInfoCallback_V2_1::GnssAntennaInfo& gnssAntennaInfo) {
205     if (gnssAntennaInfo.phaseCenterVariationCorrectionMillimeters == NULL ||
206         gnssAntennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters == NULL) {
207         return NULL;
208     }
209 
210     jobjectArray phaseCenterVariationCorrectionsArray =
211             translate2dDoubleArray(env, gnssAntennaInfo.phaseCenterVariationCorrectionMillimeters);
212     jobjectArray phaseCenterVariationCorrectionsUncertaintiesArray =
213             translate2dDoubleArray(env,
214                                    gnssAntennaInfo
215                                            .phaseCenterVariationCorrectionUncertaintyMillimeters);
216 
217     if (phaseCenterVariationCorrectionsArray == NULL ||
218         phaseCenterVariationCorrectionsUncertaintiesArray == NULL) {
219         env->DeleteLocalRef(phaseCenterVariationCorrectionsArray);
220         env->DeleteLocalRef(phaseCenterVariationCorrectionsUncertaintiesArray);
221         return NULL;
222     }
223 
224     jobject phaseCenterVariationCorrections =
225             env->NewObject(class_sphericalCorrections, method_sphericalCorrectionsCtor,
226                            phaseCenterVariationCorrectionsArray,
227                            phaseCenterVariationCorrectionsUncertaintiesArray);
228 
229     env->DeleteLocalRef(phaseCenterVariationCorrectionsArray);
230     env->DeleteLocalRef(phaseCenterVariationCorrectionsUncertaintiesArray);
231 
232     return phaseCenterVariationCorrections;
233 }
234 
235 template <>
translateSignalGainCorrections(JNIEnv * env,const IGnssAntennaInfoCallbackAidl::GnssAntennaInfo & gnssAntennaInfo)236 jobject GnssAntennaInfoCallbackUtil::translateSignalGainCorrections(
237         JNIEnv* env, const IGnssAntennaInfoCallbackAidl::GnssAntennaInfo& gnssAntennaInfo) {
238     if (gnssAntennaInfo.signalGainCorrectionDbi.empty() ||
239         gnssAntennaInfo.signalGainCorrectionUncertaintyDbi.empty()) {
240         return NULL;
241     }
242     jobjectArray signalGainCorrectionsArray =
243             translate2dDoubleArray(env, gnssAntennaInfo.signalGainCorrectionDbi);
244     jobjectArray signalGainCorrectionsUncertaintiesArray =
245             translate2dDoubleArray(env, gnssAntennaInfo.signalGainCorrectionUncertaintyDbi);
246 
247     if (signalGainCorrectionsArray == NULL || signalGainCorrectionsUncertaintiesArray == NULL) {
248         env->DeleteLocalRef(signalGainCorrectionsArray);
249         env->DeleteLocalRef(signalGainCorrectionsUncertaintiesArray);
250         return NULL;
251     }
252 
253     jobject signalGainCorrections =
254             env->NewObject(class_sphericalCorrections, method_sphericalCorrectionsCtor,
255                            signalGainCorrectionsArray, signalGainCorrectionsUncertaintiesArray);
256 
257     env->DeleteLocalRef(signalGainCorrectionsArray);
258     env->DeleteLocalRef(signalGainCorrectionsUncertaintiesArray);
259 
260     return signalGainCorrections;
261 }
262 
263 template <>
translateSignalGainCorrections(JNIEnv * env,const IGnssAntennaInfoCallback_V2_1::GnssAntennaInfo & gnssAntennaInfo)264 jobject GnssAntennaInfoCallbackUtil::translateSignalGainCorrections(
265         JNIEnv* env, const IGnssAntennaInfoCallback_V2_1::GnssAntennaInfo& gnssAntennaInfo) {
266     if (gnssAntennaInfo.signalGainCorrectionDbi == NULL ||
267         gnssAntennaInfo.signalGainCorrectionUncertaintyDbi == NULL) {
268         return NULL;
269     }
270     jobjectArray signalGainCorrectionsArray =
271             translate2dDoubleArray(env, gnssAntennaInfo.signalGainCorrectionDbi);
272     jobjectArray signalGainCorrectionsUncertaintiesArray =
273             translate2dDoubleArray(env, gnssAntennaInfo.signalGainCorrectionUncertaintyDbi);
274 
275     if (signalGainCorrectionsArray == NULL || signalGainCorrectionsUncertaintiesArray == NULL) {
276         env->DeleteLocalRef(signalGainCorrectionsArray);
277         env->DeleteLocalRef(signalGainCorrectionsUncertaintiesArray);
278         return NULL;
279     }
280 
281     jobject signalGainCorrections =
282             env->NewObject(class_sphericalCorrections, method_sphericalCorrectionsCtor,
283                            signalGainCorrectionsArray, signalGainCorrectionsUncertaintiesArray);
284 
285     env->DeleteLocalRef(signalGainCorrectionsArray);
286     env->DeleteLocalRef(signalGainCorrectionsUncertaintiesArray);
287 
288     return signalGainCorrections;
289 }
290 
291 template <class T>
translateSingleGnssAntennaInfo(JNIEnv * env,const T & gnssAntennaInfo)292 jobject GnssAntennaInfoCallbackUtil::translateSingleGnssAntennaInfo(JNIEnv* env,
293                                                                     const T& gnssAntennaInfo) {
294     jobject phaseCenterOffset = translatePhaseCenterOffset(env, gnssAntennaInfo);
295 
296     // Nullable
297     jobject phaseCenterVariationCorrections =
298             translatePhaseCenterVariationCorrections(env, gnssAntennaInfo);
299 
300     // Nullable
301     jobject signalGainCorrections = translateSignalGainCorrections(env, gnssAntennaInfo);
302 
303     // Get builder
304     jobject gnssAntennaInfoBuilderObject =
305             env->NewObject(class_gnssAntennaInfoBuilder, method_gnssAntennaInfoBuilderCtor);
306 
307     // Set fields
308     callObjectMethodIgnoringResult(env, gnssAntennaInfoBuilderObject,
309                                    method_gnssAntennaInfoBuilderSetCarrierFrequencyMHz,
310                                    getCarrierFrequencyMHz(gnssAntennaInfo));
311     callObjectMethodIgnoringResult(env, gnssAntennaInfoBuilderObject,
312                                    method_gnssAntennaInfoBuilderSetPhaseCenterOffset,
313                                    phaseCenterOffset);
314     callObjectMethodIgnoringResult(env, gnssAntennaInfoBuilderObject,
315                                    method_gnssAntennaInfoBuilderSetPhaseCenterVariationCorrections,
316                                    phaseCenterVariationCorrections);
317     callObjectMethodIgnoringResult(env, gnssAntennaInfoBuilderObject,
318                                    method_gnssAntennaInfoBuilderSetSignalGainCorrections,
319                                    signalGainCorrections);
320 
321     // build
322     jobject gnssAntennaInfoObject =
323             env->CallObjectMethod(gnssAntennaInfoBuilderObject, method_gnssAntennaInfoBuilderBuild);
324 
325     // Delete Local Refs
326     env->DeleteLocalRef(phaseCenterOffset);
327     env->DeleteLocalRef(phaseCenterVariationCorrections);
328     env->DeleteLocalRef(signalGainCorrections);
329 
330     return gnssAntennaInfoObject;
331 }
332 
333 template <template <class...> class T_vector, class T_info>
translateAndReportGnssAntennaInfo(const T_vector<T_info> & gnssAntennaInfos)334 void GnssAntennaInfoCallbackUtil::translateAndReportGnssAntennaInfo(
335         const T_vector<T_info>& gnssAntennaInfos) {
336     JNIEnv* env = getJniEnv();
337 
338     jobject arrayList = translateAllGnssAntennaInfos(env, gnssAntennaInfos);
339 
340     reportAntennaInfo(env, arrayList);
341 
342     env->DeleteLocalRef(arrayList);
343 }
344 
reportAntennaInfo(JNIEnv * env,const jobject antennaInfosArray)345 void GnssAntennaInfoCallbackUtil::reportAntennaInfo(JNIEnv* env, const jobject antennaInfosArray) {
346     env->CallVoidMethod(mCallbacksObj, method_reportAntennaInfo, antennaInfosArray);
347     checkAndClearExceptionFromCallback(env, __FUNCTION__);
348 }
349 
350 } // namespace android::gnss
351