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 <string.h> 32 #include <pthread.h> 33 34 static jobject mCallbacksObj = NULL; 35 36 static jmethodID method_reportLocation; 37 static jmethodID method_reportStatus; 38 static jmethodID method_reportSvStatus; 39 static jmethodID method_reportAGpsStatus; 40 static jmethodID method_reportNmea; 41 static jmethodID method_setEngineCapabilities; 42 static jmethodID method_xtraDownloadRequest; 43 static jmethodID method_reportNiNotification; 44 static jmethodID method_requestRefLocation; 45 static jmethodID method_requestSetID; 46 static jmethodID method_requestUtcTime; 47 static jmethodID method_reportGeofenceTransition; 48 static jmethodID method_reportGeofenceStatus; 49 static jmethodID method_reportGeofenceAddStatus; 50 static jmethodID method_reportGeofenceRemoveStatus; 51 static jmethodID method_reportGeofencePauseStatus; 52 static jmethodID method_reportGeofenceResumeStatus; 53 54 static const GpsInterface* sGpsInterface = NULL; 55 static const GpsXtraInterface* sGpsXtraInterface = NULL; 56 static const AGpsInterface* sAGpsInterface = NULL; 57 static const GpsNiInterface* sGpsNiInterface = NULL; 58 static const GpsDebugInterface* sGpsDebugInterface = NULL; 59 static const AGpsRilInterface* sAGpsRilInterface = NULL; 60 static const GpsGeofencingInterface* sGpsGeofencingInterface = NULL; 61 62 // temporary storage for GPS callbacks 63 static GpsSvStatus sGpsSvStatus; 64 static const char* sNmeaString; 65 static int sNmeaStringLength; 66 67 #define WAKE_LOCK_NAME "GPS" 68 69 namespace android { 70 71 static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) { 72 if (env->ExceptionCheck()) { 73 ALOGE("An exception was thrown by callback '%s'.", methodName); 74 LOGE_EX(env); 75 env->ExceptionClear(); 76 } 77 } 78 79 static void location_callback(GpsLocation* location) 80 { 81 JNIEnv* env = AndroidRuntime::getJNIEnv(); 82 env->CallVoidMethod(mCallbacksObj, method_reportLocation, location->flags, 83 (jdouble)location->latitude, (jdouble)location->longitude, 84 (jdouble)location->altitude, 85 (jfloat)location->speed, (jfloat)location->bearing, 86 (jfloat)location->accuracy, (jlong)location->timestamp); 87 checkAndClearExceptionFromCallback(env, __FUNCTION__); 88 } 89 90 static void status_callback(GpsStatus* status) 91 { 92 JNIEnv* env = AndroidRuntime::getJNIEnv(); 93 env->CallVoidMethod(mCallbacksObj, method_reportStatus, status->status); 94 checkAndClearExceptionFromCallback(env, __FUNCTION__); 95 } 96 97 static void sv_status_callback(GpsSvStatus* sv_status) 98 { 99 JNIEnv* env = AndroidRuntime::getJNIEnv(); 100 memcpy(&sGpsSvStatus, sv_status, sizeof(sGpsSvStatus)); 101 env->CallVoidMethod(mCallbacksObj, method_reportSvStatus); 102 checkAndClearExceptionFromCallback(env, __FUNCTION__); 103 } 104 105 static void nmea_callback(GpsUtcTime timestamp, const char* nmea, int length) 106 { 107 JNIEnv* env = AndroidRuntime::getJNIEnv(); 108 // The Java code will call back to read these values 109 // We do this to avoid creating unnecessary String objects 110 sNmeaString = nmea; 111 sNmeaStringLength = length; 112 env->CallVoidMethod(mCallbacksObj, method_reportNmea, timestamp); 113 checkAndClearExceptionFromCallback(env, __FUNCTION__); 114 } 115 116 static void set_capabilities_callback(uint32_t capabilities) 117 { 118 ALOGD("set_capabilities_callback: %du\n", capabilities); 119 JNIEnv* env = AndroidRuntime::getJNIEnv(); 120 env->CallVoidMethod(mCallbacksObj, method_setEngineCapabilities, capabilities); 121 checkAndClearExceptionFromCallback(env, __FUNCTION__); 122 } 123 124 static void acquire_wakelock_callback() 125 { 126 acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME); 127 } 128 129 static void release_wakelock_callback() 130 { 131 release_wake_lock(WAKE_LOCK_NAME); 132 } 133 134 static void request_utc_time_callback() 135 { 136 JNIEnv* env = AndroidRuntime::getJNIEnv(); 137 env->CallVoidMethod(mCallbacksObj, method_requestUtcTime); 138 checkAndClearExceptionFromCallback(env, __FUNCTION__); 139 } 140 141 static pthread_t create_thread_callback(const char* name, void (*start)(void *), void* arg) 142 { 143 return (pthread_t)AndroidRuntime::createJavaThread(name, start, arg); 144 } 145 146 GpsCallbacks sGpsCallbacks = { 147 sizeof(GpsCallbacks), 148 location_callback, 149 status_callback, 150 sv_status_callback, 151 nmea_callback, 152 set_capabilities_callback, 153 acquire_wakelock_callback, 154 release_wakelock_callback, 155 create_thread_callback, 156 request_utc_time_callback, 157 }; 158 159 static void xtra_download_request_callback() 160 { 161 JNIEnv* env = AndroidRuntime::getJNIEnv(); 162 env->CallVoidMethod(mCallbacksObj, method_xtraDownloadRequest); 163 checkAndClearExceptionFromCallback(env, __FUNCTION__); 164 } 165 166 GpsXtraCallbacks sGpsXtraCallbacks = { 167 xtra_download_request_callback, 168 create_thread_callback, 169 }; 170 171 static void agps_status_callback(AGpsStatus* agps_status) 172 { 173 JNIEnv* env = AndroidRuntime::getJNIEnv(); 174 175 uint32_t ipaddr; 176 // ipaddr field was not included in original AGpsStatus 177 if (agps_status->size >= sizeof(AGpsStatus)) 178 ipaddr = agps_status->ipaddr; 179 else 180 ipaddr = 0xFFFFFFFF; 181 env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus, 182 agps_status->type, agps_status->status, ipaddr); 183 checkAndClearExceptionFromCallback(env, __FUNCTION__); 184 } 185 186 AGpsCallbacks sAGpsCallbacks = { 187 agps_status_callback, 188 create_thread_callback, 189 }; 190 191 static void gps_ni_notify_callback(GpsNiNotification *notification) 192 { 193 ALOGD("gps_ni_notify_callback\n"); 194 JNIEnv* env = AndroidRuntime::getJNIEnv(); 195 jstring requestor_id = env->NewStringUTF(notification->requestor_id); 196 jstring text = env->NewStringUTF(notification->text); 197 jstring extras = env->NewStringUTF(notification->extras); 198 199 if (requestor_id && text && extras) { 200 env->CallVoidMethod(mCallbacksObj, method_reportNiNotification, 201 notification->notification_id, notification->ni_type, 202 notification->notify_flags, notification->timeout, 203 notification->default_response, requestor_id, text, 204 notification->requestor_id_encoding, 205 notification->text_encoding, extras); 206 } else { 207 ALOGE("out of memory in gps_ni_notify_callback\n"); 208 } 209 210 if (requestor_id) 211 env->DeleteLocalRef(requestor_id); 212 if (text) 213 env->DeleteLocalRef(text); 214 if (extras) 215 env->DeleteLocalRef(extras); 216 checkAndClearExceptionFromCallback(env, __FUNCTION__); 217 } 218 219 GpsNiCallbacks sGpsNiCallbacks = { 220 gps_ni_notify_callback, 221 create_thread_callback, 222 }; 223 224 static void agps_request_set_id(uint32_t flags) 225 { 226 JNIEnv* env = AndroidRuntime::getJNIEnv(); 227 env->CallVoidMethod(mCallbacksObj, method_requestSetID, flags); 228 checkAndClearExceptionFromCallback(env, __FUNCTION__); 229 } 230 231 static void agps_request_ref_location(uint32_t flags) 232 { 233 JNIEnv* env = AndroidRuntime::getJNIEnv(); 234 env->CallVoidMethod(mCallbacksObj, method_requestRefLocation, flags); 235 checkAndClearExceptionFromCallback(env, __FUNCTION__); 236 } 237 238 AGpsRilCallbacks sAGpsRilCallbacks = { 239 agps_request_set_id, 240 agps_request_ref_location, 241 create_thread_callback, 242 }; 243 244 static void gps_geofence_transition_callback(int32_t geofence_id, GpsLocation* location, 245 int32_t transition, GpsUtcTime timestamp) 246 { 247 JNIEnv* env = AndroidRuntime::getJNIEnv(); 248 249 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceTransition, geofence_id, 250 location->flags, (jdouble)location->latitude, (jdouble)location->longitude, 251 (jdouble)location->altitude, 252 (jfloat)location->speed, (jfloat)location->bearing, 253 (jfloat)location->accuracy, (jlong)location->timestamp, 254 transition, timestamp); 255 checkAndClearExceptionFromCallback(env, __FUNCTION__); 256 }; 257 258 static void gps_geofence_status_callback(int32_t status, GpsLocation* location) 259 { 260 JNIEnv* env = AndroidRuntime::getJNIEnv(); 261 jint flags = 0; 262 jdouble latitude = 0; 263 jdouble longitude = 0; 264 jdouble altitude = 0; 265 jfloat speed = 0; 266 jfloat bearing = 0; 267 jfloat accuracy = 0; 268 jlong timestamp = 0; 269 if (location != NULL) { 270 flags = location->flags; 271 latitude = location->latitude; 272 longitude = location->longitude; 273 altitude = location->altitude; 274 speed = location->speed; 275 bearing = location->bearing; 276 accuracy = location->accuracy; 277 timestamp = location->timestamp; 278 } 279 280 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceStatus, status, 281 flags, latitude, longitude, altitude, speed, bearing, accuracy, timestamp); 282 checkAndClearExceptionFromCallback(env, __FUNCTION__); 283 }; 284 285 static void gps_geofence_add_callback(int32_t geofence_id, int32_t status) 286 { 287 JNIEnv* env = AndroidRuntime::getJNIEnv(); 288 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) { 289 ALOGE("Error in geofence_add_callback: %d\n", status); 290 } 291 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceAddStatus, geofence_id, status); 292 checkAndClearExceptionFromCallback(env, __FUNCTION__); 293 }; 294 295 static void gps_geofence_remove_callback(int32_t geofence_id, int32_t status) 296 { 297 JNIEnv* env = AndroidRuntime::getJNIEnv(); 298 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) { 299 ALOGE("Error in geofence_remove_callback: %d\n", status); 300 } 301 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceRemoveStatus, geofence_id, status); 302 checkAndClearExceptionFromCallback(env, __FUNCTION__); 303 }; 304 305 static void gps_geofence_resume_callback(int32_t geofence_id, int32_t status) 306 { 307 JNIEnv* env = AndroidRuntime::getJNIEnv(); 308 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) { 309 ALOGE("Error in geofence_resume_callback: %d\n", status); 310 } 311 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceResumeStatus, geofence_id, status); 312 checkAndClearExceptionFromCallback(env, __FUNCTION__); 313 }; 314 315 static void gps_geofence_pause_callback(int32_t geofence_id, int32_t status) 316 { 317 JNIEnv* env = AndroidRuntime::getJNIEnv(); 318 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) { 319 ALOGE("Error in geofence_pause_callback: %d\n", status); 320 } 321 env->CallVoidMethod(mCallbacksObj, method_reportGeofencePauseStatus, geofence_id, status); 322 checkAndClearExceptionFromCallback(env, __FUNCTION__); 323 }; 324 325 GpsGeofenceCallbacks sGpsGeofenceCallbacks = { 326 gps_geofence_transition_callback, 327 gps_geofence_status_callback, 328 gps_geofence_add_callback, 329 gps_geofence_remove_callback, 330 gps_geofence_pause_callback, 331 gps_geofence_resume_callback, 332 create_thread_callback, 333 }; 334 335 static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz) { 336 int err; 337 hw_module_t* module; 338 339 method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V"); 340 method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V"); 341 method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V"); 342 method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(III)V"); 343 method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V"); 344 method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V"); 345 method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V"); 346 method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification", 347 "(IIIIILjava/lang/String;Ljava/lang/String;IILjava/lang/String;)V"); 348 method_requestRefLocation = env->GetMethodID(clazz,"requestRefLocation","(I)V"); 349 method_requestSetID = env->GetMethodID(clazz,"requestSetID","(I)V"); 350 method_requestUtcTime = env->GetMethodID(clazz,"requestUtcTime","()V"); 351 method_reportGeofenceTransition = env->GetMethodID(clazz,"reportGeofenceTransition", 352 "(IIDDDFFFJIJ)V"); 353 method_reportGeofenceStatus = env->GetMethodID(clazz,"reportGeofenceStatus", 354 "(IIDDDFFFJ)V"); 355 method_reportGeofenceAddStatus = env->GetMethodID(clazz,"reportGeofenceAddStatus", 356 "(II)V"); 357 method_reportGeofenceRemoveStatus = env->GetMethodID(clazz,"reportGeofenceRemoveStatus", 358 "(II)V"); 359 method_reportGeofenceResumeStatus = env->GetMethodID(clazz,"reportGeofenceResumeStatus", 360 "(II)V"); 361 method_reportGeofencePauseStatus = env->GetMethodID(clazz,"reportGeofencePauseStatus", 362 "(II)V"); 363 364 err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module); 365 if (err == 0) { 366 hw_device_t* device; 367 err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device); 368 if (err == 0) { 369 gps_device_t* gps_device = (gps_device_t *)device; 370 sGpsInterface = gps_device->get_gps_interface(gps_device); 371 } 372 } 373 if (sGpsInterface) { 374 sGpsXtraInterface = 375 (const GpsXtraInterface*)sGpsInterface->get_extension(GPS_XTRA_INTERFACE); 376 sAGpsInterface = 377 (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE); 378 sGpsNiInterface = 379 (const GpsNiInterface*)sGpsInterface->get_extension(GPS_NI_INTERFACE); 380 sGpsDebugInterface = 381 (const GpsDebugInterface*)sGpsInterface->get_extension(GPS_DEBUG_INTERFACE); 382 sAGpsRilInterface = 383 (const AGpsRilInterface*)sGpsInterface->get_extension(AGPS_RIL_INTERFACE); 384 sGpsGeofencingInterface = 385 (const GpsGeofencingInterface*)sGpsInterface->get_extension(GPS_GEOFENCING_INTERFACE); 386 } 387 } 388 389 static jboolean android_location_GpsLocationProvider_is_supported(JNIEnv* env, jclass clazz) { 390 return (sGpsInterface != NULL); 391 } 392 393 static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject obj) 394 { 395 // this must be set before calling into the HAL library 396 if (!mCallbacksObj) 397 mCallbacksObj = env->NewGlobalRef(obj); 398 399 // fail if the main interface fails to initialize 400 if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0) 401 return false; 402 403 // if XTRA initialization fails we will disable it by sGpsXtraInterface to NULL, 404 // but continue to allow the rest of the GPS interface to work. 405 if (sGpsXtraInterface && sGpsXtraInterface->init(&sGpsXtraCallbacks) != 0) 406 sGpsXtraInterface = NULL; 407 if (sAGpsInterface) 408 sAGpsInterface->init(&sAGpsCallbacks); 409 if (sGpsNiInterface) 410 sGpsNiInterface->init(&sGpsNiCallbacks); 411 if (sAGpsRilInterface) 412 sAGpsRilInterface->init(&sAGpsRilCallbacks); 413 if (sGpsGeofencingInterface) 414 sGpsGeofencingInterface->init(&sGpsGeofenceCallbacks); 415 416 return true; 417 } 418 419 static void android_location_GpsLocationProvider_cleanup(JNIEnv* env, jobject obj) 420 { 421 if (sGpsInterface) 422 sGpsInterface->cleanup(); 423 } 424 425 static jboolean android_location_GpsLocationProvider_set_position_mode(JNIEnv* env, jobject obj, 426 jint mode, jint recurrence, jint min_interval, jint preferred_accuracy, jint preferred_time) 427 { 428 if (sGpsInterface) 429 return (sGpsInterface->set_position_mode(mode, recurrence, min_interval, preferred_accuracy, 430 preferred_time) == 0); 431 else 432 return false; 433 } 434 435 static jboolean android_location_GpsLocationProvider_start(JNIEnv* env, jobject obj) 436 { 437 if (sGpsInterface) 438 return (sGpsInterface->start() == 0); 439 else 440 return false; 441 } 442 443 static jboolean android_location_GpsLocationProvider_stop(JNIEnv* env, jobject obj) 444 { 445 if (sGpsInterface) 446 return (sGpsInterface->stop() == 0); 447 else 448 return false; 449 } 450 451 static void android_location_GpsLocationProvider_delete_aiding_data(JNIEnv* env, jobject obj, jint flags) 452 { 453 if (sGpsInterface) 454 sGpsInterface->delete_aiding_data(flags); 455 } 456 457 static jint android_location_GpsLocationProvider_read_sv_status(JNIEnv* env, jobject obj, 458 jintArray prnArray, jfloatArray snrArray, jfloatArray elevArray, jfloatArray azumArray, 459 jintArray maskArray) 460 { 461 // this should only be called from within a call to reportSvStatus 462 463 jint* prns = env->GetIntArrayElements(prnArray, 0); 464 jfloat* snrs = env->GetFloatArrayElements(snrArray, 0); 465 jfloat* elev = env->GetFloatArrayElements(elevArray, 0); 466 jfloat* azim = env->GetFloatArrayElements(azumArray, 0); 467 jint* mask = env->GetIntArrayElements(maskArray, 0); 468 469 int num_svs = sGpsSvStatus.num_svs; 470 for (int i = 0; i < num_svs; i++) { 471 prns[i] = sGpsSvStatus.sv_list[i].prn; 472 snrs[i] = sGpsSvStatus.sv_list[i].snr; 473 elev[i] = sGpsSvStatus.sv_list[i].elevation; 474 azim[i] = sGpsSvStatus.sv_list[i].azimuth; 475 } 476 mask[0] = sGpsSvStatus.ephemeris_mask; 477 mask[1] = sGpsSvStatus.almanac_mask; 478 mask[2] = sGpsSvStatus.used_in_fix_mask; 479 480 env->ReleaseIntArrayElements(prnArray, prns, 0); 481 env->ReleaseFloatArrayElements(snrArray, snrs, 0); 482 env->ReleaseFloatArrayElements(elevArray, elev, 0); 483 env->ReleaseFloatArrayElements(azumArray, azim, 0); 484 env->ReleaseIntArrayElements(maskArray, mask, 0); 485 return num_svs; 486 } 487 488 static void android_location_GpsLocationProvider_agps_set_reference_location_cellid(JNIEnv* env, 489 jobject obj, jint type, jint mcc, jint mnc, jint lac, jint cid) 490 { 491 AGpsRefLocation location; 492 493 if (!sAGpsRilInterface) { 494 ALOGE("no AGPS RIL interface in agps_set_reference_location_cellid"); 495 return; 496 } 497 498 switch(type) { 499 case AGPS_REF_LOCATION_TYPE_GSM_CELLID: 500 case AGPS_REF_LOCATION_TYPE_UMTS_CELLID: 501 location.type = type; 502 location.u.cellID.mcc = mcc; 503 location.u.cellID.mnc = mnc; 504 location.u.cellID.lac = lac; 505 location.u.cellID.cid = cid; 506 break; 507 default: 508 ALOGE("Neither a GSM nor a UMTS cellid (%s:%d).",__FUNCTION__,__LINE__); 509 return; 510 break; 511 } 512 sAGpsRilInterface->set_ref_location(&location, sizeof(location)); 513 } 514 515 static void android_location_GpsLocationProvider_agps_send_ni_message(JNIEnv* env, 516 jobject obj, jbyteArray ni_msg, jint size) 517 { 518 size_t sz; 519 520 if (!sAGpsRilInterface) { 521 ALOGE("no AGPS RIL interface in send_ni_message"); 522 return; 523 } 524 if (size < 0) 525 return; 526 sz = (size_t)size; 527 jbyte* b = env->GetByteArrayElements(ni_msg, 0); 528 sAGpsRilInterface->ni_message((uint8_t *)b,sz); 529 env->ReleaseByteArrayElements(ni_msg,b,0); 530 } 531 532 static void android_location_GpsLocationProvider_agps_set_id(JNIEnv *env, 533 jobject obj, jint type, jstring setid_string) 534 { 535 if (!sAGpsRilInterface) { 536 ALOGE("no AGPS RIL interface in agps_set_id"); 537 return; 538 } 539 540 const char *setid = env->GetStringUTFChars(setid_string, NULL); 541 sAGpsRilInterface->set_set_id(type, setid); 542 env->ReleaseStringUTFChars(setid_string, setid); 543 } 544 545 static jint android_location_GpsLocationProvider_read_nmea(JNIEnv* env, jobject obj, 546 jbyteArray nmeaArray, jint buffer_size) 547 { 548 // this should only be called from within a call to reportNmea 549 jbyte* nmea = (jbyte *)env->GetPrimitiveArrayCritical(nmeaArray, 0); 550 int length = sNmeaStringLength; 551 if (length > buffer_size) 552 length = buffer_size; 553 memcpy(nmea, sNmeaString, length); 554 env->ReleasePrimitiveArrayCritical(nmeaArray, nmea, JNI_ABORT); 555 return length; 556 } 557 558 static void android_location_GpsLocationProvider_inject_time(JNIEnv* env, jobject obj, 559 jlong time, jlong timeReference, jint uncertainty) 560 { 561 if (sGpsInterface) 562 sGpsInterface->inject_time(time, timeReference, uncertainty); 563 } 564 565 static void android_location_GpsLocationProvider_inject_location(JNIEnv* env, jobject obj, 566 jdouble latitude, jdouble longitude, jfloat accuracy) 567 { 568 if (sGpsInterface) 569 sGpsInterface->inject_location(latitude, longitude, accuracy); 570 } 571 572 static jboolean android_location_GpsLocationProvider_supports_xtra(JNIEnv* env, jobject obj) 573 { 574 return (sGpsXtraInterface != NULL); 575 } 576 577 static void android_location_GpsLocationProvider_inject_xtra_data(JNIEnv* env, jobject obj, 578 jbyteArray data, jint length) 579 { 580 if (!sGpsXtraInterface) { 581 ALOGE("no XTRA interface in inject_xtra_data"); 582 return; 583 } 584 585 jbyte* bytes = (jbyte *)env->GetPrimitiveArrayCritical(data, 0); 586 sGpsXtraInterface->inject_xtra_data((char *)bytes, length); 587 env->ReleasePrimitiveArrayCritical(data, bytes, JNI_ABORT); 588 } 589 590 static void android_location_GpsLocationProvider_agps_data_conn_open(JNIEnv* env, jobject obj, jstring apn) 591 { 592 if (!sAGpsInterface) { 593 ALOGE("no AGPS interface in agps_data_conn_open"); 594 return; 595 } 596 if (apn == NULL) { 597 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 598 return; 599 } 600 const char *apnStr = env->GetStringUTFChars(apn, NULL); 601 sAGpsInterface->data_conn_open(apnStr); 602 env->ReleaseStringUTFChars(apn, apnStr); 603 } 604 605 static void android_location_GpsLocationProvider_agps_data_conn_closed(JNIEnv* env, jobject obj) 606 { 607 if (!sAGpsInterface) { 608 ALOGE("no AGPS interface in agps_data_conn_closed"); 609 return; 610 } 611 sAGpsInterface->data_conn_closed(); 612 } 613 614 static void android_location_GpsLocationProvider_agps_data_conn_failed(JNIEnv* env, jobject obj) 615 { 616 if (!sAGpsInterface) { 617 ALOGE("no AGPS interface in agps_data_conn_failed"); 618 return; 619 } 620 sAGpsInterface->data_conn_failed(); 621 } 622 623 static void android_location_GpsLocationProvider_set_agps_server(JNIEnv* env, jobject obj, 624 jint type, jstring hostname, jint port) 625 { 626 if (!sAGpsInterface) { 627 ALOGE("no AGPS interface in set_agps_server"); 628 return; 629 } 630 const char *c_hostname = env->GetStringUTFChars(hostname, NULL); 631 sAGpsInterface->set_server(type, c_hostname, port); 632 env->ReleaseStringUTFChars(hostname, c_hostname); 633 } 634 635 static void android_location_GpsLocationProvider_send_ni_response(JNIEnv* env, jobject obj, 636 jint notifId, jint response) 637 { 638 if (!sGpsNiInterface) { 639 ALOGE("no NI interface in send_ni_response"); 640 return; 641 } 642 643 sGpsNiInterface->respond(notifId, response); 644 } 645 646 static jstring android_location_GpsLocationProvider_get_internal_state(JNIEnv* env, jobject obj) 647 { 648 jstring result = NULL; 649 if (sGpsDebugInterface) { 650 const size_t maxLength = 2047; 651 char buffer[maxLength+1]; 652 size_t length = sGpsDebugInterface->get_internal_state(buffer, maxLength); 653 if (length > maxLength) length = maxLength; 654 buffer[length] = 0; 655 result = env->NewStringUTF(buffer); 656 } 657 return result; 658 } 659 660 static void android_location_GpsLocationProvider_update_network_state(JNIEnv* env, jobject obj, 661 jboolean connected, int type, jboolean roaming, jboolean available, jstring extraInfo, jstring apn) 662 { 663 664 if (sAGpsRilInterface && sAGpsRilInterface->update_network_state) { 665 if (extraInfo) { 666 const char *extraInfoStr = env->GetStringUTFChars(extraInfo, NULL); 667 sAGpsRilInterface->update_network_state(connected, type, roaming, extraInfoStr); 668 env->ReleaseStringUTFChars(extraInfo, extraInfoStr); 669 } else { 670 sAGpsRilInterface->update_network_state(connected, type, roaming, NULL); 671 } 672 673 // update_network_availability callback was not included in original AGpsRilInterface 674 if (sAGpsRilInterface->size >= sizeof(AGpsRilInterface) 675 && sAGpsRilInterface->update_network_availability) { 676 const char *c_apn = env->GetStringUTFChars(apn, NULL); 677 sAGpsRilInterface->update_network_availability(available, c_apn); 678 env->ReleaseStringUTFChars(apn, c_apn); 679 } 680 } 681 } 682 683 static jboolean android_location_GpsLocationProvider_is_geofence_supported(JNIEnv* env, 684 jobject obj) { 685 if (sGpsGeofencingInterface != NULL) { 686 return JNI_TRUE; 687 } 688 return JNI_FALSE; 689 } 690 691 static jboolean android_location_GpsLocationProvider_add_geofence(JNIEnv* env, jobject obj, 692 jint geofence_id, jdouble latitude, jdouble longitude, jdouble radius, 693 jint last_transition, jint monitor_transition, jint notification_responsiveness, 694 jint unknown_timer) { 695 if (sGpsGeofencingInterface != NULL) { 696 sGpsGeofencingInterface->add_geofence_area(geofence_id, latitude, longitude, 697 radius, last_transition, monitor_transition, notification_responsiveness, 698 unknown_timer); 699 return JNI_TRUE; 700 } else { 701 ALOGE("Geofence interface not available"); 702 } 703 return JNI_FALSE; 704 } 705 706 static jboolean android_location_GpsLocationProvider_remove_geofence(JNIEnv* env, jobject obj, 707 jint geofence_id) { 708 if (sGpsGeofencingInterface != NULL) { 709 sGpsGeofencingInterface->remove_geofence_area(geofence_id); 710 return JNI_TRUE; 711 } else { 712 ALOGE("Geofence interface not available"); 713 } 714 return JNI_FALSE; 715 } 716 717 static jboolean android_location_GpsLocationProvider_pause_geofence(JNIEnv* env, jobject obj, 718 jint geofence_id) { 719 if (sGpsGeofencingInterface != NULL) { 720 sGpsGeofencingInterface->pause_geofence(geofence_id); 721 return JNI_TRUE; 722 } else { 723 ALOGE("Geofence interface not available"); 724 } 725 return JNI_FALSE; 726 } 727 728 static jboolean android_location_GpsLocationProvider_resume_geofence(JNIEnv* env, jobject obj, 729 jint geofence_id, jint monitor_transition) { 730 if (sGpsGeofencingInterface != NULL) { 731 sGpsGeofencingInterface->resume_geofence(geofence_id, monitor_transition); 732 return JNI_TRUE; 733 } else { 734 ALOGE("Geofence interface not available"); 735 } 736 return JNI_FALSE; 737 } 738 739 static JNINativeMethod sMethods[] = { 740 /* name, signature, funcPtr */ 741 {"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native}, 742 {"native_is_supported", "()Z", (void*)android_location_GpsLocationProvider_is_supported}, 743 {"native_init", "()Z", (void*)android_location_GpsLocationProvider_init}, 744 {"native_cleanup", "()V", (void*)android_location_GpsLocationProvider_cleanup}, 745 {"native_set_position_mode", "(IIIII)Z", (void*)android_location_GpsLocationProvider_set_position_mode}, 746 {"native_start", "()Z", (void*)android_location_GpsLocationProvider_start}, 747 {"native_stop", "()Z", (void*)android_location_GpsLocationProvider_stop}, 748 {"native_delete_aiding_data", "(I)V", (void*)android_location_GpsLocationProvider_delete_aiding_data}, 749 {"native_read_sv_status", "([I[F[F[F[I)I", (void*)android_location_GpsLocationProvider_read_sv_status}, 750 {"native_read_nmea", "([BI)I", (void*)android_location_GpsLocationProvider_read_nmea}, 751 {"native_inject_time", "(JJI)V", (void*)android_location_GpsLocationProvider_inject_time}, 752 {"native_inject_location", "(DDF)V", (void*)android_location_GpsLocationProvider_inject_location}, 753 {"native_supports_xtra", "()Z", (void*)android_location_GpsLocationProvider_supports_xtra}, 754 {"native_inject_xtra_data", "([BI)V", (void*)android_location_GpsLocationProvider_inject_xtra_data}, 755 {"native_agps_data_conn_open", "(Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_agps_data_conn_open}, 756 {"native_agps_data_conn_closed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_closed}, 757 {"native_agps_data_conn_failed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_failed}, 758 {"native_agps_set_id","(ILjava/lang/String;)V",(void*)android_location_GpsLocationProvider_agps_set_id}, 759 {"native_agps_set_ref_location_cellid","(IIIII)V",(void*)android_location_GpsLocationProvider_agps_set_reference_location_cellid}, 760 {"native_set_agps_server", "(ILjava/lang/String;I)V", (void*)android_location_GpsLocationProvider_set_agps_server}, 761 {"native_send_ni_response", "(II)V", (void*)android_location_GpsLocationProvider_send_ni_response}, 762 {"native_agps_ni_message", "([BI)V", (void *)android_location_GpsLocationProvider_agps_send_ni_message}, 763 {"native_get_internal_state", "()Ljava/lang/String;", (void*)android_location_GpsLocationProvider_get_internal_state}, 764 {"native_update_network_state", "(ZIZZLjava/lang/String;Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_update_network_state }, 765 {"native_is_geofence_supported", "()Z", (void*) android_location_GpsLocationProvider_is_geofence_supported}, 766 {"native_add_geofence", "(IDDDIIII)Z", (void *)android_location_GpsLocationProvider_add_geofence}, 767 {"native_remove_geofence", "(I)Z", (void *)android_location_GpsLocationProvider_remove_geofence}, 768 {"native_pause_geofence", "(I)Z", (void *)android_location_GpsLocationProvider_pause_geofence}, 769 {"native_resume_geofence", "(II)Z", (void *)android_location_GpsLocationProvider_resume_geofence} 770 }; 771 772 int register_android_server_location_GpsLocationProvider(JNIEnv* env) 773 { 774 return jniRegisterNativeMethods(env, "com/android/server/location/GpsLocationProvider", sMethods, NELEM(sMethods)); 775 } 776 777 } /* namespace android */ 778