1 /*
2  * Copyright (C) 2008 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 "GnssLocationProvider"
18 
19 #define LOG_NDEBUG 0
20 
21 #include "JNIHelp.h"
22 #include "jni.h"
23 #include "hardware/hardware.h"
24 #include "hardware/gps_internal.h"
25 #include "hardware_legacy/power.h"
26 #include "utils/Log.h"
27 #include "utils/misc.h"
28 #include "android_runtime/AndroidRuntime.h"
29 #include "android_runtime/Log.h"
30 
31 #include <arpa/inet.h>
32 #include <limits>
33 #include <linux/in.h>
34 #include <linux/in6.h>
35 #include <pthread.h>
36 #include <string.h>
37 
38 static jobject mCallbacksObj = NULL;
39 
40 static jmethodID method_reportLocation;
41 static jmethodID method_reportStatus;
42 static jmethodID method_reportSvStatus;
43 static jmethodID method_reportAGpsStatus;
44 static jmethodID method_reportNmea;
45 static jmethodID method_setEngineCapabilities;
46 static jmethodID method_setGnssYearOfHardware;
47 static jmethodID method_xtraDownloadRequest;
48 static jmethodID method_reportNiNotification;
49 static jmethodID method_requestRefLocation;
50 static jmethodID method_requestSetID;
51 static jmethodID method_requestUtcTime;
52 static jmethodID method_reportGeofenceTransition;
53 static jmethodID method_reportGeofenceStatus;
54 static jmethodID method_reportGeofenceAddStatus;
55 static jmethodID method_reportGeofenceRemoveStatus;
56 static jmethodID method_reportGeofencePauseStatus;
57 static jmethodID method_reportGeofenceResumeStatus;
58 static jmethodID method_reportMeasurementData;
59 static jmethodID method_reportNavigationMessages;
60 
61 static const GpsInterface* sGpsInterface = NULL;
62 static const GpsXtraInterface* sGpsXtraInterface = NULL;
63 static const AGpsInterface* sAGpsInterface = NULL;
64 static const GpsNiInterface* sGpsNiInterface = NULL;
65 static const GpsDebugInterface* sGpsDebugInterface = NULL;
66 static const AGpsRilInterface* sAGpsRilInterface = NULL;
67 static const GpsGeofencingInterface* sGpsGeofencingInterface = NULL;
68 static const GpsMeasurementInterface* sGpsMeasurementInterface = NULL;
69 static const GpsNavigationMessageInterface* sGpsNavigationMessageInterface = NULL;
70 static const GnssConfigurationInterface* sGnssConfigurationInterface = NULL;
71 
72 #define GPS_MAX_SATELLITE_COUNT 32
73 #define GNSS_MAX_SATELLITE_COUNT 64
74 
75 // Let these through, with ID remapped down to 1, 2... by offset
76 #define GLONASS_SVID_OFFSET 64
77 #define GLONASS_SVID_COUNT 24
78 #define BEIDOU_SVID_OFFSET 200
79 #define BEIDOU_SVID_COUNT 35
80 
81 // Let these through, with ID remapped up (33->120 ... 64->151, etc.)
82 #define SBAS_SVID_MIN 33
83 #define SBAS_SVID_MAX 64
84 #define SBAS_SVID_ADD 87
85 
86 // Let these through, with no ID remapping
87 #define QZSS_SVID_MIN 193
88 #define QZSS_SVID_MAX 200
89 
90 #define SVID_SHIFT_WIDTH 7
91 #define CONSTELLATION_TYPE_SHIFT_WIDTH 3
92 
93 // temporary storage for GPS callbacks
94 static GnssSvInfo sGnssSvList[GNSS_MAX_SATELLITE_COUNT];
95 static size_t sGnssSvListSize;
96 static const char* sNmeaString;
97 static int sNmeaStringLength;
98 
99 #define WAKE_LOCK_NAME  "GPS"
100 
101 namespace android {
102 
checkAndClearExceptionFromCallback(JNIEnv * env,const char * methodName)103 static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
104     if (env->ExceptionCheck()) {
105         ALOGE("An exception was thrown by callback '%s'.", methodName);
106         LOGE_EX(env);
107         env->ExceptionClear();
108     }
109 }
110 
location_callback(GpsLocation * location)111 static void location_callback(GpsLocation* location)
112 {
113     JNIEnv* env = AndroidRuntime::getJNIEnv();
114     env->CallVoidMethod(mCallbacksObj, method_reportLocation, location->flags,
115             (jdouble)location->latitude, (jdouble)location->longitude,
116             (jdouble)location->altitude,
117             (jfloat)location->speed, (jfloat)location->bearing,
118             (jfloat)location->accuracy, (jlong)location->timestamp);
119     checkAndClearExceptionFromCallback(env, __FUNCTION__);
120 }
121 
status_callback(GpsStatus * status)122 static void status_callback(GpsStatus* status)
123 {
124     JNIEnv* env = AndroidRuntime::getJNIEnv();
125     env->CallVoidMethod(mCallbacksObj, method_reportStatus, status->status);
126     checkAndClearExceptionFromCallback(env, __FUNCTION__);
127 }
128 
sv_status_callback(GpsSvStatus * sv_status)129 static void sv_status_callback(GpsSvStatus* sv_status)
130 {
131     JNIEnv* env = AndroidRuntime::getJNIEnv();
132     size_t status_size = sv_status->size;
133     // Some drives doesn't set the size field correctly. Assume GpsSvStatus_v1
134     // if it doesn't provide a valid size.
135     if (status_size == 0) {
136         ALOGW("Invalid size of GpsSvStatus found: %zd.", status_size);
137     }
138     sGnssSvListSize = sv_status->num_svs;
139     // Clamp the list size. Legacy GpsSvStatus has only 32 elements in sv_list.
140     if (sGnssSvListSize > GPS_MAX_SATELLITE_COUNT) {
141         ALOGW("Too many satellites %zd. Clamps to %d.",
142               sGnssSvListSize,
143               GPS_MAX_SATELLITE_COUNT);
144         sGnssSvListSize = GPS_MAX_SATELLITE_COUNT;
145     }
146     uint32_t ephemeris_mask = sv_status->ephemeris_mask;
147     uint32_t almanac_mask = sv_status->almanac_mask;
148     uint32_t used_in_fix_mask = sv_status->used_in_fix_mask;
149     for (size_t i = 0; i < sGnssSvListSize; i++) {
150         GnssSvInfo& info = sGnssSvList[i];
151         info.svid = sv_status->sv_list[i].prn;
152         // Defacto mapping from the overused API that was designed for GPS-only
153         if (info.svid >=1 && info.svid <= 32) {
154             info.constellation = GNSS_CONSTELLATION_GPS;
155         } else if (info.svid > GLONASS_SVID_OFFSET &&
156                    info.svid <= GLONASS_SVID_OFFSET + GLONASS_SVID_COUNT) {
157             info.constellation = GNSS_CONSTELLATION_GLONASS;
158             info.svid -= GLONASS_SVID_OFFSET;
159         } else if (info.svid > BEIDOU_SVID_OFFSET &&
160                    info.svid <= BEIDOU_SVID_OFFSET + BEIDOU_SVID_COUNT) {
161             info.constellation = GNSS_CONSTELLATION_BEIDOU;
162             info.svid -= BEIDOU_SVID_OFFSET;
163         } else if (info.svid >= SBAS_SVID_MIN && info.svid <= SBAS_SVID_MAX) {
164             info.constellation = GNSS_CONSTELLATION_SBAS;
165             info.svid += SBAS_SVID_ADD;
166         } else if (info.svid >= QZSS_SVID_MIN && info.svid <= QZSS_SVID_MAX) {
167             info.constellation = GNSS_CONSTELLATION_QZSS;
168         } else {
169             ALOGD("Unknown constellation type with Svid = %d.", info.svid);
170             info.constellation = GNSS_CONSTELLATION_UNKNOWN;
171         }
172         info.c_n0_dbhz = sv_status->sv_list[i].snr;
173         info.elevation = sv_status->sv_list[i].elevation;
174         info.azimuth = sv_status->sv_list[i].azimuth;
175         info.flags = GNSS_SV_FLAGS_NONE;
176         // Only GPS info is valid for these fields, as these masks are just 32 bits, by GPS prn
177         if (info.constellation == GNSS_CONSTELLATION_GPS) {
178             int32_t this_svid_mask = (1 << (info.svid - 1));
179             if ((ephemeris_mask & this_svid_mask) != 0) {
180                 info.flags |= GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA;
181             }
182             if ((almanac_mask & this_svid_mask) != 0) {
183                 info.flags |= GNSS_SV_FLAGS_HAS_ALMANAC_DATA;
184             }
185             if ((used_in_fix_mask & this_svid_mask) != 0) {
186                 info.flags |= GNSS_SV_FLAGS_USED_IN_FIX;
187             }
188         }
189     }
190     env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
191     checkAndClearExceptionFromCallback(env, __FUNCTION__);
192 }
193 
gnss_sv_status_callback(GnssSvStatus * sv_status)194 static void gnss_sv_status_callback(GnssSvStatus* sv_status) {
195     JNIEnv* env = AndroidRuntime::getJNIEnv();
196     size_t status_size = sv_status->size;
197     // Check the size, and reject the object that has invalid size.
198     if (status_size != sizeof(GnssSvStatus)) {
199         ALOGE("Invalid size of GnssSvStatus found: %zd.", status_size);
200         return;
201     }
202     sGnssSvListSize = sv_status->num_svs;
203     // Clamp the list size
204     if (sGnssSvListSize > GNSS_MAX_SATELLITE_COUNT) {
205         ALOGD("Too many satellites %zd. Clamps to %d.",
206               sGnssSvListSize,
207               GNSS_MAX_SATELLITE_COUNT);
208         sGnssSvListSize = GNSS_MAX_SATELLITE_COUNT;
209     }
210     // Copy GNSS SV info into sGnssSvList, if any.
211     if (sGnssSvListSize > 0) {
212         memcpy(sGnssSvList,
213                sv_status->gnss_sv_list,
214                sizeof(GnssSvInfo) * sGnssSvListSize);
215     }
216     env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
217     checkAndClearExceptionFromCallback(env, __FUNCTION__);
218 }
219 
nmea_callback(GpsUtcTime timestamp,const char * nmea,int length)220 static void nmea_callback(GpsUtcTime timestamp, const char* nmea, int length)
221 {
222     JNIEnv* env = AndroidRuntime::getJNIEnv();
223     // The Java code will call back to read these values
224     // We do this to avoid creating unnecessary String objects
225     sNmeaString = nmea;
226     sNmeaStringLength = length;
227     env->CallVoidMethod(mCallbacksObj, method_reportNmea, timestamp);
228     checkAndClearExceptionFromCallback(env, __FUNCTION__);
229 }
230 
set_system_info_callback(const GnssSystemInfo * info)231 static void set_system_info_callback(const GnssSystemInfo* info) {
232     ALOGD("set_system_info_callback: year_of_hw=%d\n", info->year_of_hw);
233     JNIEnv* env = AndroidRuntime::getJNIEnv();
234     env->CallVoidMethod(mCallbacksObj, method_setGnssYearOfHardware,
235                         info->year_of_hw);
236     checkAndClearExceptionFromCallback(env, __FUNCTION__);
237 }
238 
set_capabilities_callback(uint32_t capabilities)239 static void set_capabilities_callback(uint32_t capabilities)
240 {
241     ALOGD("set_capabilities_callback: %du\n", capabilities);
242     JNIEnv* env = AndroidRuntime::getJNIEnv();
243     env->CallVoidMethod(mCallbacksObj, method_setEngineCapabilities, capabilities);
244     checkAndClearExceptionFromCallback(env, __FUNCTION__);
245 }
246 
acquire_wakelock_callback()247 static void acquire_wakelock_callback()
248 {
249     acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
250 }
251 
release_wakelock_callback()252 static void release_wakelock_callback()
253 {
254     release_wake_lock(WAKE_LOCK_NAME);
255 }
256 
request_utc_time_callback()257 static void request_utc_time_callback()
258 {
259     JNIEnv* env = AndroidRuntime::getJNIEnv();
260     env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
261     checkAndClearExceptionFromCallback(env, __FUNCTION__);
262 }
263 
create_thread_callback(const char * name,void (* start)(void *),void * arg)264 static pthread_t create_thread_callback(const char* name, void (*start)(void *), void* arg)
265 {
266     return (pthread_t)AndroidRuntime::createJavaThread(name, start, arg);
267 }
268 
269 GpsCallbacks sGpsCallbacks = {
270     sizeof(GpsCallbacks),
271     location_callback,
272     status_callback,
273     sv_status_callback,
274     nmea_callback,
275     set_capabilities_callback,
276     acquire_wakelock_callback,
277     release_wakelock_callback,
278     create_thread_callback,
279     request_utc_time_callback,
280     set_system_info_callback,
281     gnss_sv_status_callback,
282 };
283 
xtra_download_request_callback()284 static void xtra_download_request_callback()
285 {
286     JNIEnv* env = AndroidRuntime::getJNIEnv();
287     env->CallVoidMethod(mCallbacksObj, method_xtraDownloadRequest);
288     checkAndClearExceptionFromCallback(env, __FUNCTION__);
289 }
290 
291 GpsXtraCallbacks sGpsXtraCallbacks = {
292     xtra_download_request_callback,
293     create_thread_callback,
294 };
295 
convert_to_ipv4(uint32_t ip,bool net_order)296 static jbyteArray convert_to_ipv4(uint32_t ip, bool net_order)
297 {
298     if (INADDR_NONE == ip) {
299         return NULL;
300     }
301 
302     JNIEnv* env = AndroidRuntime::getJNIEnv();
303     jbyteArray byteArray = env->NewByteArray(4);
304     if (byteArray == NULL) {
305         ALOGE("Unable to allocate byte array for IPv4 address");
306         return NULL;
307     }
308 
309     jbyte ipv4[4];
310     if (net_order) {
311         ALOGV("Converting IPv4 address(net_order) %x", ip);
312         memcpy(ipv4, &ip, sizeof(ipv4));
313     } else {
314         ALOGV("Converting IPv4 address(host_order) %x", ip);
315         //endianess transparent conversion from int to char[]
316         ipv4[0] = (jbyte) (ip & 0xFF);
317         ipv4[1] = (jbyte)((ip>>8) & 0xFF);
318         ipv4[2] = (jbyte)((ip>>16) & 0xFF);
319         ipv4[3] = (jbyte) (ip>>24);
320     }
321 
322     env->SetByteArrayRegion(byteArray, 0, 4, (const jbyte*) ipv4);
323     return byteArray;
324 }
325 
agps_status_callback(AGpsStatus * agps_status)326 static void agps_status_callback(AGpsStatus* agps_status)
327 {
328     JNIEnv* env = AndroidRuntime::getJNIEnv();
329     jbyteArray byteArray = NULL;
330     bool isSupported = false;
331 
332     size_t status_size = agps_status->size;
333     if (status_size == sizeof(AGpsStatus)) {
334       ALOGV("AGpsStatus is V3: %zd", status_size);
335       switch (agps_status->addr.ss_family)
336       {
337       case AF_INET:
338           {
339             struct sockaddr_in *in = (struct sockaddr_in*)&(agps_status->addr);
340             uint32_t ipAddr = *(uint32_t*)&(in->sin_addr);
341             byteArray = convert_to_ipv4(ipAddr, true /* net_order */);
342             if (ipAddr == INADDR_NONE || byteArray != NULL) {
343                 isSupported = true;
344             }
345             IF_ALOGD() {
346                 // log the IP for reference in case there is a bogus value pushed by HAL
347                 char str[INET_ADDRSTRLEN];
348                 inet_ntop(AF_INET, &(in->sin_addr), str, INET_ADDRSTRLEN);
349                 ALOGD("AGPS IP is v4: %s", str);
350             }
351           }
352           break;
353       case AF_INET6:
354           {
355             struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&(agps_status->addr);
356             byteArray = env->NewByteArray(16);
357             if (byteArray != NULL) {
358                 env->SetByteArrayRegion(byteArray, 0, 16, (const jbyte *)&(in6->sin6_addr));
359                 isSupported = true;
360             } else {
361                 ALOGE("Unable to allocate byte array for IPv6 address.");
362             }
363             IF_ALOGD() {
364                 // log the IP for reference in case there is a bogus value pushed by HAL
365                 char str[INET6_ADDRSTRLEN];
366                 inet_ntop(AF_INET6, &(in6->sin6_addr), str, INET6_ADDRSTRLEN);
367                 ALOGD("AGPS IP is v6: %s", str);
368             }
369           }
370           break;
371       default:
372           ALOGE("Invalid ss_family found: %d", agps_status->addr.ss_family);
373           break;
374       }
375     } else if (status_size >= sizeof(AGpsStatus_v2)) {
376       ALOGV("AGpsStatus is V2+: %zd", status_size);
377       // for back-compatibility reasons we check in v2 that the data structure size is greater or
378       // equal to the declared size in gps.h
379       uint32_t ipaddr = agps_status->ipaddr;
380       ALOGV("AGPS IP is v4: %x", ipaddr);
381       byteArray = convert_to_ipv4(ipaddr, false /* net_order */);
382       if (ipaddr == INADDR_NONE || byteArray != NULL) {
383           isSupported = true;
384       }
385     } else if (status_size >= sizeof(AGpsStatus_v1)) {
386         ALOGV("AGpsStatus is V1+: %zd", status_size);
387         // because we have to check for >= with regards to v2, we also need to relax the check here
388         // and only make sure that the size is at least what we expect
389         isSupported = true;
390     } else {
391         ALOGE("Invalid size of AGpsStatus found: %zd.", status_size);
392     }
393 
394     if (isSupported) {
395         jsize byteArrayLength = byteArray != NULL ? env->GetArrayLength(byteArray) : 0;
396         ALOGV("Passing AGPS IP addr: size %d", byteArrayLength);
397         env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus, agps_status->type,
398                             agps_status->status, byteArray);
399 
400         checkAndClearExceptionFromCallback(env, __FUNCTION__);
401     } else {
402         ALOGD("Skipping calling method_reportAGpsStatus.");
403     }
404 
405     if (byteArray) {
406         env->DeleteLocalRef(byteArray);
407     }
408 }
409 
410 AGpsCallbacks sAGpsCallbacks = {
411     agps_status_callback,
412     create_thread_callback,
413 };
414 
gps_ni_notify_callback(GpsNiNotification * notification)415 static void gps_ni_notify_callback(GpsNiNotification *notification)
416 {
417     ALOGD("gps_ni_notify_callback\n");
418     JNIEnv* env = AndroidRuntime::getJNIEnv();
419     jstring requestor_id = env->NewStringUTF(notification->requestor_id);
420     jstring text = env->NewStringUTF(notification->text);
421     jstring extras = env->NewStringUTF(notification->extras);
422 
423     if (requestor_id && text && extras) {
424         env->CallVoidMethod(mCallbacksObj, method_reportNiNotification,
425             notification->notification_id, notification->ni_type,
426             notification->notify_flags, notification->timeout,
427             notification->default_response, requestor_id, text,
428             notification->requestor_id_encoding,
429             notification->text_encoding, extras);
430     } else {
431         ALOGE("out of memory in gps_ni_notify_callback\n");
432     }
433 
434     if (requestor_id)
435         env->DeleteLocalRef(requestor_id);
436     if (text)
437         env->DeleteLocalRef(text);
438     if (extras)
439         env->DeleteLocalRef(extras);
440     checkAndClearExceptionFromCallback(env, __FUNCTION__);
441 }
442 
443 GpsNiCallbacks sGpsNiCallbacks = {
444     gps_ni_notify_callback,
445     create_thread_callback,
446 };
447 
agps_request_set_id(uint32_t flags)448 static void agps_request_set_id(uint32_t flags)
449 {
450     JNIEnv* env = AndroidRuntime::getJNIEnv();
451     env->CallVoidMethod(mCallbacksObj, method_requestSetID, flags);
452     checkAndClearExceptionFromCallback(env, __FUNCTION__);
453 }
454 
agps_request_ref_location(uint32_t flags)455 static void agps_request_ref_location(uint32_t flags)
456 {
457     JNIEnv* env = AndroidRuntime::getJNIEnv();
458     env->CallVoidMethod(mCallbacksObj, method_requestRefLocation, flags);
459     checkAndClearExceptionFromCallback(env, __FUNCTION__);
460 }
461 
462 AGpsRilCallbacks sAGpsRilCallbacks = {
463     agps_request_set_id,
464     agps_request_ref_location,
465     create_thread_callback,
466 };
467 
gps_geofence_transition_callback(int32_t geofence_id,GpsLocation * location,int32_t transition,GpsUtcTime timestamp)468 static void gps_geofence_transition_callback(int32_t geofence_id,  GpsLocation* location,
469         int32_t transition, GpsUtcTime timestamp)
470 {
471     JNIEnv* env = AndroidRuntime::getJNIEnv();
472 
473     env->CallVoidMethod(mCallbacksObj, method_reportGeofenceTransition, geofence_id,
474             location->flags, (jdouble)location->latitude, (jdouble)location->longitude,
475             (jdouble)location->altitude,
476             (jfloat)location->speed, (jfloat)location->bearing,
477             (jfloat)location->accuracy, (jlong)location->timestamp,
478             transition, timestamp);
479     checkAndClearExceptionFromCallback(env, __FUNCTION__);
480 };
481 
gps_geofence_status_callback(int32_t status,GpsLocation * location)482 static void gps_geofence_status_callback(int32_t status, GpsLocation* location)
483 {
484     JNIEnv* env = AndroidRuntime::getJNIEnv();
485     jint flags = 0;
486     jdouble latitude = 0;
487     jdouble longitude = 0;
488     jdouble altitude = 0;
489     jfloat speed = 0;
490     jfloat bearing = 0;
491     jfloat accuracy = 0;
492     jlong timestamp = 0;
493     if (location != NULL) {
494         flags = location->flags;
495         latitude = location->latitude;
496         longitude = location->longitude;
497         altitude = location->altitude;
498         speed = location->speed;
499         bearing = location->bearing;
500         accuracy = location->accuracy;
501         timestamp = location->timestamp;
502     }
503 
504     env->CallVoidMethod(mCallbacksObj, method_reportGeofenceStatus, status,
505             flags, latitude, longitude, altitude, speed, bearing, accuracy, timestamp);
506     checkAndClearExceptionFromCallback(env, __FUNCTION__);
507 };
508 
gps_geofence_add_callback(int32_t geofence_id,int32_t status)509 static void gps_geofence_add_callback(int32_t geofence_id, int32_t status)
510 {
511     JNIEnv* env = AndroidRuntime::getJNIEnv();
512     if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
513         ALOGE("Error in geofence_add_callback: %d\n", status);
514     }
515     env->CallVoidMethod(mCallbacksObj, method_reportGeofenceAddStatus, geofence_id, status);
516     checkAndClearExceptionFromCallback(env, __FUNCTION__);
517 };
518 
gps_geofence_remove_callback(int32_t geofence_id,int32_t status)519 static void gps_geofence_remove_callback(int32_t geofence_id, int32_t status)
520 {
521     JNIEnv* env = AndroidRuntime::getJNIEnv();
522     if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
523         ALOGE("Error in geofence_remove_callback: %d\n", status);
524     }
525     env->CallVoidMethod(mCallbacksObj, method_reportGeofenceRemoveStatus, geofence_id, status);
526     checkAndClearExceptionFromCallback(env, __FUNCTION__);
527 };
528 
gps_geofence_resume_callback(int32_t geofence_id,int32_t status)529 static void gps_geofence_resume_callback(int32_t geofence_id, int32_t status)
530 {
531     JNIEnv* env = AndroidRuntime::getJNIEnv();
532     if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
533         ALOGE("Error in geofence_resume_callback: %d\n", status);
534     }
535     env->CallVoidMethod(mCallbacksObj, method_reportGeofenceResumeStatus, geofence_id, status);
536     checkAndClearExceptionFromCallback(env, __FUNCTION__);
537 };
538 
gps_geofence_pause_callback(int32_t geofence_id,int32_t status)539 static void gps_geofence_pause_callback(int32_t geofence_id, int32_t status)
540 {
541     JNIEnv* env = AndroidRuntime::getJNIEnv();
542     if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
543         ALOGE("Error in geofence_pause_callback: %d\n", status);
544     }
545     env->CallVoidMethod(mCallbacksObj, method_reportGeofencePauseStatus, geofence_id, status);
546     checkAndClearExceptionFromCallback(env, __FUNCTION__);
547 };
548 
549 GpsGeofenceCallbacks sGpsGeofenceCallbacks = {
550     gps_geofence_transition_callback,
551     gps_geofence_status_callback,
552     gps_geofence_add_callback,
553     gps_geofence_remove_callback,
554     gps_geofence_pause_callback,
555     gps_geofence_resume_callback,
556     create_thread_callback,
557 };
558 
android_location_GnssLocationProvider_class_init_native(JNIEnv * env,jclass clazz)559 static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
560     int err;
561     hw_module_t* module;
562 
563     method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
564     method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
565     method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");
566     method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V");
567     method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");
568     method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V");
569     method_setGnssYearOfHardware = env->GetMethodID(clazz, "setGnssYearOfHardware", "(I)V");
570     method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
571     method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",
572             "(IIIIILjava/lang/String;Ljava/lang/String;IILjava/lang/String;)V");
573     method_requestRefLocation = env->GetMethodID(clazz,"requestRefLocation","(I)V");
574     method_requestSetID = env->GetMethodID(clazz,"requestSetID","(I)V");
575     method_requestUtcTime = env->GetMethodID(clazz,"requestUtcTime","()V");
576     method_reportGeofenceTransition = env->GetMethodID(clazz,"reportGeofenceTransition",
577             "(IIDDDFFFJIJ)V");
578     method_reportGeofenceStatus = env->GetMethodID(clazz,"reportGeofenceStatus",
579             "(IIDDDFFFJ)V");
580     method_reportGeofenceAddStatus = env->GetMethodID(clazz,"reportGeofenceAddStatus",
581             "(II)V");
582     method_reportGeofenceRemoveStatus = env->GetMethodID(clazz,"reportGeofenceRemoveStatus",
583             "(II)V");
584     method_reportGeofenceResumeStatus = env->GetMethodID(clazz,"reportGeofenceResumeStatus",
585             "(II)V");
586     method_reportGeofencePauseStatus = env->GetMethodID(clazz,"reportGeofencePauseStatus",
587             "(II)V");
588     method_reportMeasurementData = env->GetMethodID(
589             clazz,
590             "reportMeasurementData",
591             "(Landroid/location/GnssMeasurementsEvent;)V");
592     method_reportNavigationMessages = env->GetMethodID(
593             clazz,
594             "reportNavigationMessage",
595             "(Landroid/location/GnssNavigationMessage;)V");
596 
597     err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
598     if (err == 0) {
599         hw_device_t* device;
600         err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
601         if (err == 0) {
602             gps_device_t* gps_device = (gps_device_t *)device;
603             sGpsInterface = gps_device->get_gps_interface(gps_device);
604         }
605     }
606     if (sGpsInterface) {
607         sGpsXtraInterface =
608             (const GpsXtraInterface*)sGpsInterface->get_extension(GPS_XTRA_INTERFACE);
609         sAGpsInterface =
610             (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
611         sGpsNiInterface =
612             (const GpsNiInterface*)sGpsInterface->get_extension(GPS_NI_INTERFACE);
613         sGpsDebugInterface =
614             (const GpsDebugInterface*)sGpsInterface->get_extension(GPS_DEBUG_INTERFACE);
615         sAGpsRilInterface =
616             (const AGpsRilInterface*)sGpsInterface->get_extension(AGPS_RIL_INTERFACE);
617         sGpsGeofencingInterface =
618             (const GpsGeofencingInterface*)sGpsInterface->get_extension(GPS_GEOFENCING_INTERFACE);
619         sGpsMeasurementInterface =
620             (const GpsMeasurementInterface*)sGpsInterface->get_extension(GPS_MEASUREMENT_INTERFACE);
621         sGpsNavigationMessageInterface =
622             (const GpsNavigationMessageInterface*)sGpsInterface->get_extension(
623                     GPS_NAVIGATION_MESSAGE_INTERFACE);
624         sGnssConfigurationInterface =
625             (const GnssConfigurationInterface*)sGpsInterface->get_extension(
626                     GNSS_CONFIGURATION_INTERFACE);
627     }
628 }
629 
android_location_GnssLocationProvider_is_supported(JNIEnv *,jclass)630 static jboolean android_location_GnssLocationProvider_is_supported(
631         JNIEnv* /* env */, jclass /* clazz */)
632 {
633     return (sGpsInterface != NULL) ?  JNI_TRUE : JNI_FALSE;
634 }
635 
android_location_GnssLocationProvider_is_agps_ril_supported(JNIEnv *,jclass)636 static jboolean android_location_GnssLocationProvider_is_agps_ril_supported(
637         JNIEnv* /* env */, jclass /* clazz */)
638 {
639     return (sAGpsRilInterface != NULL) ? JNI_TRUE : JNI_FALSE;
640 }
641 
android_location_gpsLocationProvider_is_gnss_configuration_supported(JNIEnv *,jclass)642 static jboolean android_location_gpsLocationProvider_is_gnss_configuration_supported(
643         JNIEnv* /* env */, jclass /* jclazz */)
644 {
645     return (sGnssConfigurationInterface != NULL) ? JNI_TRUE : JNI_FALSE;
646 }
647 
android_location_GnssLocationProvider_init(JNIEnv * env,jobject obj)648 static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject obj)
649 {
650     // this must be set before calling into the HAL library
651     if (!mCallbacksObj)
652         mCallbacksObj = env->NewGlobalRef(obj);
653 
654     // fail if the main interface fails to initialize
655     if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
656         return JNI_FALSE;
657 
658     // if XTRA initialization fails we will disable it by sGpsXtraInterface to NULL,
659     // but continue to allow the rest of the GPS interface to work.
660     if (sGpsXtraInterface && sGpsXtraInterface->init(&sGpsXtraCallbacks) != 0)
661         sGpsXtraInterface = NULL;
662     if (sAGpsInterface)
663         sAGpsInterface->init(&sAGpsCallbacks);
664     if (sGpsNiInterface)
665         sGpsNiInterface->init(&sGpsNiCallbacks);
666     if (sAGpsRilInterface)
667         sAGpsRilInterface->init(&sAGpsRilCallbacks);
668     if (sGpsGeofencingInterface)
669         sGpsGeofencingInterface->init(&sGpsGeofenceCallbacks);
670 
671     return JNI_TRUE;
672 }
673 
android_location_GnssLocationProvider_cleanup(JNIEnv *,jobject)674 static void android_location_GnssLocationProvider_cleanup(JNIEnv* /* env */, jobject /* obj */)
675 {
676     if (sGpsInterface)
677         sGpsInterface->cleanup();
678 }
679 
android_location_GnssLocationProvider_set_position_mode(JNIEnv *,jobject,jint mode,jint recurrence,jint min_interval,jint preferred_accuracy,jint preferred_time)680 static jboolean android_location_GnssLocationProvider_set_position_mode(JNIEnv* /* env */,
681         jobject /* obj */, jint mode, jint recurrence, jint min_interval, jint preferred_accuracy,
682         jint preferred_time)
683 {
684     if (sGpsInterface) {
685         if (sGpsInterface->set_position_mode(mode, recurrence, min_interval, preferred_accuracy,
686                 preferred_time) == 0) {
687             return JNI_TRUE;
688         } else {
689             return JNI_FALSE;
690         }
691     }
692     else
693         return JNI_FALSE;
694 }
695 
android_location_GnssLocationProvider_start(JNIEnv *,jobject)696 static jboolean android_location_GnssLocationProvider_start(JNIEnv* /* env */, jobject /* obj */)
697 {
698     if (sGpsInterface) {
699         if (sGpsInterface->start() == 0) {
700             return JNI_TRUE;
701         } else {
702             return JNI_FALSE;
703         }
704     }
705     else
706         return JNI_FALSE;
707 }
708 
android_location_GnssLocationProvider_stop(JNIEnv *,jobject)709 static jboolean android_location_GnssLocationProvider_stop(JNIEnv* /* env */, jobject /* obj */)
710 {
711     if (sGpsInterface) {
712         if (sGpsInterface->stop() == 0) {
713             return JNI_TRUE;
714         } else {
715             return JNI_FALSE;
716         }
717     }
718     else
719         return JNI_FALSE;
720 }
721 
android_location_GnssLocationProvider_delete_aiding_data(JNIEnv *,jobject,jint flags)722 static void android_location_GnssLocationProvider_delete_aiding_data(JNIEnv* /* env */,
723                                                                     jobject /* obj */,
724                                                                     jint flags)
725 {
726     if (sGpsInterface)
727         sGpsInterface->delete_aiding_data(flags);
728 }
729 
android_location_GnssLocationProvider_read_sv_status(JNIEnv * env,jobject,jintArray svidWithFlagArray,jfloatArray cn0Array,jfloatArray elevArray,jfloatArray azumArray)730 static jint android_location_GnssLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */,
731         jintArray svidWithFlagArray, jfloatArray cn0Array, jfloatArray elevArray,
732         jfloatArray azumArray)
733 {
734     // this should only be called from within a call to reportSvStatus
735     jint* svidWithFlags = env->GetIntArrayElements(svidWithFlagArray, 0);
736     jfloat* cn0s = env->GetFloatArrayElements(cn0Array, 0);
737     jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
738     jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
739 
740     // GNSS SV info.
741     for (size_t i = 0; i < sGnssSvListSize; ++i) {
742         const GnssSvInfo& info = sGnssSvList[i];
743         svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) |
744             (info.constellation << CONSTELLATION_TYPE_SHIFT_WIDTH) |
745             info.flags;
746         cn0s[i] = info.c_n0_dbhz;
747         elev[i] = info.elevation;
748         azim[i] = info.azimuth;
749     }
750 
751     env->ReleaseIntArrayElements(svidWithFlagArray, svidWithFlags, 0);
752     env->ReleaseFloatArrayElements(cn0Array, cn0s, 0);
753     env->ReleaseFloatArrayElements(elevArray, elev, 0);
754     env->ReleaseFloatArrayElements(azumArray, azim, 0);
755     return (jint) sGnssSvListSize;
756 }
757 
android_location_GnssLocationProvider_agps_set_reference_location_cellid(JNIEnv *,jobject,jint type,jint mcc,jint mnc,jint lac,jint cid)758 static void android_location_GnssLocationProvider_agps_set_reference_location_cellid(
759         JNIEnv* /* env */, jobject /* obj */, jint type, jint mcc, jint mnc, jint lac, jint cid)
760 {
761     AGpsRefLocation location;
762 
763     if (!sAGpsRilInterface) {
764         ALOGE("no AGPS RIL interface in agps_set_reference_location_cellid");
765         return;
766     }
767 
768     switch(type) {
769         case AGPS_REF_LOCATION_TYPE_GSM_CELLID:
770         case AGPS_REF_LOCATION_TYPE_UMTS_CELLID:
771             location.type = type;
772             location.u.cellID.mcc = mcc;
773             location.u.cellID.mnc = mnc;
774             location.u.cellID.lac = lac;
775             location.u.cellID.cid = cid;
776             break;
777         default:
778             ALOGE("Neither a GSM nor a UMTS cellid (%s:%d).",__FUNCTION__,__LINE__);
779             return;
780             break;
781     }
782     sAGpsRilInterface->set_ref_location(&location, sizeof(location));
783 }
784 
android_location_GnssLocationProvider_agps_send_ni_message(JNIEnv * env,jobject,jbyteArray ni_msg,jint size)785 static void android_location_GnssLocationProvider_agps_send_ni_message(JNIEnv* env,
786         jobject /* obj */, jbyteArray ni_msg, jint size)
787 {
788     size_t sz;
789 
790     if (!sAGpsRilInterface) {
791         ALOGE("no AGPS RIL interface in send_ni_message");
792         return;
793     }
794     if (size < 0)
795         return;
796     sz = (size_t)size;
797     jbyte* b = env->GetByteArrayElements(ni_msg, 0);
798     sAGpsRilInterface->ni_message((uint8_t *)b,sz);
799     env->ReleaseByteArrayElements(ni_msg,b,0);
800 }
801 
android_location_GnssLocationProvider_agps_set_id(JNIEnv * env,jobject,jint type,jstring setid_string)802 static void android_location_GnssLocationProvider_agps_set_id(JNIEnv *env, jobject /* obj */,
803                                                              jint type, jstring  setid_string)
804 {
805     if (!sAGpsRilInterface) {
806         ALOGE("no AGPS RIL interface in agps_set_id");
807         return;
808     }
809 
810     const char *setid = env->GetStringUTFChars(setid_string, NULL);
811     sAGpsRilInterface->set_set_id(type, setid);
812     env->ReleaseStringUTFChars(setid_string, setid);
813 }
814 
android_location_GnssLocationProvider_read_nmea(JNIEnv * env,jobject,jbyteArray nmeaArray,jint buffer_size)815 static jint android_location_GnssLocationProvider_read_nmea(JNIEnv* env, jobject /* obj */,
816                                             jbyteArray nmeaArray, jint buffer_size)
817 {
818     // this should only be called from within a call to reportNmea
819     jbyte* nmea = (jbyte *)env->GetPrimitiveArrayCritical(nmeaArray, 0);
820     int length = sNmeaStringLength;
821     if (length > buffer_size)
822         length = buffer_size;
823     memcpy(nmea, sNmeaString, length);
824     env->ReleasePrimitiveArrayCritical(nmeaArray, nmea, JNI_ABORT);
825     return (jint) length;
826 }
827 
android_location_GnssLocationProvider_inject_time(JNIEnv *,jobject,jlong time,jlong timeReference,jint uncertainty)828 static void android_location_GnssLocationProvider_inject_time(JNIEnv* /* env */, jobject /* obj */,
829         jlong time, jlong timeReference, jint uncertainty)
830 {
831     if (sGpsInterface)
832         sGpsInterface->inject_time(time, timeReference, uncertainty);
833 }
834 
android_location_GnssLocationProvider_inject_location(JNIEnv *,jobject,jdouble latitude,jdouble longitude,jfloat accuracy)835 static void android_location_GnssLocationProvider_inject_location(JNIEnv* /* env */,
836         jobject /* obj */, jdouble latitude, jdouble longitude, jfloat accuracy)
837 {
838     if (sGpsInterface)
839         sGpsInterface->inject_location(latitude, longitude, accuracy);
840 }
841 
android_location_GnssLocationProvider_supports_xtra(JNIEnv *,jobject)842 static jboolean android_location_GnssLocationProvider_supports_xtra(
843         JNIEnv* /* env */, jobject /* obj */)
844 {
845     return (sGpsXtraInterface != NULL) ? JNI_TRUE : JNI_FALSE;
846 }
847 
android_location_GnssLocationProvider_inject_xtra_data(JNIEnv * env,jobject,jbyteArray data,jint length)848 static void android_location_GnssLocationProvider_inject_xtra_data(JNIEnv* env, jobject /* obj */,
849         jbyteArray data, jint length)
850 {
851     if (!sGpsXtraInterface) {
852         ALOGE("no XTRA interface in inject_xtra_data");
853         return;
854     }
855 
856     jbyte* bytes = (jbyte *)env->GetPrimitiveArrayCritical(data, 0);
857     sGpsXtraInterface->inject_xtra_data((char *)bytes, length);
858     env->ReleasePrimitiveArrayCritical(data, bytes, JNI_ABORT);
859 }
860 
android_location_GnssLocationProvider_agps_data_conn_open(JNIEnv * env,jobject,jstring apn,jint apnIpType)861 static void android_location_GnssLocationProvider_agps_data_conn_open(
862         JNIEnv* env, jobject /* obj */, jstring apn, jint apnIpType)
863 {
864     if (!sAGpsInterface) {
865         ALOGE("no AGPS interface in agps_data_conn_open");
866         return;
867     }
868     if (apn == NULL) {
869         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
870         return;
871     }
872 
873     const char *apnStr = env->GetStringUTFChars(apn, NULL);
874 
875     size_t interface_size = sAGpsInterface->size;
876     if (interface_size == sizeof(AGpsInterface)) {
877         sAGpsInterface->data_conn_open_with_apn_ip_type(apnStr, apnIpType);
878     } else if (interface_size == sizeof(AGpsInterface_v1)) {
879         sAGpsInterface->data_conn_open(apnStr);
880     } else {
881         ALOGE("Invalid size of AGpsInterface found: %zd.", interface_size);
882     }
883 
884     env->ReleaseStringUTFChars(apn, apnStr);
885 }
886 
android_location_GnssLocationProvider_agps_data_conn_closed(JNIEnv *,jobject)887 static void android_location_GnssLocationProvider_agps_data_conn_closed(JNIEnv* /* env */,
888                                                                        jobject /* obj */)
889 {
890     if (!sAGpsInterface) {
891         ALOGE("no AGPS interface in agps_data_conn_closed");
892         return;
893     }
894     sAGpsInterface->data_conn_closed();
895 }
896 
android_location_GnssLocationProvider_agps_data_conn_failed(JNIEnv *,jobject)897 static void android_location_GnssLocationProvider_agps_data_conn_failed(JNIEnv* /* env */,
898                                                                        jobject /* obj */)
899 {
900     if (!sAGpsInterface) {
901         ALOGE("no AGPS interface in agps_data_conn_failed");
902         return;
903     }
904     sAGpsInterface->data_conn_failed();
905 }
906 
android_location_GnssLocationProvider_set_agps_server(JNIEnv * env,jobject,jint type,jstring hostname,jint port)907 static void android_location_GnssLocationProvider_set_agps_server(JNIEnv* env, jobject /* obj */,
908         jint type, jstring hostname, jint port)
909 {
910     if (!sAGpsInterface) {
911         ALOGE("no AGPS interface in set_agps_server");
912         return;
913     }
914     const char *c_hostname = env->GetStringUTFChars(hostname, NULL);
915     sAGpsInterface->set_server(type, c_hostname, port);
916     env->ReleaseStringUTFChars(hostname, c_hostname);
917 }
918 
android_location_GnssLocationProvider_send_ni_response(JNIEnv *,jobject,jint notifId,jint response)919 static void android_location_GnssLocationProvider_send_ni_response(JNIEnv* /* env */,
920       jobject /* obj */, jint notifId, jint response)
921 {
922     if (!sGpsNiInterface) {
923         ALOGE("no NI interface in send_ni_response");
924         return;
925     }
926 
927     sGpsNiInterface->respond(notifId, response);
928 }
929 
android_location_GnssLocationProvider_get_internal_state(JNIEnv * env,jobject)930 static jstring android_location_GnssLocationProvider_get_internal_state(JNIEnv* env,
931                                                                        jobject /* obj */) {
932     jstring result = NULL;
933     if (sGpsDebugInterface) {
934         const size_t maxLength = 2047;
935         char buffer[maxLength+1];
936         size_t length = sGpsDebugInterface->get_internal_state(buffer, maxLength);
937         if (length > maxLength) length = maxLength;
938         buffer[length] = 0;
939         result = env->NewStringUTF(buffer);
940     }
941     return result;
942 }
943 
android_location_GnssLocationProvider_update_network_state(JNIEnv * env,jobject,jboolean connected,jint type,jboolean roaming,jboolean available,jstring extraInfo,jstring apn)944 static void android_location_GnssLocationProvider_update_network_state(JNIEnv* env, jobject /* obj */,
945         jboolean connected, jint type, jboolean roaming, jboolean available, jstring extraInfo, jstring apn)
946 {
947 
948     if (sAGpsRilInterface && sAGpsRilInterface->update_network_state) {
949         if (extraInfo) {
950             const char *extraInfoStr = env->GetStringUTFChars(extraInfo, NULL);
951             sAGpsRilInterface->update_network_state(connected, type, roaming, extraInfoStr);
952             env->ReleaseStringUTFChars(extraInfo, extraInfoStr);
953         } else {
954             sAGpsRilInterface->update_network_state(connected, type, roaming, NULL);
955         }
956 
957         // update_network_availability callback was not included in original AGpsRilInterface
958         if (sAGpsRilInterface->size >= sizeof(AGpsRilInterface)
959                 && sAGpsRilInterface->update_network_availability) {
960             const char *c_apn = env->GetStringUTFChars(apn, NULL);
961             sAGpsRilInterface->update_network_availability(available, c_apn);
962             env->ReleaseStringUTFChars(apn, c_apn);
963         }
964     }
965 }
966 
android_location_GnssLocationProvider_is_geofence_supported(JNIEnv *,jobject)967 static jboolean android_location_GnssLocationProvider_is_geofence_supported(
968         JNIEnv* /* env */, jobject /* obj */)
969 {
970     return (sGpsGeofencingInterface != NULL) ? JNI_TRUE : JNI_FALSE;
971 }
972 
android_location_GnssLocationProvider_add_geofence(JNIEnv *,jobject,jint geofence_id,jdouble latitude,jdouble longitude,jdouble radius,jint last_transition,jint monitor_transition,jint notification_responsiveness,jint unknown_timer)973 static jboolean android_location_GnssLocationProvider_add_geofence(JNIEnv* /* env */,
974         jobject /* obj */, jint geofence_id, jdouble latitude, jdouble longitude, jdouble radius,
975         jint last_transition, jint monitor_transition, jint notification_responsiveness,
976         jint unknown_timer) {
977     if (sGpsGeofencingInterface != NULL) {
978         sGpsGeofencingInterface->add_geofence_area(geofence_id, latitude, longitude,
979                 radius, last_transition, monitor_transition, notification_responsiveness,
980                 unknown_timer);
981         return JNI_TRUE;
982     } else {
983         ALOGE("Geofence interface not available");
984     }
985     return JNI_FALSE;
986 }
987 
android_location_GnssLocationProvider_remove_geofence(JNIEnv *,jobject,jint geofence_id)988 static jboolean android_location_GnssLocationProvider_remove_geofence(JNIEnv* /* env */,
989         jobject /* obj */, jint geofence_id) {
990     if (sGpsGeofencingInterface != NULL) {
991         sGpsGeofencingInterface->remove_geofence_area(geofence_id);
992         return JNI_TRUE;
993     } else {
994         ALOGE("Geofence interface not available");
995     }
996     return JNI_FALSE;
997 }
998 
android_location_GnssLocationProvider_pause_geofence(JNIEnv *,jobject,jint geofence_id)999 static jboolean android_location_GnssLocationProvider_pause_geofence(JNIEnv* /* env */,
1000         jobject /* obj */, jint geofence_id) {
1001     if (sGpsGeofencingInterface != NULL) {
1002         sGpsGeofencingInterface->pause_geofence(geofence_id);
1003         return JNI_TRUE;
1004     } else {
1005         ALOGE("Geofence interface not available");
1006     }
1007     return JNI_FALSE;
1008 }
1009 
android_location_GnssLocationProvider_resume_geofence(JNIEnv *,jobject,jint geofence_id,jint monitor_transition)1010 static jboolean android_location_GnssLocationProvider_resume_geofence(JNIEnv* /* env */,
1011         jobject /* obj */, jint geofence_id, jint monitor_transition) {
1012     if (sGpsGeofencingInterface != NULL) {
1013         sGpsGeofencingInterface->resume_geofence(geofence_id, monitor_transition);
1014         return JNI_TRUE;
1015     } else {
1016         ALOGE("Geofence interface not available");
1017     }
1018     return JNI_FALSE;
1019 }
1020 
1021 template<class T>
1022 class JavaMethodHelper {
1023   public:
1024    // Helper function to call setter on a Java object.
1025    static void callJavaMethod(
1026            JNIEnv* env,
1027            jclass clazz,
1028            jobject object,
1029            const char* method_name,
1030            T value);
1031 
1032   private:
1033     static const char *const signature_;
1034 };
1035 
1036 template<class T>
callJavaMethod(JNIEnv * env,jclass clazz,jobject object,const char * method_name,T value)1037 void JavaMethodHelper<T>::callJavaMethod(
1038         JNIEnv* env,
1039         jclass clazz,
1040         jobject object,
1041         const char* method_name,
1042         T value) {
1043     jmethodID method = env->GetMethodID(clazz, method_name, signature_);
1044     env->CallVoidMethod(object, method, value);
1045 }
1046 
1047 class JavaObject {
1048   public:
1049    JavaObject(JNIEnv* env, const char* class_name);
1050    virtual ~JavaObject();
1051 
1052    template<class T>
1053    void callSetter(const char* method_name, T value);
1054    template<class T>
1055    void callSetter(const char* method_name, T* value, size_t size);
1056    jobject get();
1057 
1058   private:
1059    JNIEnv* env_;
1060    jclass clazz_;
1061    jobject object_;
1062 };
1063 
JavaObject(JNIEnv * env,const char * class_name)1064 JavaObject::JavaObject(JNIEnv* env, const char* class_name) : env_(env) {
1065     clazz_ = env_->FindClass(class_name);
1066     jmethodID ctor = env->GetMethodID(clazz_, "<init>", "()V");
1067     object_ = env_->NewObject(clazz_, ctor);
1068 }
1069 
~JavaObject()1070 JavaObject::~JavaObject() {
1071     env_->DeleteLocalRef(clazz_);
1072 }
1073 
1074 template<class T>
callSetter(const char * method_name,T value)1075 void JavaObject::callSetter(const char* method_name, T value) {
1076     JavaMethodHelper<T>::callJavaMethod(
1077             env_, clazz_, object_, method_name, value);
1078 }
1079 
1080 template<>
callSetter(const char * method_name,uint8_t * value,size_t size)1081 void JavaObject::callSetter(
1082         const char* method_name, uint8_t* value, size_t size) {
1083     jbyteArray array = env_->NewByteArray(size);
1084     env_->SetByteArrayRegion(array, 0, size, (jbyte*) value);
1085     jmethodID method = env_->GetMethodID(
1086             clazz_,
1087             method_name,
1088             "([B)V");
1089     env_->CallVoidMethod(object_, method, array);
1090 }
1091 
get()1092 jobject JavaObject::get() {
1093     return object_;
1094 }
1095 
1096 // Define Java method signatures for all known types.
1097 
1098 template<>
1099 const char *const JavaMethodHelper<uint8_t>::signature_ = "(B)V";
1100 template<>
1101 const char *const JavaMethodHelper<int8_t>::signature_ = "(B)V";
1102 template<>
1103 const char *const JavaMethodHelper<int16_t>::signature_ = "(S)V";
1104 template<>
1105 const char *const JavaMethodHelper<uint16_t>::signature_ = "(S)V";
1106 template<>
1107 const char *const JavaMethodHelper<int32_t>::signature_ = "(I)V";
1108 template<>
1109 const char *const JavaMethodHelper<uint32_t>::signature_ = "(I)V";
1110 template<>
1111 const char *const JavaMethodHelper<int64_t>::signature_ = "(J)V";
1112 template<>
1113 const char *const JavaMethodHelper<float>::signature_ = "(F)V";
1114 template<>
1115 const char *const JavaMethodHelper<double>::signature_ = "(D)V";
1116 template<>
1117 const char *const JavaMethodHelper<bool>::signature_ = "(Z)V";
1118 
1119 #define SET(setter, value) object.callSetter("set" # setter, (value))
1120 
1121 // If you want to check if a flag is not set, use SET_IF_NOT(FLAG, setter,
1122 // value) to do that. SET_IF(!FLAG, setter, value) won't compile.
1123 //
1124 // This macros generates compilation error if the provided 'flag' is not a
1125 // single token. For example, 'GNSS_CLOCK_HAS_BIAS' can be accepted, but
1126 // '!GNSS_CLOCK_HAS_DRIFT' will fail to compile.
1127 #define SET_IF(flag, setter, value) do { \
1128         if (flags & flag) { \
1129             JavaObject& name_check_##flag = object; \
1130             name_check_##flag.callSetter("set" # setter, (value)); \
1131         } \
1132     } while (false)
1133 #define SET_IF_NOT(flag, setter, value) do { \
1134         if (!(flags & flag)) { \
1135             JavaObject& name_check_##flag = object; \
1136             name_check_##flag.callSetter("set" # setter, (value)); \
1137         } \
1138     } while (false)
1139 
translate_gps_clock(JNIEnv * env,GpsClock * clock)1140 static jobject translate_gps_clock(JNIEnv* env, GpsClock* clock) {
1141     static uint32_t discontinuity_count_to_handle_old_clock_type = 0;
1142     JavaObject object(env, "android/location/GnssClock");
1143     GpsClockFlags flags = clock->flags;
1144 
1145     SET_IF(GPS_CLOCK_HAS_LEAP_SECOND,
1146            LeapSecond,
1147            static_cast<int32_t>(clock->leap_second));
1148 
1149     // GnssClock only supports the more effective HW_CLOCK type, so type
1150     // handling and documentation complexity has been removed.  To convert the
1151     // old GPS_CLOCK types (active only in a limited number of older devices),
1152     // the GPS time information is handled as an always discontinuous HW clock,
1153     // with the GPS time information put into the full_bias_ns instead - so that
1154     // time_ns - full_bias_ns = local estimate of GPS time. Additionally, the
1155     // sign of full_bias_ns and bias_ns has flipped between GpsClock &
1156     // GnssClock, so that is also handled below.
1157     switch (clock->type) {
1158       case GPS_CLOCK_TYPE_UNKNOWN:
1159         // Clock type unsupported.
1160         ALOGE("Unknown clock type provided.");
1161         break;
1162       case GPS_CLOCK_TYPE_LOCAL_HW_TIME:
1163         // Already local hardware time. No need to do anything.
1164         break;
1165       case GPS_CLOCK_TYPE_GPS_TIME:
1166         // GPS time, need to convert.
1167         flags |= GPS_CLOCK_HAS_FULL_BIAS;
1168         clock->full_bias_ns = clock->time_ns;
1169         clock->time_ns = 0;
1170         SET(HardwareClockDiscontinuityCount,
1171             discontinuity_count_to_handle_old_clock_type++);
1172         break;
1173     }
1174 
1175     SET(TimeNanos, clock->time_ns);
1176     SET_IF(GPS_CLOCK_HAS_TIME_UNCERTAINTY,
1177            TimeUncertaintyNanos,
1178            clock->time_uncertainty_ns);
1179 
1180     // Definition of sign for full_bias_ns & bias_ns has been changed since N,
1181     // so flip signs here.
1182     SET_IF(GPS_CLOCK_HAS_FULL_BIAS, FullBiasNanos, -(clock->full_bias_ns));
1183     SET_IF(GPS_CLOCK_HAS_BIAS, BiasNanos, -(clock->bias_ns));
1184 
1185     SET_IF(GPS_CLOCK_HAS_BIAS_UNCERTAINTY,
1186            BiasUncertaintyNanos,
1187            clock->bias_uncertainty_ns);
1188     SET_IF(GPS_CLOCK_HAS_DRIFT, DriftNanosPerSecond, clock->drift_nsps);
1189     SET_IF(GPS_CLOCK_HAS_DRIFT_UNCERTAINTY,
1190            DriftUncertaintyNanosPerSecond,
1191            clock->drift_uncertainty_nsps);
1192 
1193     return object.get();
1194 }
1195 
translate_gnss_clock(JNIEnv * env,GnssClock * clock)1196 static jobject translate_gnss_clock(JNIEnv* env, GnssClock* clock) {
1197     JavaObject object(env, "android/location/GnssClock");
1198     GnssClockFlags flags = clock->flags;
1199 
1200     SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND,
1201            LeapSecond,
1202            static_cast<int32_t>(clock->leap_second));
1203     SET(TimeNanos, clock->time_ns);
1204     SET_IF(GNSS_CLOCK_HAS_TIME_UNCERTAINTY,
1205            TimeUncertaintyNanos,
1206            clock->time_uncertainty_ns);
1207     SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasNanos, clock->full_bias_ns);
1208     SET_IF(GNSS_CLOCK_HAS_BIAS, BiasNanos, clock->bias_ns);
1209     SET_IF(GNSS_CLOCK_HAS_BIAS_UNCERTAINTY,
1210            BiasUncertaintyNanos,
1211            clock->bias_uncertainty_ns);
1212     SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftNanosPerSecond, clock->drift_nsps);
1213     SET_IF(GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY,
1214            DriftUncertaintyNanosPerSecond,
1215            clock->drift_uncertainty_nsps);
1216 
1217     SET(HardwareClockDiscontinuityCount, clock->hw_clock_discontinuity_count);
1218 
1219     return object.get();
1220 }
1221 
translate_gps_measurement(JNIEnv * env,GpsMeasurement * measurement)1222 static jobject translate_gps_measurement(JNIEnv* env,
1223                                          GpsMeasurement* measurement) {
1224     JavaObject object(env, "android/location/GnssMeasurement");
1225     GpsMeasurementFlags flags = measurement->flags;
1226     SET(Svid, static_cast<int32_t>(measurement->prn));
1227     if (measurement->prn >= 1 && measurement->prn <= 32) {
1228         SET(ConstellationType, static_cast<int32_t>(GNSS_CONSTELLATION_GPS));
1229     } else {
1230         ALOGD("Unknown constellation type with Svid = %d.", measurement->prn);
1231         SET(ConstellationType,
1232             static_cast<int32_t>(GNSS_CONSTELLATION_UNKNOWN));
1233     }
1234     SET(TimeOffsetNanos, measurement->time_offset_ns);
1235     SET(State, static_cast<int32_t>(measurement->state));
1236     SET(ReceivedSvTimeNanos, measurement->received_gps_tow_ns);
1237     SET(ReceivedSvTimeUncertaintyNanos,
1238         measurement->received_gps_tow_uncertainty_ns);
1239     SET(Cn0DbHz, measurement->c_n0_dbhz);
1240     SET(PseudorangeRateMetersPerSecond, measurement->pseudorange_rate_mps);
1241     SET(PseudorangeRateUncertaintyMetersPerSecond,
1242         measurement->pseudorange_rate_uncertainty_mps);
1243     SET(AccumulatedDeltaRangeState,
1244         static_cast<int32_t>(measurement->accumulated_delta_range_state));
1245     SET(AccumulatedDeltaRangeMeters, measurement->accumulated_delta_range_m);
1246     SET(AccumulatedDeltaRangeUncertaintyMeters,
1247         measurement->accumulated_delta_range_uncertainty_m);
1248     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
1249            CarrierFrequencyHz,
1250            measurement->carrier_frequency_hz);
1251     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
1252            CarrierCycles,
1253            measurement->carrier_cycles);
1254     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE,
1255            CarrierPhase,
1256            measurement->carrier_phase);
1257     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
1258            CarrierPhaseUncertainty,
1259            measurement->carrier_phase_uncertainty);
1260     SET(MultipathIndicator,
1261         static_cast<int32_t>(measurement->multipath_indicator));
1262     SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
1263 
1264     return object.get();
1265 }
1266 
translate_gnss_measurement(JNIEnv * env,GnssMeasurement * measurement)1267 static jobject translate_gnss_measurement(JNIEnv* env,
1268                                           GnssMeasurement* measurement) {
1269     JavaObject object(env, "android/location/GnssMeasurement");
1270 
1271     GnssMeasurementFlags flags = measurement->flags;
1272 
1273     SET(Svid, static_cast<int32_t>(measurement->svid));
1274     SET(ConstellationType, static_cast<int32_t>(measurement->constellation));
1275     SET(TimeOffsetNanos, measurement->time_offset_ns);
1276     SET(State, static_cast<int32_t>(measurement->state));
1277     SET(ReceivedSvTimeNanos, measurement->received_sv_time_in_ns);
1278     SET(ReceivedSvTimeUncertaintyNanos,
1279         measurement->received_sv_time_uncertainty_in_ns);
1280     SET(Cn0DbHz, measurement->c_n0_dbhz);
1281     SET(PseudorangeRateMetersPerSecond, measurement->pseudorange_rate_mps);
1282     SET(PseudorangeRateUncertaintyMetersPerSecond,
1283         measurement->pseudorange_rate_uncertainty_mps);
1284     SET(AccumulatedDeltaRangeState,
1285         static_cast<int32_t>(measurement->accumulated_delta_range_state));
1286     SET(AccumulatedDeltaRangeMeters, measurement->accumulated_delta_range_m);
1287     SET(AccumulatedDeltaRangeUncertaintyMeters,
1288         measurement->accumulated_delta_range_uncertainty_m);
1289     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
1290            CarrierFrequencyHz,
1291            measurement->carrier_frequency_hz);
1292     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
1293            CarrierCycles,
1294            measurement->carrier_cycles);
1295     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE,
1296            CarrierPhase,
1297            measurement->carrier_phase);
1298     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
1299            CarrierPhaseUncertainty,
1300            measurement->carrier_phase_uncertainty);
1301     SET(MultipathIndicator,
1302         static_cast<int32_t>(measurement->multipath_indicator));
1303     SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
1304 
1305     return object.get();
1306 }
1307 
translate_gps_measurements(JNIEnv * env,GpsMeasurement * measurements,size_t count)1308 static jobjectArray translate_gps_measurements(JNIEnv* env,
1309                                                GpsMeasurement* measurements,
1310                                                size_t count) {
1311     if (count == 0) {
1312         return NULL;
1313     }
1314 
1315     jclass gnssMeasurementClass = env->FindClass(
1316             "android/location/GnssMeasurement");
1317     jobjectArray gnssMeasurementArray = env->NewObjectArray(
1318             count,
1319             gnssMeasurementClass,
1320             NULL /* initialElement */);
1321 
1322     for (uint16_t i = 0; i < count; ++i) {
1323         jobject gnssMeasurement = translate_gps_measurement(
1324             env,
1325             &measurements[i]);
1326         env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
1327         env->DeleteLocalRef(gnssMeasurement);
1328     }
1329 
1330     env->DeleteLocalRef(gnssMeasurementClass);
1331     return gnssMeasurementArray;
1332 }
1333 
translate_gnss_measurements(JNIEnv * env,GnssMeasurement * measurements,size_t count)1334 static jobjectArray translate_gnss_measurements(JNIEnv* env,
1335                                                 GnssMeasurement* measurements,
1336                                                 size_t count) {
1337     if (count == 0) {
1338         return NULL;
1339     }
1340 
1341     jclass gnssMeasurementClass = env->FindClass(
1342             "android/location/GnssMeasurement");
1343     jobjectArray gnssMeasurementArray = env->NewObjectArray(
1344             count,
1345             gnssMeasurementClass,
1346             NULL /* initialElement */);
1347 
1348     for (uint16_t i = 0; i < count; ++i) {
1349         jobject gnssMeasurement = translate_gnss_measurement(
1350             env,
1351             &measurements[i]);
1352         env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
1353         env->DeleteLocalRef(gnssMeasurement);
1354     }
1355 
1356     env->DeleteLocalRef(gnssMeasurementClass);
1357     return gnssMeasurementArray;
1358 }
1359 
set_measurement_data(JNIEnv * env,jobject clock,jobjectArray measurementArray)1360 static void set_measurement_data(JNIEnv *env,
1361                                  jobject clock,
1362                                  jobjectArray measurementArray) {
1363     jclass gnssMeasurementsEventClass = env->FindClass(
1364             "android/location/GnssMeasurementsEvent");
1365     jmethodID gnssMeasurementsEventCtor = env->GetMethodID(
1366         gnssMeasurementsEventClass,
1367         "<init>",
1368         "(Landroid/location/GnssClock;[Landroid/location/GnssMeasurement;)V");
1369 
1370     jobject gnssMeasurementsEvent = env->NewObject(
1371         gnssMeasurementsEventClass,
1372         gnssMeasurementsEventCtor,
1373         clock,
1374         measurementArray);
1375     env->CallVoidMethod(mCallbacksObj,
1376                         method_reportMeasurementData,
1377                         gnssMeasurementsEvent);
1378     checkAndClearExceptionFromCallback(env, __FUNCTION__);
1379     env->DeleteLocalRef(gnssMeasurementsEventClass);
1380     env->DeleteLocalRef(gnssMeasurementsEvent);
1381 }
1382 
measurement_callback(GpsData * data)1383 static void measurement_callback(GpsData* data) {
1384     JNIEnv* env = AndroidRuntime::getJNIEnv();
1385     if (data == NULL) {
1386         ALOGE("Invalid data provided to gps_measurement_callback");
1387         return;
1388     }
1389     if (data->size != sizeof(GpsData)) {
1390         ALOGE("Invalid GpsData size found in gps_measurement_callback, "
1391               "size=%zd",
1392               data->size);
1393         return;
1394     }
1395 
1396     jobject clock;
1397     jobjectArray measurementArray;
1398     clock = translate_gps_clock(env, &data->clock);
1399     measurementArray = translate_gps_measurements(
1400             env, data->measurements, data->measurement_count);
1401     set_measurement_data(env, clock, measurementArray);
1402 
1403     env->DeleteLocalRef(clock);
1404     env->DeleteLocalRef(measurementArray);
1405 }
1406 
gnss_measurement_callback(GnssData * data)1407 static void gnss_measurement_callback(GnssData* data) {
1408     JNIEnv* env = AndroidRuntime::getJNIEnv();
1409     if (data == NULL) {
1410         ALOGE("Invalid data provided to gps_measurement_callback");
1411         return;
1412     }
1413     if (data->size != sizeof(GnssData)) {
1414         ALOGE("Invalid GnssData size found in gnss_measurement_callback, "
1415               "size=%zd",
1416               data->size);
1417         return;
1418     }
1419 
1420     jobject clock;
1421     jobjectArray measurementArray;
1422     clock = translate_gnss_clock(env, &data->clock);
1423     measurementArray = translate_gnss_measurements(
1424             env, data->measurements, data->measurement_count);
1425     set_measurement_data(env, clock, measurementArray);
1426 
1427     env->DeleteLocalRef(clock);
1428     env->DeleteLocalRef(measurementArray);
1429 }
1430 
1431 GpsMeasurementCallbacks sGpsMeasurementCallbacks = {
1432     sizeof(GpsMeasurementCallbacks),
1433     measurement_callback,
1434     gnss_measurement_callback,
1435 };
1436 
android_location_GnssLocationProvider_is_measurement_supported(JNIEnv * env,jclass clazz)1437 static jboolean android_location_GnssLocationProvider_is_measurement_supported(
1438         JNIEnv* env,
1439         jclass clazz) {
1440     if (sGpsMeasurementInterface != NULL) {
1441         return JNI_TRUE;
1442     }
1443     return JNI_FALSE;
1444 }
1445 
android_location_GnssLocationProvider_start_measurement_collection(JNIEnv * env,jobject obj)1446 static jboolean android_location_GnssLocationProvider_start_measurement_collection(
1447         JNIEnv* env,
1448         jobject obj) {
1449     if (sGpsMeasurementInterface == NULL) {
1450         ALOGE("Measurement interface is not available.");
1451         return JNI_FALSE;
1452     }
1453 
1454     int result = sGpsMeasurementInterface->init(&sGpsMeasurementCallbacks);
1455     if (result != GPS_GEOFENCE_OPERATION_SUCCESS) {
1456         ALOGE("An error has been found on GpsMeasurementInterface::init, status=%d", result);
1457         return JNI_FALSE;
1458     }
1459 
1460     return JNI_TRUE;
1461 }
1462 
android_location_GnssLocationProvider_stop_measurement_collection(JNIEnv * env,jobject obj)1463 static jboolean android_location_GnssLocationProvider_stop_measurement_collection(
1464         JNIEnv* env,
1465         jobject obj) {
1466     if (sGpsMeasurementInterface == NULL) {
1467         ALOGE("Measurement interface not available");
1468         return JNI_FALSE;
1469     }
1470 
1471     sGpsMeasurementInterface->close();
1472     return JNI_TRUE;
1473 }
1474 
translate_gps_navigation_message(JNIEnv * env,GpsNavigationMessage * message)1475 static jobject translate_gps_navigation_message(JNIEnv* env, GpsNavigationMessage* message) {
1476     size_t dataLength = message->data_length;
1477     uint8_t* data = message->data;
1478     if (dataLength == 0 || data == NULL) {
1479         ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
1480         return NULL;
1481     }
1482     JavaObject object(env, "android/location/GnssNavigationMessage");
1483     SET(Svid, static_cast<int32_t>(message->prn));
1484     if (message->prn >=1 && message->prn <= 32) {
1485         SET(ConstellationType, static_cast<int32_t>(GNSS_CONSTELLATION_GPS));
1486         // Legacy driver doesn't set the higher byte to constellation type
1487         // correctly. Set the higher byte to 'GPS'.
1488         SET(Type, static_cast<int32_t>(message->type | 0x0100));
1489     } else {
1490         ALOGD("Unknown constellation type with Svid = %d.", message->prn);
1491         SET(ConstellationType,
1492             static_cast<int32_t>(GNSS_CONSTELLATION_UNKNOWN));
1493         SET(Type, static_cast<int32_t>(GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN));
1494     }
1495     SET(MessageId, static_cast<int32_t>(message->message_id));
1496     SET(SubmessageId, static_cast<int32_t>(message->submessage_id));
1497     object.callSetter("setData", data, dataLength);
1498     SET(Status, static_cast<int32_t>(message->status));
1499     return object.get();
1500 }
1501 
translate_gnss_navigation_message(JNIEnv * env,GnssNavigationMessage * message)1502 static jobject translate_gnss_navigation_message(
1503         JNIEnv* env, GnssNavigationMessage* message) {
1504     size_t dataLength = message->data_length;
1505     uint8_t* data = message->data;
1506     if (dataLength == 0 || data == NULL) {
1507         ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
1508         return NULL;
1509     }
1510     JavaObject object(env, "android/location/GnssNavigationMessage");
1511     SET(Type, static_cast<int32_t>(message->type));
1512     SET(Svid, static_cast<int32_t>(message->svid));
1513     SET(MessageId, static_cast<int32_t>(message->message_id));
1514     SET(SubmessageId, static_cast<int32_t>(message->submessage_id));
1515     object.callSetter("setData", data, dataLength);
1516     SET(Status, static_cast<int32_t>(message->status));
1517     return object.get();
1518 }
1519 
navigation_message_callback(GpsNavigationMessage * message)1520 static void navigation_message_callback(GpsNavigationMessage* message) {
1521     if (message == NULL) {
1522         ALOGE("Invalid Navigation Message provided to callback");
1523         return;
1524     }
1525     if (message->size != sizeof(GpsNavigationMessage)) {
1526         ALOGE("Invalid GpsNavigationMessage size found: %zd", message->size);
1527         return;
1528     }
1529     JNIEnv* env = AndroidRuntime::getJNIEnv();
1530     jobject navigationMessage = translate_gps_navigation_message(env, message);
1531     env->CallVoidMethod(mCallbacksObj,
1532                         method_reportNavigationMessages,
1533                         navigationMessage);
1534     env->DeleteLocalRef(navigationMessage);
1535 }
1536 
gnss_navigation_message_callback(GnssNavigationMessage * message)1537 static void gnss_navigation_message_callback(GnssNavigationMessage* message) {
1538     if (message == NULL) {
1539         ALOGE("Invalid Navigation Message provided to callback");
1540         return;
1541     }
1542     if (message->size != sizeof(GnssNavigationMessage)) {
1543         ALOGE("Invalid GnssNavigationMessage size found: %zd", message->size);
1544         return;
1545     }
1546     JNIEnv* env = AndroidRuntime::getJNIEnv();
1547     jobject navigationMessage = translate_gnss_navigation_message(env, message);
1548     env->CallVoidMethod(mCallbacksObj,
1549                         method_reportNavigationMessages,
1550                         navigationMessage);
1551     env->DeleteLocalRef(navigationMessage);
1552 }
1553 
1554 GpsNavigationMessageCallbacks sGpsNavigationMessageCallbacks = {
1555     sizeof(GpsNavigationMessageCallbacks),
1556     navigation_message_callback,
1557     gnss_navigation_message_callback,
1558 };
1559 
android_location_GnssLocationProvider_is_navigation_message_supported(JNIEnv * env,jclass clazz)1560 static jboolean android_location_GnssLocationProvider_is_navigation_message_supported(
1561         JNIEnv* env,
1562         jclass clazz) {
1563     if(sGpsNavigationMessageInterface != NULL) {
1564         return JNI_TRUE;
1565     }
1566     return JNI_FALSE;
1567 }
1568 
android_location_GnssLocationProvider_start_navigation_message_collection(JNIEnv * env,jobject obj)1569 static jboolean android_location_GnssLocationProvider_start_navigation_message_collection(
1570         JNIEnv* env,
1571         jobject obj) {
1572     if (sGpsNavigationMessageInterface == NULL) {
1573         ALOGE("Navigation Message interface is not available.");
1574         return JNI_FALSE;
1575     }
1576 
1577     int result = sGpsNavigationMessageInterface->init(&sGpsNavigationMessageCallbacks);
1578     if (result != GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS) {
1579         ALOGE("An error has been found in %s: %d", __FUNCTION__, result);
1580         return JNI_FALSE;
1581     }
1582 
1583     return JNI_TRUE;
1584 }
1585 
android_location_GnssLocationProvider_stop_navigation_message_collection(JNIEnv * env,jobject obj)1586 static jboolean android_location_GnssLocationProvider_stop_navigation_message_collection(
1587         JNIEnv* env,
1588         jobject obj) {
1589     if (sGpsNavigationMessageInterface == NULL) {
1590         ALOGE("Navigation Message interface is not available.");
1591         return JNI_FALSE;
1592     }
1593 
1594     sGpsNavigationMessageInterface->close();
1595     return JNI_TRUE;
1596 }
1597 
android_location_GnssLocationProvider_configuration_update(JNIEnv * env,jobject obj,jstring config_content)1598 static void android_location_GnssLocationProvider_configuration_update(JNIEnv* env, jobject obj,
1599         jstring config_content)
1600 {
1601     if (!sGnssConfigurationInterface) {
1602         ALOGE("no GPS configuration interface in configuraiton_update");
1603         return;
1604     }
1605     const char *data = env->GetStringUTFChars(config_content, NULL);
1606     ALOGD("GPS configuration:\n %s", data);
1607     sGnssConfigurationInterface->configuration_update(
1608             data, env->GetStringUTFLength(config_content));
1609     env->ReleaseStringUTFChars(config_content, data);
1610 }
1611 
1612 static const JNINativeMethod sMethods[] = {
1613      /* name, signature, funcPtr */
1614     {"class_init_native", "()V", (void *)android_location_GnssLocationProvider_class_init_native},
1615     {"native_is_supported", "()Z", (void*)android_location_GnssLocationProvider_is_supported},
1616     {"native_is_agps_ril_supported", "()Z",
1617             (void*)android_location_GnssLocationProvider_is_agps_ril_supported},
1618     {"native_is_gnss_configuration_supported", "()Z",
1619             (void*)android_location_gpsLocationProvider_is_gnss_configuration_supported},
1620     {"native_init", "()Z", (void*)android_location_GnssLocationProvider_init},
1621     {"native_cleanup", "()V", (void*)android_location_GnssLocationProvider_cleanup},
1622     {"native_set_position_mode",
1623             "(IIIII)Z",
1624             (void*)android_location_GnssLocationProvider_set_position_mode},
1625     {"native_start", "()Z", (void*)android_location_GnssLocationProvider_start},
1626     {"native_stop", "()Z", (void*)android_location_GnssLocationProvider_stop},
1627     {"native_delete_aiding_data",
1628             "(I)V",
1629             (void*)android_location_GnssLocationProvider_delete_aiding_data},
1630     {"native_read_sv_status",
1631             "([I[F[F[F)I",
1632             (void*)android_location_GnssLocationProvider_read_sv_status},
1633     {"native_read_nmea", "([BI)I", (void*)android_location_GnssLocationProvider_read_nmea},
1634     {"native_inject_time", "(JJI)V", (void*)android_location_GnssLocationProvider_inject_time},
1635     {"native_inject_location",
1636             "(DDF)V",
1637             (void*)android_location_GnssLocationProvider_inject_location},
1638     {"native_supports_xtra", "()Z", (void*)android_location_GnssLocationProvider_supports_xtra},
1639     {"native_inject_xtra_data",
1640             "([BI)V",
1641             (void*)android_location_GnssLocationProvider_inject_xtra_data},
1642     {"native_agps_data_conn_open",
1643             "(Ljava/lang/String;I)V",
1644             (void*)android_location_GnssLocationProvider_agps_data_conn_open},
1645     {"native_agps_data_conn_closed",
1646             "()V",
1647             (void*)android_location_GnssLocationProvider_agps_data_conn_closed},
1648     {"native_agps_data_conn_failed",
1649             "()V",
1650             (void*)android_location_GnssLocationProvider_agps_data_conn_failed},
1651     {"native_agps_set_id",
1652             "(ILjava/lang/String;)V",
1653             (void*)android_location_GnssLocationProvider_agps_set_id},
1654     {"native_agps_set_ref_location_cellid",
1655             "(IIIII)V",
1656             (void*)android_location_GnssLocationProvider_agps_set_reference_location_cellid},
1657     {"native_set_agps_server",
1658             "(ILjava/lang/String;I)V",
1659             (void*)android_location_GnssLocationProvider_set_agps_server},
1660     {"native_send_ni_response",
1661             "(II)V",
1662             (void*)android_location_GnssLocationProvider_send_ni_response},
1663     {"native_agps_ni_message",
1664             "([BI)V",
1665             (void *)android_location_GnssLocationProvider_agps_send_ni_message},
1666     {"native_get_internal_state",
1667             "()Ljava/lang/String;",
1668             (void*)android_location_GnssLocationProvider_get_internal_state},
1669     {"native_update_network_state",
1670             "(ZIZZLjava/lang/String;Ljava/lang/String;)V",
1671             (void*)android_location_GnssLocationProvider_update_network_state },
1672     {"native_is_geofence_supported",
1673             "()Z",
1674             (void*) android_location_GnssLocationProvider_is_geofence_supported},
1675     {"native_add_geofence",
1676             "(IDDDIIII)Z",
1677             (void *)android_location_GnssLocationProvider_add_geofence},
1678     {"native_remove_geofence",
1679             "(I)Z",
1680             (void *)android_location_GnssLocationProvider_remove_geofence},
1681     {"native_pause_geofence", "(I)Z", (void *)android_location_GnssLocationProvider_pause_geofence},
1682     {"native_resume_geofence",
1683             "(II)Z",
1684             (void *)android_location_GnssLocationProvider_resume_geofence},
1685     {"native_is_measurement_supported",
1686             "()Z",
1687             (void*) android_location_GnssLocationProvider_is_measurement_supported},
1688     {"native_start_measurement_collection",
1689             "()Z",
1690             (void*) android_location_GnssLocationProvider_start_measurement_collection},
1691     {"native_stop_measurement_collection",
1692             "()Z",
1693             (void*) android_location_GnssLocationProvider_stop_measurement_collection},
1694     {"native_is_navigation_message_supported",
1695             "()Z",
1696             (void*) android_location_GnssLocationProvider_is_navigation_message_supported},
1697     {"native_start_navigation_message_collection",
1698             "()Z",
1699             (void*) android_location_GnssLocationProvider_start_navigation_message_collection},
1700     {"native_stop_navigation_message_collection",
1701             "()Z",
1702             (void*) android_location_GnssLocationProvider_stop_navigation_message_collection},
1703     {"native_configuration_update",
1704             "(Ljava/lang/String;)V",
1705             (void*)android_location_GnssLocationProvider_configuration_update},
1706 };
1707 
register_android_server_location_GnssLocationProvider(JNIEnv * env)1708 int register_android_server_location_GnssLocationProvider(JNIEnv* env)
1709 {
1710     return jniRegisterNativeMethods(
1711             env,
1712             "com/android/server/location/GnssLocationProvider",
1713             sMethods,
1714             NELEM(sMethods));
1715 }
1716 
1717 } /* namespace android */
1718