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