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