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