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 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 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 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 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 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 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 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 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 247 static void acquire_wakelock_callback() 248 { 249 acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME); 250 } 251 252 static void release_wakelock_callback() 253 { 254 release_wake_lock(WAKE_LOCK_NAME); 255 } 256 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 630 static jboolean android_location_GnssLocationProvider_is_supported( 631 JNIEnv* /* env */, jclass /* clazz */) 632 { 633 return (sGpsInterface != NULL) ? JNI_TRUE : JNI_FALSE; 634 } 635 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 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 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 674 static void android_location_GnssLocationProvider_cleanup(JNIEnv* /* env */, jobject /* obj */) 675 { 676 if (sGpsInterface) 677 sGpsInterface->cleanup(); 678 } 679 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 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 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 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 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 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 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 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 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 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 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 842 static jboolean android_location_GnssLocationProvider_supports_xtra( 843 JNIEnv* /* env */, jobject /* obj */) 844 { 845 return (sGpsXtraInterface != NULL) ? JNI_TRUE : JNI_FALSE; 846 } 847 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 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 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 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 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 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 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 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 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 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 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 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 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> 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 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 1070 JavaObject::~JavaObject() { 1071 env_->DeleteLocalRef(clazz_); 1072 } 1073 1074 template<class T> 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<> 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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