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 "GpsLocationProvider" 18 19 #define LOG_NDEBUG 0 20 21 #include "JNIHelp.h" 22 #include "jni.h" 23 #include "hardware/hardware.h" 24 #include "hardware/gps.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 <string.h> 33 #include <pthread.h> 34 #include <linux/in.h> 35 #include <linux/in6.h> 36 37 static jobject mCallbacksObj = NULL; 38 39 static jmethodID method_reportLocation; 40 static jmethodID method_reportStatus; 41 static jmethodID method_reportSvStatus; 42 static jmethodID method_reportAGpsStatus; 43 static jmethodID method_reportNmea; 44 static jmethodID method_setEngineCapabilities; 45 static jmethodID method_xtraDownloadRequest; 46 static jmethodID method_reportNiNotification; 47 static jmethodID method_requestRefLocation; 48 static jmethodID method_requestSetID; 49 static jmethodID method_requestUtcTime; 50 static jmethodID method_reportGeofenceTransition; 51 static jmethodID method_reportGeofenceStatus; 52 static jmethodID method_reportGeofenceAddStatus; 53 static jmethodID method_reportGeofenceRemoveStatus; 54 static jmethodID method_reportGeofencePauseStatus; 55 static jmethodID method_reportGeofenceResumeStatus; 56 static jmethodID method_reportMeasurementData; 57 static jmethodID method_reportNavigationMessages; 58 59 static const GpsInterface* sGpsInterface = NULL; 60 static const GpsXtraInterface* sGpsXtraInterface = NULL; 61 static const AGpsInterface* sAGpsInterface = NULL; 62 static const GpsNiInterface* sGpsNiInterface = NULL; 63 static const GpsDebugInterface* sGpsDebugInterface = NULL; 64 static const AGpsRilInterface* sAGpsRilInterface = NULL; 65 static const GpsGeofencingInterface* sGpsGeofencingInterface = NULL; 66 static const GpsMeasurementInterface* sGpsMeasurementInterface = NULL; 67 static const GpsNavigationMessageInterface* sGpsNavigationMessageInterface = NULL; 68 static const GnssConfigurationInterface* sGnssConfigurationInterface = NULL; 69 70 // temporary storage for GPS callbacks 71 static GpsSvStatus sGpsSvStatus; 72 static const char* sNmeaString; 73 static int sNmeaStringLength; 74 75 #define WAKE_LOCK_NAME "GPS" 76 77 namespace android { 78 79 static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) { 80 if (env->ExceptionCheck()) { 81 ALOGE("An exception was thrown by callback '%s'.", methodName); 82 LOGE_EX(env); 83 env->ExceptionClear(); 84 } 85 } 86 87 static void location_callback(GpsLocation* location) 88 { 89 JNIEnv* env = AndroidRuntime::getJNIEnv(); 90 env->CallVoidMethod(mCallbacksObj, method_reportLocation, location->flags, 91 (jdouble)location->latitude, (jdouble)location->longitude, 92 (jdouble)location->altitude, 93 (jfloat)location->speed, (jfloat)location->bearing, 94 (jfloat)location->accuracy, (jlong)location->timestamp); 95 checkAndClearExceptionFromCallback(env, __FUNCTION__); 96 } 97 98 static void status_callback(GpsStatus* status) 99 { 100 JNIEnv* env = AndroidRuntime::getJNIEnv(); 101 env->CallVoidMethod(mCallbacksObj, method_reportStatus, status->status); 102 checkAndClearExceptionFromCallback(env, __FUNCTION__); 103 } 104 105 static void sv_status_callback(GpsSvStatus* sv_status) 106 { 107 JNIEnv* env = AndroidRuntime::getJNIEnv(); 108 memcpy(&sGpsSvStatus, sv_status, sizeof(sGpsSvStatus)); 109 env->CallVoidMethod(mCallbacksObj, method_reportSvStatus); 110 checkAndClearExceptionFromCallback(env, __FUNCTION__); 111 } 112 113 static void nmea_callback(GpsUtcTime timestamp, const char* nmea, int length) 114 { 115 JNIEnv* env = AndroidRuntime::getJNIEnv(); 116 // The Java code will call back to read these values 117 // We do this to avoid creating unnecessary String objects 118 sNmeaString = nmea; 119 sNmeaStringLength = length; 120 env->CallVoidMethod(mCallbacksObj, method_reportNmea, timestamp); 121 checkAndClearExceptionFromCallback(env, __FUNCTION__); 122 } 123 124 static void set_capabilities_callback(uint32_t capabilities) 125 { 126 ALOGD("set_capabilities_callback: %du\n", capabilities); 127 JNIEnv* env = AndroidRuntime::getJNIEnv(); 128 env->CallVoidMethod(mCallbacksObj, method_setEngineCapabilities, capabilities); 129 checkAndClearExceptionFromCallback(env, __FUNCTION__); 130 } 131 132 static void acquire_wakelock_callback() 133 { 134 acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME); 135 } 136 137 static void release_wakelock_callback() 138 { 139 release_wake_lock(WAKE_LOCK_NAME); 140 } 141 142 static void request_utc_time_callback() 143 { 144 JNIEnv* env = AndroidRuntime::getJNIEnv(); 145 env->CallVoidMethod(mCallbacksObj, method_requestUtcTime); 146 checkAndClearExceptionFromCallback(env, __FUNCTION__); 147 } 148 149 static pthread_t create_thread_callback(const char* name, void (*start)(void *), void* arg) 150 { 151 return (pthread_t)AndroidRuntime::createJavaThread(name, start, arg); 152 } 153 154 GpsCallbacks sGpsCallbacks = { 155 sizeof(GpsCallbacks), 156 location_callback, 157 status_callback, 158 sv_status_callback, 159 nmea_callback, 160 set_capabilities_callback, 161 acquire_wakelock_callback, 162 release_wakelock_callback, 163 create_thread_callback, 164 request_utc_time_callback, 165 }; 166 167 static void xtra_download_request_callback() 168 { 169 JNIEnv* env = AndroidRuntime::getJNIEnv(); 170 env->CallVoidMethod(mCallbacksObj, method_xtraDownloadRequest); 171 checkAndClearExceptionFromCallback(env, __FUNCTION__); 172 } 173 174 GpsXtraCallbacks sGpsXtraCallbacks = { 175 xtra_download_request_callback, 176 create_thread_callback, 177 }; 178 179 static jbyteArray convert_to_ipv4(uint32_t ip, bool net_order) 180 { 181 if (INADDR_NONE == ip) { 182 return NULL; 183 } 184 185 JNIEnv* env = AndroidRuntime::getJNIEnv(); 186 jbyteArray byteArray = env->NewByteArray(4); 187 if (byteArray == NULL) { 188 ALOGE("Unable to allocate byte array for IPv4 address"); 189 return NULL; 190 } 191 192 jbyte ipv4[4]; 193 if (net_order) { 194 ALOGV("Converting IPv4 address(net_order) %x", ip); 195 memcpy(ipv4, &ip, sizeof(ipv4)); 196 } else { 197 ALOGV("Converting IPv4 address(host_order) %x", ip); 198 //endianess transparent conversion from int to char[] 199 ipv4[0] = (jbyte) (ip & 0xFF); 200 ipv4[1] = (jbyte)((ip>>8) & 0xFF); 201 ipv4[2] = (jbyte)((ip>>16) & 0xFF); 202 ipv4[3] = (jbyte) (ip>>24); 203 } 204 205 env->SetByteArrayRegion(byteArray, 0, 4, (const jbyte*) ipv4); 206 return byteArray; 207 } 208 209 static void agps_status_callback(AGpsStatus* agps_status) 210 { 211 JNIEnv* env = AndroidRuntime::getJNIEnv(); 212 jbyteArray byteArray = NULL; 213 bool isSupported = false; 214 215 size_t status_size = agps_status->size; 216 if (status_size == sizeof(AGpsStatus_v3)) { 217 ALOGV("AGpsStatus is V3: %zd", status_size); 218 switch (agps_status->addr.ss_family) 219 { 220 case AF_INET: 221 { 222 struct sockaddr_in *in = (struct sockaddr_in*)&(agps_status->addr); 223 uint32_t ipAddr = *(uint32_t*)&(in->sin_addr); 224 byteArray = convert_to_ipv4(ipAddr, true /* net_order */); 225 if (ipAddr == INADDR_NONE || byteArray != NULL) { 226 isSupported = true; 227 } 228 IF_ALOGD() { 229 // log the IP for reference in case there is a bogus value pushed by HAL 230 char str[INET_ADDRSTRLEN]; 231 inet_ntop(AF_INET, &(in->sin_addr), str, INET_ADDRSTRLEN); 232 ALOGD("AGPS IP is v4: %s", str); 233 } 234 } 235 break; 236 case AF_INET6: 237 { 238 struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&(agps_status->addr); 239 byteArray = env->NewByteArray(16); 240 if (byteArray != NULL) { 241 env->SetByteArrayRegion(byteArray, 0, 16, (const jbyte *)&(in6->sin6_addr)); 242 isSupported = true; 243 } else { 244 ALOGE("Unable to allocate byte array for IPv6 address."); 245 } 246 IF_ALOGD() { 247 // log the IP for reference in case there is a bogus value pushed by HAL 248 char str[INET6_ADDRSTRLEN]; 249 inet_ntop(AF_INET6, &(in6->sin6_addr), str, INET6_ADDRSTRLEN); 250 ALOGD("AGPS IP is v6: %s", str); 251 } 252 } 253 break; 254 default: 255 ALOGE("Invalid ss_family found: %d", agps_status->addr.ss_family); 256 break; 257 } 258 } else if (status_size >= sizeof(AGpsStatus_v2)) { 259 ALOGV("AGpsStatus is V2+: %zd", status_size); 260 // for back-compatibility reasons we check in v2 that the data structure size is greater or 261 // equal to the declared size in gps.h 262 uint32_t ipaddr = agps_status->ipaddr; 263 ALOGV("AGPS IP is v4: %x", ipaddr); 264 byteArray = convert_to_ipv4(ipaddr, false /* net_order */); 265 if (ipaddr == INADDR_NONE || byteArray != NULL) { 266 isSupported = true; 267 } 268 } else if (status_size >= sizeof(AGpsStatus_v1)) { 269 ALOGV("AGpsStatus is V1+: %zd", status_size); 270 // because we have to check for >= with regards to v2, we also need to relax the check here 271 // and only make sure that the size is at least what we expect 272 isSupported = true; 273 } else { 274 ALOGE("Invalid size of AGpsStatus found: %zd.", status_size); 275 } 276 277 if (isSupported) { 278 jsize byteArrayLength = byteArray != NULL ? env->GetArrayLength(byteArray) : 0; 279 ALOGV("Passing AGPS IP addr: size %d", byteArrayLength); 280 env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus, agps_status->type, 281 agps_status->status, byteArray); 282 283 checkAndClearExceptionFromCallback(env, __FUNCTION__); 284 } else { 285 ALOGD("Skipping calling method_reportAGpsStatus."); 286 } 287 288 if (byteArray) { 289 env->DeleteLocalRef(byteArray); 290 } 291 } 292 293 AGpsCallbacks sAGpsCallbacks = { 294 agps_status_callback, 295 create_thread_callback, 296 }; 297 298 static void gps_ni_notify_callback(GpsNiNotification *notification) 299 { 300 ALOGD("gps_ni_notify_callback\n"); 301 JNIEnv* env = AndroidRuntime::getJNIEnv(); 302 jstring requestor_id = env->NewStringUTF(notification->requestor_id); 303 jstring text = env->NewStringUTF(notification->text); 304 jstring extras = env->NewStringUTF(notification->extras); 305 306 if (requestor_id && text && extras) { 307 env->CallVoidMethod(mCallbacksObj, method_reportNiNotification, 308 notification->notification_id, notification->ni_type, 309 notification->notify_flags, notification->timeout, 310 notification->default_response, requestor_id, text, 311 notification->requestor_id_encoding, 312 notification->text_encoding, extras); 313 } else { 314 ALOGE("out of memory in gps_ni_notify_callback\n"); 315 } 316 317 if (requestor_id) 318 env->DeleteLocalRef(requestor_id); 319 if (text) 320 env->DeleteLocalRef(text); 321 if (extras) 322 env->DeleteLocalRef(extras); 323 checkAndClearExceptionFromCallback(env, __FUNCTION__); 324 } 325 326 GpsNiCallbacks sGpsNiCallbacks = { 327 gps_ni_notify_callback, 328 create_thread_callback, 329 }; 330 331 static void agps_request_set_id(uint32_t flags) 332 { 333 JNIEnv* env = AndroidRuntime::getJNIEnv(); 334 env->CallVoidMethod(mCallbacksObj, method_requestSetID, flags); 335 checkAndClearExceptionFromCallback(env, __FUNCTION__); 336 } 337 338 static void agps_request_ref_location(uint32_t flags) 339 { 340 JNIEnv* env = AndroidRuntime::getJNIEnv(); 341 env->CallVoidMethod(mCallbacksObj, method_requestRefLocation, flags); 342 checkAndClearExceptionFromCallback(env, __FUNCTION__); 343 } 344 345 AGpsRilCallbacks sAGpsRilCallbacks = { 346 agps_request_set_id, 347 agps_request_ref_location, 348 create_thread_callback, 349 }; 350 351 static void gps_geofence_transition_callback(int32_t geofence_id, GpsLocation* location, 352 int32_t transition, GpsUtcTime timestamp) 353 { 354 JNIEnv* env = AndroidRuntime::getJNIEnv(); 355 356 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceTransition, geofence_id, 357 location->flags, (jdouble)location->latitude, (jdouble)location->longitude, 358 (jdouble)location->altitude, 359 (jfloat)location->speed, (jfloat)location->bearing, 360 (jfloat)location->accuracy, (jlong)location->timestamp, 361 transition, timestamp); 362 checkAndClearExceptionFromCallback(env, __FUNCTION__); 363 }; 364 365 static void gps_geofence_status_callback(int32_t status, GpsLocation* location) 366 { 367 JNIEnv* env = AndroidRuntime::getJNIEnv(); 368 jint flags = 0; 369 jdouble latitude = 0; 370 jdouble longitude = 0; 371 jdouble altitude = 0; 372 jfloat speed = 0; 373 jfloat bearing = 0; 374 jfloat accuracy = 0; 375 jlong timestamp = 0; 376 if (location != NULL) { 377 flags = location->flags; 378 latitude = location->latitude; 379 longitude = location->longitude; 380 altitude = location->altitude; 381 speed = location->speed; 382 bearing = location->bearing; 383 accuracy = location->accuracy; 384 timestamp = location->timestamp; 385 } 386 387 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceStatus, status, 388 flags, latitude, longitude, altitude, speed, bearing, accuracy, timestamp); 389 checkAndClearExceptionFromCallback(env, __FUNCTION__); 390 }; 391 392 static void gps_geofence_add_callback(int32_t geofence_id, int32_t status) 393 { 394 JNIEnv* env = AndroidRuntime::getJNIEnv(); 395 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) { 396 ALOGE("Error in geofence_add_callback: %d\n", status); 397 } 398 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceAddStatus, geofence_id, status); 399 checkAndClearExceptionFromCallback(env, __FUNCTION__); 400 }; 401 402 static void gps_geofence_remove_callback(int32_t geofence_id, int32_t status) 403 { 404 JNIEnv* env = AndroidRuntime::getJNIEnv(); 405 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) { 406 ALOGE("Error in geofence_remove_callback: %d\n", status); 407 } 408 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceRemoveStatus, geofence_id, status); 409 checkAndClearExceptionFromCallback(env, __FUNCTION__); 410 }; 411 412 static void gps_geofence_resume_callback(int32_t geofence_id, int32_t status) 413 { 414 JNIEnv* env = AndroidRuntime::getJNIEnv(); 415 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) { 416 ALOGE("Error in geofence_resume_callback: %d\n", status); 417 } 418 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceResumeStatus, geofence_id, status); 419 checkAndClearExceptionFromCallback(env, __FUNCTION__); 420 }; 421 422 static void gps_geofence_pause_callback(int32_t geofence_id, int32_t status) 423 { 424 JNIEnv* env = AndroidRuntime::getJNIEnv(); 425 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) { 426 ALOGE("Error in geofence_pause_callback: %d\n", status); 427 } 428 env->CallVoidMethod(mCallbacksObj, method_reportGeofencePauseStatus, geofence_id, status); 429 checkAndClearExceptionFromCallback(env, __FUNCTION__); 430 }; 431 432 GpsGeofenceCallbacks sGpsGeofenceCallbacks = { 433 gps_geofence_transition_callback, 434 gps_geofence_status_callback, 435 gps_geofence_add_callback, 436 gps_geofence_remove_callback, 437 gps_geofence_pause_callback, 438 gps_geofence_resume_callback, 439 create_thread_callback, 440 }; 441 442 static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz) { 443 int err; 444 hw_module_t* module; 445 446 method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V"); 447 method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V"); 448 method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V"); 449 method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V"); 450 method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V"); 451 method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V"); 452 method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V"); 453 method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification", 454 "(IIIIILjava/lang/String;Ljava/lang/String;IILjava/lang/String;)V"); 455 method_requestRefLocation = env->GetMethodID(clazz,"requestRefLocation","(I)V"); 456 method_requestSetID = env->GetMethodID(clazz,"requestSetID","(I)V"); 457 method_requestUtcTime = env->GetMethodID(clazz,"requestUtcTime","()V"); 458 method_reportGeofenceTransition = env->GetMethodID(clazz,"reportGeofenceTransition", 459 "(IIDDDFFFJIJ)V"); 460 method_reportGeofenceStatus = env->GetMethodID(clazz,"reportGeofenceStatus", 461 "(IIDDDFFFJ)V"); 462 method_reportGeofenceAddStatus = env->GetMethodID(clazz,"reportGeofenceAddStatus", 463 "(II)V"); 464 method_reportGeofenceRemoveStatus = env->GetMethodID(clazz,"reportGeofenceRemoveStatus", 465 "(II)V"); 466 method_reportGeofenceResumeStatus = env->GetMethodID(clazz,"reportGeofenceResumeStatus", 467 "(II)V"); 468 method_reportGeofencePauseStatus = env->GetMethodID(clazz,"reportGeofencePauseStatus", 469 "(II)V"); 470 method_reportMeasurementData = env->GetMethodID( 471 clazz, 472 "reportMeasurementData", 473 "(Landroid/location/GpsMeasurementsEvent;)V"); 474 method_reportNavigationMessages = env->GetMethodID( 475 clazz, 476 "reportNavigationMessage", 477 "(Landroid/location/GpsNavigationMessageEvent;)V"); 478 479 err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module); 480 if (err == 0) { 481 hw_device_t* device; 482 err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device); 483 if (err == 0) { 484 gps_device_t* gps_device = (gps_device_t *)device; 485 sGpsInterface = gps_device->get_gps_interface(gps_device); 486 } 487 } 488 if (sGpsInterface) { 489 sGpsXtraInterface = 490 (const GpsXtraInterface*)sGpsInterface->get_extension(GPS_XTRA_INTERFACE); 491 sAGpsInterface = 492 (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE); 493 sGpsNiInterface = 494 (const GpsNiInterface*)sGpsInterface->get_extension(GPS_NI_INTERFACE); 495 sGpsDebugInterface = 496 (const GpsDebugInterface*)sGpsInterface->get_extension(GPS_DEBUG_INTERFACE); 497 sAGpsRilInterface = 498 (const AGpsRilInterface*)sGpsInterface->get_extension(AGPS_RIL_INTERFACE); 499 sGpsGeofencingInterface = 500 (const GpsGeofencingInterface*)sGpsInterface->get_extension(GPS_GEOFENCING_INTERFACE); 501 sGpsMeasurementInterface = 502 (const GpsMeasurementInterface*)sGpsInterface->get_extension(GPS_MEASUREMENT_INTERFACE); 503 sGpsNavigationMessageInterface = 504 (const GpsNavigationMessageInterface*)sGpsInterface->get_extension( 505 GPS_NAVIGATION_MESSAGE_INTERFACE); 506 sGnssConfigurationInterface = 507 (const GnssConfigurationInterface*)sGpsInterface->get_extension( 508 GNSS_CONFIGURATION_INTERFACE); 509 } 510 } 511 512 static jboolean android_location_GpsLocationProvider_is_supported( 513 JNIEnv* /* env */, jclass /* clazz */) 514 { 515 return (sGpsInterface != NULL) ? JNI_TRUE : JNI_FALSE; 516 } 517 518 static jboolean android_location_GpsLocationProvider_is_agps_ril_supported( 519 JNIEnv* /* env */, jclass /* clazz */) 520 { 521 return (sAGpsRilInterface != NULL) ? JNI_TRUE : JNI_FALSE; 522 } 523 524 static jboolean android_location_gpsLocationProvider_is_gnss_configuration_supported( 525 JNIEnv* /* env */, jclass /* jclazz */) 526 { 527 return (sGnssConfigurationInterface != NULL) ? JNI_TRUE : JNI_FALSE; 528 } 529 530 static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject obj) 531 { 532 // this must be set before calling into the HAL library 533 if (!mCallbacksObj) 534 mCallbacksObj = env->NewGlobalRef(obj); 535 536 // fail if the main interface fails to initialize 537 if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0) 538 return JNI_FALSE; 539 540 // if XTRA initialization fails we will disable it by sGpsXtraInterface to NULL, 541 // but continue to allow the rest of the GPS interface to work. 542 if (sGpsXtraInterface && sGpsXtraInterface->init(&sGpsXtraCallbacks) != 0) 543 sGpsXtraInterface = NULL; 544 if (sAGpsInterface) 545 sAGpsInterface->init(&sAGpsCallbacks); 546 if (sGpsNiInterface) 547 sGpsNiInterface->init(&sGpsNiCallbacks); 548 if (sAGpsRilInterface) 549 sAGpsRilInterface->init(&sAGpsRilCallbacks); 550 if (sGpsGeofencingInterface) 551 sGpsGeofencingInterface->init(&sGpsGeofenceCallbacks); 552 553 return JNI_TRUE; 554 } 555 556 static void android_location_GpsLocationProvider_cleanup(JNIEnv* /* env */, jobject /* obj */) 557 { 558 if (sGpsInterface) 559 sGpsInterface->cleanup(); 560 } 561 562 static jboolean android_location_GpsLocationProvider_set_position_mode(JNIEnv* /* env */, 563 jobject /* obj */, jint mode, jint recurrence, jint min_interval, jint preferred_accuracy, 564 jint preferred_time) 565 { 566 if (sGpsInterface) { 567 if (sGpsInterface->set_position_mode(mode, recurrence, min_interval, preferred_accuracy, 568 preferred_time) == 0) { 569 return JNI_TRUE; 570 } else { 571 return JNI_FALSE; 572 } 573 } 574 else 575 return JNI_FALSE; 576 } 577 578 static jboolean android_location_GpsLocationProvider_start(JNIEnv* /* env */, jobject /* obj */) 579 { 580 if (sGpsInterface) { 581 if (sGpsInterface->start() == 0) { 582 return JNI_TRUE; 583 } else { 584 return JNI_FALSE; 585 } 586 } 587 else 588 return JNI_FALSE; 589 } 590 591 static jboolean android_location_GpsLocationProvider_stop(JNIEnv* /* env */, jobject /* obj */) 592 { 593 if (sGpsInterface) { 594 if (sGpsInterface->stop() == 0) { 595 return JNI_TRUE; 596 } else { 597 return JNI_FALSE; 598 } 599 } 600 else 601 return JNI_FALSE; 602 } 603 604 static void android_location_GpsLocationProvider_delete_aiding_data(JNIEnv* /* env */, 605 jobject /* obj */, 606 jint flags) 607 { 608 if (sGpsInterface) 609 sGpsInterface->delete_aiding_data(flags); 610 } 611 612 static jint android_location_GpsLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */, 613 jintArray prnArray, jfloatArray snrArray, jfloatArray elevArray, jfloatArray azumArray, 614 jintArray maskArray) 615 { 616 // this should only be called from within a call to reportSvStatus 617 618 jint* prns = env->GetIntArrayElements(prnArray, 0); 619 jfloat* snrs = env->GetFloatArrayElements(snrArray, 0); 620 jfloat* elev = env->GetFloatArrayElements(elevArray, 0); 621 jfloat* azim = env->GetFloatArrayElements(azumArray, 0); 622 jint* mask = env->GetIntArrayElements(maskArray, 0); 623 624 int num_svs = sGpsSvStatus.num_svs; 625 for (int i = 0; i < num_svs; i++) { 626 prns[i] = sGpsSvStatus.sv_list[i].prn; 627 snrs[i] = sGpsSvStatus.sv_list[i].snr; 628 elev[i] = sGpsSvStatus.sv_list[i].elevation; 629 azim[i] = sGpsSvStatus.sv_list[i].azimuth; 630 } 631 mask[0] = sGpsSvStatus.ephemeris_mask; 632 mask[1] = sGpsSvStatus.almanac_mask; 633 mask[2] = sGpsSvStatus.used_in_fix_mask; 634 635 env->ReleaseIntArrayElements(prnArray, prns, 0); 636 env->ReleaseFloatArrayElements(snrArray, snrs, 0); 637 env->ReleaseFloatArrayElements(elevArray, elev, 0); 638 env->ReleaseFloatArrayElements(azumArray, azim, 0); 639 env->ReleaseIntArrayElements(maskArray, mask, 0); 640 return (jint) num_svs; 641 } 642 643 static void android_location_GpsLocationProvider_agps_set_reference_location_cellid( 644 JNIEnv* /* env */, jobject /* obj */, jint type, jint mcc, jint mnc, jint lac, jint cid) 645 { 646 AGpsRefLocation location; 647 648 if (!sAGpsRilInterface) { 649 ALOGE("no AGPS RIL interface in agps_set_reference_location_cellid"); 650 return; 651 } 652 653 switch(type) { 654 case AGPS_REF_LOCATION_TYPE_GSM_CELLID: 655 case AGPS_REF_LOCATION_TYPE_UMTS_CELLID: 656 location.type = type; 657 location.u.cellID.mcc = mcc; 658 location.u.cellID.mnc = mnc; 659 location.u.cellID.lac = lac; 660 location.u.cellID.cid = cid; 661 break; 662 default: 663 ALOGE("Neither a GSM nor a UMTS cellid (%s:%d).",__FUNCTION__,__LINE__); 664 return; 665 break; 666 } 667 sAGpsRilInterface->set_ref_location(&location, sizeof(location)); 668 } 669 670 static void android_location_GpsLocationProvider_agps_send_ni_message(JNIEnv* env, 671 jobject /* obj */, jbyteArray ni_msg, jint size) 672 { 673 size_t sz; 674 675 if (!sAGpsRilInterface) { 676 ALOGE("no AGPS RIL interface in send_ni_message"); 677 return; 678 } 679 if (size < 0) 680 return; 681 sz = (size_t)size; 682 jbyte* b = env->GetByteArrayElements(ni_msg, 0); 683 sAGpsRilInterface->ni_message((uint8_t *)b,sz); 684 env->ReleaseByteArrayElements(ni_msg,b,0); 685 } 686 687 static void android_location_GpsLocationProvider_agps_set_id(JNIEnv *env, jobject /* obj */, 688 jint type, jstring setid_string) 689 { 690 if (!sAGpsRilInterface) { 691 ALOGE("no AGPS RIL interface in agps_set_id"); 692 return; 693 } 694 695 const char *setid = env->GetStringUTFChars(setid_string, NULL); 696 sAGpsRilInterface->set_set_id(type, setid); 697 env->ReleaseStringUTFChars(setid_string, setid); 698 } 699 700 static jint android_location_GpsLocationProvider_read_nmea(JNIEnv* env, jobject /* obj */, 701 jbyteArray nmeaArray, jint buffer_size) 702 { 703 // this should only be called from within a call to reportNmea 704 jbyte* nmea = (jbyte *)env->GetPrimitiveArrayCritical(nmeaArray, 0); 705 int length = sNmeaStringLength; 706 if (length > buffer_size) 707 length = buffer_size; 708 memcpy(nmea, sNmeaString, length); 709 env->ReleasePrimitiveArrayCritical(nmeaArray, nmea, JNI_ABORT); 710 return (jint) length; 711 } 712 713 static void android_location_GpsLocationProvider_inject_time(JNIEnv* /* env */, jobject /* obj */, 714 jlong time, jlong timeReference, jint uncertainty) 715 { 716 if (sGpsInterface) 717 sGpsInterface->inject_time(time, timeReference, uncertainty); 718 } 719 720 static void android_location_GpsLocationProvider_inject_location(JNIEnv* /* env */, 721 jobject /* obj */, jdouble latitude, jdouble longitude, jfloat accuracy) 722 { 723 if (sGpsInterface) 724 sGpsInterface->inject_location(latitude, longitude, accuracy); 725 } 726 727 static jboolean android_location_GpsLocationProvider_supports_xtra( 728 JNIEnv* /* env */, jobject /* obj */) 729 { 730 return (sGpsXtraInterface != NULL) ? JNI_TRUE : JNI_FALSE; 731 } 732 733 static void android_location_GpsLocationProvider_inject_xtra_data(JNIEnv* env, jobject /* obj */, 734 jbyteArray data, jint length) 735 { 736 if (!sGpsXtraInterface) { 737 ALOGE("no XTRA interface in inject_xtra_data"); 738 return; 739 } 740 741 jbyte* bytes = (jbyte *)env->GetPrimitiveArrayCritical(data, 0); 742 sGpsXtraInterface->inject_xtra_data((char *)bytes, length); 743 env->ReleasePrimitiveArrayCritical(data, bytes, JNI_ABORT); 744 } 745 746 static void android_location_GpsLocationProvider_agps_data_conn_open( 747 JNIEnv* env, jobject /* obj */, jstring apn, jint apnIpType) 748 { 749 if (!sAGpsInterface) { 750 ALOGE("no AGPS interface in agps_data_conn_open"); 751 return; 752 } 753 if (apn == NULL) { 754 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 755 return; 756 } 757 758 const char *apnStr = env->GetStringUTFChars(apn, NULL); 759 760 size_t interface_size = sAGpsInterface->size; 761 if (interface_size == sizeof(AGpsInterface_v2)) { 762 sAGpsInterface->data_conn_open_with_apn_ip_type(apnStr, apnIpType); 763 } else if (interface_size == sizeof(AGpsInterface_v1)) { 764 sAGpsInterface->data_conn_open(apnStr); 765 } else { 766 ALOGE("Invalid size of AGpsInterface found: %zd.", interface_size); 767 } 768 769 env->ReleaseStringUTFChars(apn, apnStr); 770 } 771 772 static void android_location_GpsLocationProvider_agps_data_conn_closed(JNIEnv* /* env */, 773 jobject /* obj */) 774 { 775 if (!sAGpsInterface) { 776 ALOGE("no AGPS interface in agps_data_conn_closed"); 777 return; 778 } 779 sAGpsInterface->data_conn_closed(); 780 } 781 782 static void android_location_GpsLocationProvider_agps_data_conn_failed(JNIEnv* /* env */, 783 jobject /* obj */) 784 { 785 if (!sAGpsInterface) { 786 ALOGE("no AGPS interface in agps_data_conn_failed"); 787 return; 788 } 789 sAGpsInterface->data_conn_failed(); 790 } 791 792 static void android_location_GpsLocationProvider_set_agps_server(JNIEnv* env, jobject /* obj */, 793 jint type, jstring hostname, jint port) 794 { 795 if (!sAGpsInterface) { 796 ALOGE("no AGPS interface in set_agps_server"); 797 return; 798 } 799 const char *c_hostname = env->GetStringUTFChars(hostname, NULL); 800 sAGpsInterface->set_server(type, c_hostname, port); 801 env->ReleaseStringUTFChars(hostname, c_hostname); 802 } 803 804 static void android_location_GpsLocationProvider_send_ni_response(JNIEnv* /* env */, 805 jobject /* obj */, jint notifId, jint response) 806 { 807 if (!sGpsNiInterface) { 808 ALOGE("no NI interface in send_ni_response"); 809 return; 810 } 811 812 sGpsNiInterface->respond(notifId, response); 813 } 814 815 static jstring android_location_GpsLocationProvider_get_internal_state(JNIEnv* env, 816 jobject /* obj */) { 817 jstring result = NULL; 818 if (sGpsDebugInterface) { 819 const size_t maxLength = 2047; 820 char buffer[maxLength+1]; 821 size_t length = sGpsDebugInterface->get_internal_state(buffer, maxLength); 822 if (length > maxLength) length = maxLength; 823 buffer[length] = 0; 824 result = env->NewStringUTF(buffer); 825 } 826 return result; 827 } 828 829 static void android_location_GpsLocationProvider_update_network_state(JNIEnv* env, jobject /* obj */, 830 jboolean connected, jint type, jboolean roaming, jboolean available, jstring extraInfo, jstring apn) 831 { 832 833 if (sAGpsRilInterface && sAGpsRilInterface->update_network_state) { 834 if (extraInfo) { 835 const char *extraInfoStr = env->GetStringUTFChars(extraInfo, NULL); 836 sAGpsRilInterface->update_network_state(connected, type, roaming, extraInfoStr); 837 env->ReleaseStringUTFChars(extraInfo, extraInfoStr); 838 } else { 839 sAGpsRilInterface->update_network_state(connected, type, roaming, NULL); 840 } 841 842 // update_network_availability callback was not included in original AGpsRilInterface 843 if (sAGpsRilInterface->size >= sizeof(AGpsRilInterface) 844 && sAGpsRilInterface->update_network_availability) { 845 const char *c_apn = env->GetStringUTFChars(apn, NULL); 846 sAGpsRilInterface->update_network_availability(available, c_apn); 847 env->ReleaseStringUTFChars(apn, c_apn); 848 } 849 } 850 } 851 852 static jboolean android_location_GpsLocationProvider_is_geofence_supported( 853 JNIEnv* /* env */, jobject /* obj */) 854 { 855 return (sGpsGeofencingInterface != NULL) ? JNI_TRUE : JNI_FALSE; 856 } 857 858 static jboolean android_location_GpsLocationProvider_add_geofence(JNIEnv* /* env */, 859 jobject /* obj */, jint geofence_id, jdouble latitude, jdouble longitude, jdouble radius, 860 jint last_transition, jint monitor_transition, jint notification_responsiveness, 861 jint unknown_timer) { 862 if (sGpsGeofencingInterface != NULL) { 863 sGpsGeofencingInterface->add_geofence_area(geofence_id, latitude, longitude, 864 radius, last_transition, monitor_transition, notification_responsiveness, 865 unknown_timer); 866 return JNI_TRUE; 867 } else { 868 ALOGE("Geofence interface not available"); 869 } 870 return JNI_FALSE; 871 } 872 873 static jboolean android_location_GpsLocationProvider_remove_geofence(JNIEnv* /* env */, 874 jobject /* obj */, jint geofence_id) { 875 if (sGpsGeofencingInterface != NULL) { 876 sGpsGeofencingInterface->remove_geofence_area(geofence_id); 877 return JNI_TRUE; 878 } else { 879 ALOGE("Geofence interface not available"); 880 } 881 return JNI_FALSE; 882 } 883 884 static jboolean android_location_GpsLocationProvider_pause_geofence(JNIEnv* /* env */, 885 jobject /* obj */, jint geofence_id) { 886 if (sGpsGeofencingInterface != NULL) { 887 sGpsGeofencingInterface->pause_geofence(geofence_id); 888 return JNI_TRUE; 889 } else { 890 ALOGE("Geofence interface not available"); 891 } 892 return JNI_FALSE; 893 } 894 895 static jboolean android_location_GpsLocationProvider_resume_geofence(JNIEnv* /* env */, 896 jobject /* obj */, jint geofence_id, jint monitor_transition) { 897 if (sGpsGeofencingInterface != NULL) { 898 sGpsGeofencingInterface->resume_geofence(geofence_id, monitor_transition); 899 return JNI_TRUE; 900 } else { 901 ALOGE("Geofence interface not available"); 902 } 903 return JNI_FALSE; 904 } 905 906 static jobject translate_gps_clock(JNIEnv* env, GpsClock* clock) { 907 const char* doubleSignature = "(D)V"; 908 const char* longSignature = "(J)V"; 909 910 jclass gpsClockClass = env->FindClass("android/location/GpsClock"); 911 jmethodID gpsClockCtor = env->GetMethodID(gpsClockClass, "<init>", "()V"); 912 913 jobject gpsClockObject = env->NewObject(gpsClockClass, gpsClockCtor); 914 GpsClockFlags flags = clock->flags; 915 916 if (flags & GPS_CLOCK_HAS_LEAP_SECOND) { 917 jmethodID setterMethod = env->GetMethodID(gpsClockClass, "setLeapSecond", "(S)V"); 918 env->CallVoidMethod(gpsClockObject, setterMethod, clock->leap_second); 919 } 920 921 jmethodID typeSetterMethod = env->GetMethodID(gpsClockClass, "setType", "(B)V"); 922 env->CallVoidMethod(gpsClockObject, typeSetterMethod, clock->type); 923 924 jmethodID setterMethod = env->GetMethodID(gpsClockClass, "setTimeInNs", longSignature); 925 env->CallVoidMethod(gpsClockObject, setterMethod, clock->time_ns); 926 927 if (flags & GPS_CLOCK_HAS_TIME_UNCERTAINTY) { 928 jmethodID setterMethod = 929 env->GetMethodID(gpsClockClass, "setTimeUncertaintyInNs", doubleSignature); 930 env->CallVoidMethod(gpsClockObject, setterMethod, clock->time_uncertainty_ns); 931 } 932 933 if (flags & GPS_CLOCK_HAS_FULL_BIAS) { 934 jmethodID setterMethod = env->GetMethodID(gpsClockClass, "setFullBiasInNs", longSignature); 935 env->CallVoidMethod(gpsClockObject, setterMethod, clock->full_bias_ns); 936 } 937 938 if (flags & GPS_CLOCK_HAS_BIAS) { 939 jmethodID setterMethod = env->GetMethodID(gpsClockClass, "setBiasInNs", doubleSignature); 940 env->CallVoidMethod(gpsClockObject, setterMethod, clock->bias_ns); 941 } 942 943 if (flags & GPS_CLOCK_HAS_BIAS_UNCERTAINTY) { 944 jmethodID setterMethod = 945 env->GetMethodID(gpsClockClass, "setBiasUncertaintyInNs", doubleSignature); 946 env->CallVoidMethod(gpsClockObject, setterMethod, clock->bias_uncertainty_ns); 947 } 948 949 if (flags & GPS_CLOCK_HAS_DRIFT) { 950 jmethodID setterMethod = 951 env->GetMethodID(gpsClockClass, "setDriftInNsPerSec", doubleSignature); 952 env->CallVoidMethod(gpsClockObject, setterMethod, clock->drift_nsps); 953 } 954 955 if (flags & GPS_CLOCK_HAS_DRIFT_UNCERTAINTY) { 956 jmethodID setterMethod = 957 env->GetMethodID(gpsClockClass, "setDriftUncertaintyInNsPerSec", doubleSignature); 958 env->CallVoidMethod(gpsClockObject, setterMethod, clock->drift_uncertainty_nsps); 959 } 960 961 env->DeleteLocalRef(gpsClockClass); 962 return gpsClockObject; 963 } 964 965 static jobject translate_gps_measurement(JNIEnv* env, GpsMeasurement* measurement) { 966 const char* byteSignature = "(B)V"; 967 const char* shortSignature = "(S)V"; 968 const char* intSignature = "(I)V"; 969 const char* longSignature = "(J)V"; 970 const char* floatSignature = "(F)V"; 971 const char* doubleSignature = "(D)V"; 972 973 jclass gpsMeasurementClass = env->FindClass("android/location/GpsMeasurement"); 974 jmethodID gpsMeasurementCtor = env->GetMethodID(gpsMeasurementClass, "<init>", "()V"); 975 976 jobject gpsMeasurementObject = env->NewObject(gpsMeasurementClass, gpsMeasurementCtor); 977 GpsMeasurementFlags flags = measurement->flags; 978 979 jmethodID prnSetterMethod = env->GetMethodID(gpsMeasurementClass, "setPrn", byteSignature); 980 env->CallVoidMethod(gpsMeasurementObject, prnSetterMethod, measurement->prn); 981 982 jmethodID timeOffsetSetterMethod = 983 env->GetMethodID(gpsMeasurementClass, "setTimeOffsetInNs", doubleSignature); 984 env->CallVoidMethod( 985 gpsMeasurementObject, 986 timeOffsetSetterMethod, 987 measurement->time_offset_ns); 988 989 jmethodID stateSetterMethod = env->GetMethodID(gpsMeasurementClass, "setState", shortSignature); 990 env->CallVoidMethod(gpsMeasurementObject, stateSetterMethod, measurement->state); 991 992 jmethodID receivedGpsTowSetterMethod = 993 env->GetMethodID(gpsMeasurementClass, "setReceivedGpsTowInNs", longSignature); 994 env->CallVoidMethod( 995 gpsMeasurementObject, 996 receivedGpsTowSetterMethod, 997 measurement->received_gps_tow_ns); 998 999 jmethodID receivedGpsTowUncertaintySetterMethod = env->GetMethodID( 1000 gpsMeasurementClass, 1001 "setReceivedGpsTowUncertaintyInNs", 1002 longSignature); 1003 env->CallVoidMethod( 1004 gpsMeasurementObject, 1005 receivedGpsTowUncertaintySetterMethod, 1006 measurement->received_gps_tow_uncertainty_ns); 1007 1008 jmethodID cn0SetterMethod = 1009 env->GetMethodID(gpsMeasurementClass, "setCn0InDbHz", doubleSignature); 1010 env->CallVoidMethod(gpsMeasurementObject, cn0SetterMethod, measurement->c_n0_dbhz); 1011 1012 jmethodID pseudorangeRateSetterMethod = env->GetMethodID( 1013 gpsMeasurementClass, 1014 "setPseudorangeRateInMetersPerSec", 1015 doubleSignature); 1016 env->CallVoidMethod( 1017 gpsMeasurementObject, 1018 pseudorangeRateSetterMethod, 1019 measurement->pseudorange_rate_mps); 1020 1021 jmethodID pseudorangeRateUncertaintySetterMethod = env->GetMethodID( 1022 gpsMeasurementClass, 1023 "setPseudorangeRateUncertaintyInMetersPerSec", 1024 doubleSignature); 1025 env->CallVoidMethod( 1026 gpsMeasurementObject, 1027 pseudorangeRateUncertaintySetterMethod, 1028 measurement->pseudorange_rate_uncertainty_mps); 1029 1030 jmethodID accumulatedDeltaRangeStateSetterMethod = 1031 env->GetMethodID(gpsMeasurementClass, "setAccumulatedDeltaRangeState", shortSignature); 1032 env->CallVoidMethod( 1033 gpsMeasurementObject, 1034 accumulatedDeltaRangeStateSetterMethod, 1035 measurement->accumulated_delta_range_state); 1036 1037 jmethodID accumulatedDeltaRangeSetterMethod = env->GetMethodID( 1038 gpsMeasurementClass, 1039 "setAccumulatedDeltaRangeInMeters", 1040 doubleSignature); 1041 env->CallVoidMethod( 1042 gpsMeasurementObject, 1043 accumulatedDeltaRangeSetterMethod, 1044 measurement->accumulated_delta_range_m); 1045 1046 jmethodID accumulatedDeltaRangeUncertaintySetterMethod = env->GetMethodID( 1047 gpsMeasurementClass, 1048 "setAccumulatedDeltaRangeUncertaintyInMeters", 1049 doubleSignature); 1050 env->CallVoidMethod( 1051 gpsMeasurementObject, 1052 accumulatedDeltaRangeUncertaintySetterMethod, 1053 measurement->accumulated_delta_range_uncertainty_m); 1054 1055 if (flags & GPS_MEASUREMENT_HAS_PSEUDORANGE) { 1056 jmethodID setterMethod = 1057 env->GetMethodID(gpsMeasurementClass, "setPseudorangeInMeters", doubleSignature); 1058 env->CallVoidMethod(gpsMeasurementObject, setterMethod, measurement->pseudorange_m); 1059 } 1060 1061 if (flags & GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY) { 1062 jmethodID setterMethod = env->GetMethodID( 1063 gpsMeasurementClass, 1064 "setPseudorangeUncertaintyInMeters", 1065 doubleSignature); 1066 env->CallVoidMethod( 1067 gpsMeasurementObject, 1068 setterMethod, 1069 measurement->pseudorange_uncertainty_m); 1070 } 1071 1072 if (flags & GPS_MEASUREMENT_HAS_CODE_PHASE) { 1073 jmethodID setterMethod = 1074 env->GetMethodID(gpsMeasurementClass, "setCodePhaseInChips", doubleSignature); 1075 env->CallVoidMethod(gpsMeasurementObject, setterMethod, measurement->code_phase_chips); 1076 } 1077 1078 if (flags & GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY) { 1079 jmethodID setterMethod = env->GetMethodID( 1080 gpsMeasurementClass, 1081 "setCodePhaseUncertaintyInChips", 1082 doubleSignature); 1083 env->CallVoidMethod( 1084 gpsMeasurementObject, 1085 setterMethod, 1086 measurement->code_phase_uncertainty_chips); 1087 } 1088 1089 if (flags & GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY) { 1090 jmethodID setterMethod = 1091 env->GetMethodID(gpsMeasurementClass, "setCarrierFrequencyInHz", floatSignature); 1092 env->CallVoidMethod( 1093 gpsMeasurementObject, 1094 setterMethod, 1095 measurement->carrier_frequency_hz); 1096 } 1097 1098 if (flags & GPS_MEASUREMENT_HAS_CARRIER_CYCLES) { 1099 jmethodID setterMethod = 1100 env->GetMethodID(gpsMeasurementClass, "setCarrierCycles", longSignature); 1101 env->CallVoidMethod(gpsMeasurementObject, setterMethod, measurement->carrier_cycles); 1102 } 1103 1104 if (flags & GPS_MEASUREMENT_HAS_CARRIER_PHASE) { 1105 jmethodID setterMethod = 1106 env->GetMethodID(gpsMeasurementClass, "setCarrierPhase", doubleSignature); 1107 env->CallVoidMethod(gpsMeasurementObject, setterMethod, measurement->carrier_phase); 1108 } 1109 1110 if (flags & GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY) { 1111 jmethodID setterMethod = env->GetMethodID( 1112 gpsMeasurementClass, 1113 "setCarrierPhaseUncertainty", 1114 doubleSignature); 1115 env->CallVoidMethod( 1116 gpsMeasurementObject, 1117 setterMethod, 1118 measurement->carrier_phase_uncertainty); 1119 } 1120 1121 jmethodID lossOfLockSetterMethod = 1122 env->GetMethodID(gpsMeasurementClass, "setLossOfLock", byteSignature); 1123 env->CallVoidMethod(gpsMeasurementObject, lossOfLockSetterMethod, measurement->loss_of_lock); 1124 1125 if (flags & GPS_MEASUREMENT_HAS_BIT_NUMBER) { 1126 jmethodID setterMethod = 1127 env->GetMethodID(gpsMeasurementClass, "setBitNumber", intSignature); 1128 env->CallVoidMethod(gpsMeasurementObject, setterMethod, measurement->bit_number); 1129 } 1130 1131 if (flags & GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT) { 1132 jmethodID setterMethod = 1133 env->GetMethodID(gpsMeasurementClass, "setTimeFromLastBitInMs", shortSignature); 1134 env->CallVoidMethod( 1135 gpsMeasurementObject, 1136 setterMethod, 1137 measurement->time_from_last_bit_ms); 1138 } 1139 1140 if (flags & GPS_MEASUREMENT_HAS_DOPPLER_SHIFT) { 1141 jmethodID setterMethod = 1142 env->GetMethodID(gpsMeasurementClass, "setDopplerShiftInHz", doubleSignature); 1143 env->CallVoidMethod(gpsMeasurementObject, setterMethod, measurement->doppler_shift_hz); 1144 } 1145 1146 if (flags & GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY) { 1147 jmethodID setterMethod = env->GetMethodID( 1148 gpsMeasurementClass, 1149 "setDopplerShiftUncertaintyInHz", 1150 doubleSignature); 1151 env->CallVoidMethod( 1152 gpsMeasurementObject, 1153 setterMethod, 1154 measurement->doppler_shift_uncertainty_hz); 1155 } 1156 1157 jmethodID multipathIndicatorSetterMethod = 1158 env->GetMethodID(gpsMeasurementClass, "setMultipathIndicator", byteSignature); 1159 env->CallVoidMethod( 1160 gpsMeasurementObject, 1161 multipathIndicatorSetterMethod, 1162 measurement->multipath_indicator); 1163 1164 if (flags & GPS_MEASUREMENT_HAS_SNR) { 1165 jmethodID setterMethod = 1166 env->GetMethodID(gpsMeasurementClass, "setSnrInDb", doubleSignature); 1167 env->CallVoidMethod(gpsMeasurementObject, setterMethod, measurement->snr_db); 1168 } 1169 1170 if (flags & GPS_MEASUREMENT_HAS_ELEVATION) { 1171 jmethodID setterMethod = 1172 env->GetMethodID(gpsMeasurementClass, "setElevationInDeg", doubleSignature); 1173 env->CallVoidMethod(gpsMeasurementObject, setterMethod, measurement->elevation_deg); 1174 } 1175 1176 if (flags & GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY) { 1177 jmethodID setterMethod = 1178 env->GetMethodID(gpsMeasurementClass, "setElevationUncertaintyInDeg", doubleSignature); 1179 env->CallVoidMethod( 1180 gpsMeasurementObject, 1181 setterMethod, 1182 measurement->elevation_uncertainty_deg); 1183 } 1184 1185 if (flags & GPS_MEASUREMENT_HAS_AZIMUTH) { 1186 jmethodID setterMethod = 1187 env->GetMethodID(gpsMeasurementClass, "setAzimuthInDeg", doubleSignature); 1188 env->CallVoidMethod(gpsMeasurementObject, setterMethod, measurement->azimuth_deg); 1189 } 1190 1191 if (flags & GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY) { 1192 jmethodID setterMethod = env->GetMethodID( 1193 gpsMeasurementClass, 1194 "setAzimuthUncertaintyInDeg", 1195 doubleSignature); 1196 env->CallVoidMethod( 1197 gpsMeasurementObject, 1198 setterMethod, 1199 measurement->azimuth_uncertainty_deg); 1200 } 1201 1202 jmethodID usedInFixSetterMethod = env->GetMethodID(gpsMeasurementClass, "setUsedInFix", "(Z)V"); 1203 env->CallVoidMethod( 1204 gpsMeasurementObject, 1205 usedInFixSetterMethod, 1206 (flags & GPS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix); 1207 1208 env->DeleteLocalRef(gpsMeasurementClass); 1209 return gpsMeasurementObject; 1210 } 1211 1212 static jobjectArray translate_gps_measurements(JNIEnv* env, GpsData* data) { 1213 size_t measurementCount = data->measurement_count; 1214 if (measurementCount == 0) { 1215 return NULL; 1216 } 1217 1218 jclass gpsMeasurementClass = env->FindClass("android/location/GpsMeasurement"); 1219 jobjectArray gpsMeasurementArray = env->NewObjectArray( 1220 measurementCount, 1221 gpsMeasurementClass, 1222 NULL /* initialElement */); 1223 1224 GpsMeasurement* gpsMeasurements = data->measurements; 1225 for (uint16_t i = 0; i < measurementCount; ++i) { 1226 jobject gpsMeasurement = translate_gps_measurement(env, &gpsMeasurements[i]); 1227 env->SetObjectArrayElement(gpsMeasurementArray, i, gpsMeasurement); 1228 env->DeleteLocalRef(gpsMeasurement); 1229 } 1230 1231 env->DeleteLocalRef(gpsMeasurementClass); 1232 return gpsMeasurementArray; 1233 } 1234 1235 static void measurement_callback(GpsData* data) { 1236 JNIEnv* env = AndroidRuntime::getJNIEnv(); 1237 if (data == NULL) { 1238 ALOGE("Invalid data provided to gps_measurement_callback"); 1239 return; 1240 } 1241 1242 if (data->size == sizeof(GpsData)) { 1243 jobject gpsClock = translate_gps_clock(env, &data->clock); 1244 jobjectArray measurementArray = translate_gps_measurements(env, data); 1245 1246 jclass gpsMeasurementsEventClass = env->FindClass("android/location/GpsMeasurementsEvent"); 1247 jmethodID gpsMeasurementsEventCtor = env->GetMethodID( 1248 gpsMeasurementsEventClass, 1249 "<init>", 1250 "(Landroid/location/GpsClock;[Landroid/location/GpsMeasurement;)V"); 1251 1252 jobject gpsMeasurementsEvent = env->NewObject( 1253 gpsMeasurementsEventClass, 1254 gpsMeasurementsEventCtor, 1255 gpsClock, 1256 measurementArray); 1257 1258 env->CallVoidMethod(mCallbacksObj, method_reportMeasurementData, gpsMeasurementsEvent); 1259 checkAndClearExceptionFromCallback(env, __FUNCTION__); 1260 1261 env->DeleteLocalRef(gpsClock); 1262 env->DeleteLocalRef(measurementArray); 1263 env->DeleteLocalRef(gpsMeasurementsEventClass); 1264 env->DeleteLocalRef(gpsMeasurementsEvent); 1265 } else { 1266 ALOGE("Invalid GpsData size found in gps_measurement_callback, size=%zd", data->size); 1267 } 1268 } 1269 1270 GpsMeasurementCallbacks sGpsMeasurementCallbacks = { 1271 sizeof(GpsMeasurementCallbacks), 1272 measurement_callback, 1273 }; 1274 1275 static jboolean android_location_GpsLocationProvider_is_measurement_supported( 1276 JNIEnv* env, 1277 jclass clazz) { 1278 if (sGpsMeasurementInterface != NULL) { 1279 return JNI_TRUE; 1280 } 1281 return JNI_FALSE; 1282 } 1283 1284 static jboolean android_location_GpsLocationProvider_start_measurement_collection( 1285 JNIEnv* env, 1286 jobject obj) { 1287 if (sGpsMeasurementInterface == NULL) { 1288 ALOGE("Measurement interface is not available."); 1289 return JNI_FALSE; 1290 } 1291 1292 int result = sGpsMeasurementInterface->init(&sGpsMeasurementCallbacks); 1293 if (result != GPS_GEOFENCE_OPERATION_SUCCESS) { 1294 ALOGE("An error has been found on GpsMeasurementInterface::init, status=%d", result); 1295 return JNI_FALSE; 1296 } 1297 1298 return JNI_TRUE; 1299 } 1300 1301 static jboolean android_location_GpsLocationProvider_stop_measurement_collection( 1302 JNIEnv* env, 1303 jobject obj) { 1304 if (sGpsMeasurementInterface == NULL) { 1305 ALOGE("Measurement interface not available"); 1306 return JNI_FALSE; 1307 } 1308 1309 sGpsMeasurementInterface->close(); 1310 return JNI_TRUE; 1311 } 1312 1313 static jobject translate_gps_navigation_message(JNIEnv* env, GpsNavigationMessage* message) { 1314 size_t dataLength = message->data_length; 1315 uint8_t* data = message->data; 1316 if (dataLength == 0 || data == NULL) { 1317 ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength); 1318 return NULL; 1319 } 1320 1321 jclass navigationMessageClass = env->FindClass("android/location/GpsNavigationMessage"); 1322 jmethodID navigationMessageCtor = env->GetMethodID(navigationMessageClass, "<init>", "()V"); 1323 jobject navigationMessageObject = env->NewObject(navigationMessageClass, navigationMessageCtor); 1324 1325 jmethodID setTypeMethod = env->GetMethodID(navigationMessageClass, "setType", "(B)V"); 1326 env->CallVoidMethod(navigationMessageObject, setTypeMethod, message->type); 1327 1328 jmethodID setPrnMethod = env->GetMethodID(navigationMessageClass, "setPrn", "(B)V"); 1329 env->CallVoidMethod(navigationMessageObject, setPrnMethod, message->prn); 1330 1331 jmethodID setMessageIdMethod = env->GetMethodID(navigationMessageClass, "setMessageId", "(S)V"); 1332 env->CallVoidMethod(navigationMessageObject, setMessageIdMethod, message->message_id); 1333 1334 jmethodID setSubmessageIdMethod = 1335 env->GetMethodID(navigationMessageClass, "setSubmessageId", "(S)V"); 1336 env->CallVoidMethod(navigationMessageObject, setSubmessageIdMethod, message->submessage_id); 1337 1338 jbyteArray dataArray = env->NewByteArray(dataLength); 1339 env->SetByteArrayRegion(dataArray, 0, dataLength, (jbyte*) data); 1340 jmethodID setDataMethod = env->GetMethodID(navigationMessageClass, "setData", "([B)V"); 1341 env->CallVoidMethod(navigationMessageObject, setDataMethod, dataArray); 1342 1343 env->DeleteLocalRef(navigationMessageClass); 1344 env->DeleteLocalRef(dataArray); 1345 return navigationMessageObject; 1346 } 1347 1348 static void navigation_message_callback(GpsNavigationMessage* message) { 1349 JNIEnv* env = AndroidRuntime::getJNIEnv(); 1350 if (message == NULL) { 1351 ALOGE("Invalid Navigation Message provided to callback"); 1352 return; 1353 } 1354 1355 if (message->size == sizeof(GpsNavigationMessage)) { 1356 jobject navigationMessage = translate_gps_navigation_message(env, message); 1357 1358 jclass navigationMessageEventClass = 1359 env->FindClass("android/location/GpsNavigationMessageEvent"); 1360 jmethodID navigationMessageEventCtor = env->GetMethodID( 1361 navigationMessageEventClass, 1362 "<init>", 1363 "(Landroid/location/GpsNavigationMessage;)V"); 1364 jobject navigationMessageEvent = env->NewObject( 1365 navigationMessageEventClass, 1366 navigationMessageEventCtor, 1367 navigationMessage); 1368 1369 env->CallVoidMethod(mCallbacksObj, method_reportNavigationMessages, navigationMessageEvent); 1370 checkAndClearExceptionFromCallback(env, __FUNCTION__); 1371 1372 env->DeleteLocalRef(navigationMessage); 1373 env->DeleteLocalRef(navigationMessageEventClass); 1374 env->DeleteLocalRef(navigationMessageEvent); 1375 } else { 1376 ALOGE("Invalid GpsNavigationMessage size found: %zd", message->size); 1377 } 1378 } 1379 1380 GpsNavigationMessageCallbacks sGpsNavigationMessageCallbacks = { 1381 sizeof(GpsNavigationMessageCallbacks), 1382 navigation_message_callback, 1383 }; 1384 1385 static jboolean android_location_GpsLocationProvider_is_navigation_message_supported( 1386 JNIEnv* env, 1387 jclass clazz) { 1388 if(sGpsNavigationMessageInterface != NULL) { 1389 return JNI_TRUE; 1390 } 1391 return JNI_FALSE; 1392 } 1393 1394 static jboolean android_location_GpsLocationProvider_start_navigation_message_collection( 1395 JNIEnv* env, 1396 jobject obj) { 1397 if (sGpsNavigationMessageInterface == NULL) { 1398 ALOGE("Navigation Message interface is not available."); 1399 return JNI_FALSE; 1400 } 1401 1402 int result = sGpsNavigationMessageInterface->init(&sGpsNavigationMessageCallbacks); 1403 if (result != GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS) { 1404 ALOGE("An error has been found in %s: %d", __FUNCTION__, result); 1405 return JNI_FALSE; 1406 } 1407 1408 return JNI_TRUE; 1409 } 1410 1411 static jboolean android_location_GpsLocationProvider_stop_navigation_message_collection( 1412 JNIEnv* env, 1413 jobject obj) { 1414 if (sGpsNavigationMessageInterface == NULL) { 1415 ALOGE("Navigation Message interface is not available."); 1416 return JNI_FALSE; 1417 } 1418 1419 sGpsNavigationMessageInterface->close(); 1420 return JNI_TRUE; 1421 } 1422 1423 static void android_location_GpsLocationProvider_configuration_update(JNIEnv* env, jobject obj, 1424 jstring config_content) 1425 { 1426 if (!sGnssConfigurationInterface) { 1427 ALOGE("no GPS configuration interface in configuraiton_update"); 1428 return; 1429 } 1430 const char *data = env->GetStringUTFChars(config_content, NULL); 1431 ALOGD("GPS configuration:\n %s", data); 1432 sGnssConfigurationInterface->configuration_update( 1433 data, env->GetStringUTFLength(config_content)); 1434 env->ReleaseStringUTFChars(config_content, data); 1435 } 1436 1437 static JNINativeMethod sMethods[] = { 1438 /* name, signature, funcPtr */ 1439 {"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native}, 1440 {"native_is_supported", "()Z", (void*)android_location_GpsLocationProvider_is_supported}, 1441 {"native_is_agps_ril_supported", "()Z", 1442 (void*)android_location_GpsLocationProvider_is_agps_ril_supported}, 1443 {"native_is_gnss_configuration_supported", "()Z", 1444 (void*)android_location_gpsLocationProvider_is_gnss_configuration_supported}, 1445 {"native_init", "()Z", (void*)android_location_GpsLocationProvider_init}, 1446 {"native_cleanup", "()V", (void*)android_location_GpsLocationProvider_cleanup}, 1447 {"native_set_position_mode", 1448 "(IIIII)Z", 1449 (void*)android_location_GpsLocationProvider_set_position_mode}, 1450 {"native_start", "()Z", (void*)android_location_GpsLocationProvider_start}, 1451 {"native_stop", "()Z", (void*)android_location_GpsLocationProvider_stop}, 1452 {"native_delete_aiding_data", 1453 "(I)V", 1454 (void*)android_location_GpsLocationProvider_delete_aiding_data}, 1455 {"native_read_sv_status", 1456 "([I[F[F[F[I)I", 1457 (void*)android_location_GpsLocationProvider_read_sv_status}, 1458 {"native_read_nmea", "([BI)I", (void*)android_location_GpsLocationProvider_read_nmea}, 1459 {"native_inject_time", "(JJI)V", (void*)android_location_GpsLocationProvider_inject_time}, 1460 {"native_inject_location", 1461 "(DDF)V", 1462 (void*)android_location_GpsLocationProvider_inject_location}, 1463 {"native_supports_xtra", "()Z", (void*)android_location_GpsLocationProvider_supports_xtra}, 1464 {"native_inject_xtra_data", 1465 "([BI)V", 1466 (void*)android_location_GpsLocationProvider_inject_xtra_data}, 1467 {"native_agps_data_conn_open", 1468 "(Ljava/lang/String;I)V", 1469 (void*)android_location_GpsLocationProvider_agps_data_conn_open}, 1470 {"native_agps_data_conn_closed", 1471 "()V", 1472 (void*)android_location_GpsLocationProvider_agps_data_conn_closed}, 1473 {"native_agps_data_conn_failed", 1474 "()V", 1475 (void*)android_location_GpsLocationProvider_agps_data_conn_failed}, 1476 {"native_agps_set_id", 1477 "(ILjava/lang/String;)V", 1478 (void*)android_location_GpsLocationProvider_agps_set_id}, 1479 {"native_agps_set_ref_location_cellid", 1480 "(IIIII)V", 1481 (void*)android_location_GpsLocationProvider_agps_set_reference_location_cellid}, 1482 {"native_set_agps_server", 1483 "(ILjava/lang/String;I)V", 1484 (void*)android_location_GpsLocationProvider_set_agps_server}, 1485 {"native_send_ni_response", 1486 "(II)V", 1487 (void*)android_location_GpsLocationProvider_send_ni_response}, 1488 {"native_agps_ni_message", 1489 "([BI)V", 1490 (void *)android_location_GpsLocationProvider_agps_send_ni_message}, 1491 {"native_get_internal_state", 1492 "()Ljava/lang/String;", 1493 (void*)android_location_GpsLocationProvider_get_internal_state}, 1494 {"native_update_network_state", 1495 "(ZIZZLjava/lang/String;Ljava/lang/String;)V", 1496 (void*)android_location_GpsLocationProvider_update_network_state }, 1497 {"native_is_geofence_supported", 1498 "()Z", 1499 (void*) android_location_GpsLocationProvider_is_geofence_supported}, 1500 {"native_add_geofence", 1501 "(IDDDIIII)Z", 1502 (void *)android_location_GpsLocationProvider_add_geofence}, 1503 {"native_remove_geofence", 1504 "(I)Z", 1505 (void *)android_location_GpsLocationProvider_remove_geofence}, 1506 {"native_pause_geofence", "(I)Z", (void *)android_location_GpsLocationProvider_pause_geofence}, 1507 {"native_resume_geofence", 1508 "(II)Z", 1509 (void *)android_location_GpsLocationProvider_resume_geofence}, 1510 {"native_is_measurement_supported", 1511 "()Z", 1512 (void*) android_location_GpsLocationProvider_is_measurement_supported}, 1513 {"native_start_measurement_collection", 1514 "()Z", 1515 (void*) android_location_GpsLocationProvider_start_measurement_collection}, 1516 {"native_stop_measurement_collection", 1517 "()Z", 1518 (void*) android_location_GpsLocationProvider_stop_measurement_collection}, 1519 {"native_is_navigation_message_supported", 1520 "()Z", 1521 (void*) android_location_GpsLocationProvider_is_navigation_message_supported}, 1522 {"native_start_navigation_message_collection", 1523 "()Z", 1524 (void*) android_location_GpsLocationProvider_start_navigation_message_collection}, 1525 {"native_stop_navigation_message_collection", 1526 "()Z", 1527 (void*) android_location_GpsLocationProvider_stop_navigation_message_collection}, 1528 {"native_configuration_update", 1529 "(Ljava/lang/String;)V", 1530 (void*)android_location_GpsLocationProvider_configuration_update}, 1531 }; 1532 1533 int register_android_server_location_GpsLocationProvider(JNIEnv* env) 1534 { 1535 return jniRegisterNativeMethods( 1536 env, 1537 "com/android/server/location/GpsLocationProvider", 1538 sMethods, 1539 NELEM(sMethods)); 1540 } 1541 1542 } /* namespace android */ 1543