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