Home | History | Annotate | Download | only in jni
      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 "GnssLocationProvider"
     18 
     19 #define LOG_NDEBUG 0
     20 
     21 #include "JNIHelp.h"
     22 #include "jni.h"
     23 #include "hardware/hardware.h"
     24 #include "hardware/gps_internal.h"
     25 #include "hardware_legacy/power.h"
     26 #include "utils/Log.h"
     27 #include "utils/misc.h"
     28 #include "android_runtime/AndroidRuntime.h"
     29 #include "android_runtime/Log.h"
     30 
     31 #include <arpa/inet.h>
     32 #include <limits>
     33 #include <linux/in.h>
     34 #include <linux/in6.h>
     35 #include <pthread.h>
     36 #include <string.h>
     37 
     38 static jobject mCallbacksObj = NULL;
     39 
     40 static jmethodID method_reportLocation;
     41 static jmethodID method_reportStatus;
     42 static jmethodID method_reportSvStatus;
     43 static jmethodID method_reportAGpsStatus;
     44 static jmethodID method_reportNmea;
     45 static jmethodID method_setEngineCapabilities;
     46 static jmethodID method_setGnssYearOfHardware;
     47 static jmethodID method_xtraDownloadRequest;
     48 static jmethodID method_reportNiNotification;
     49 static jmethodID method_requestRefLocation;
     50 static jmethodID method_requestSetID;
     51 static jmethodID method_requestUtcTime;
     52 static jmethodID method_reportGeofenceTransition;
     53 static jmethodID method_reportGeofenceStatus;
     54 static jmethodID method_reportGeofenceAddStatus;
     55 static jmethodID method_reportGeofenceRemoveStatus;
     56 static jmethodID method_reportGeofencePauseStatus;
     57 static jmethodID method_reportGeofenceResumeStatus;
     58 static jmethodID method_reportMeasurementData;
     59 static jmethodID method_reportNavigationMessages;
     60 
     61 static const GpsInterface* sGpsInterface = NULL;
     62 static const GpsXtraInterface* sGpsXtraInterface = NULL;
     63 static const AGpsInterface* sAGpsInterface = NULL;
     64 static const GpsNiInterface* sGpsNiInterface = NULL;
     65 static const GpsDebugInterface* sGpsDebugInterface = NULL;
     66 static const AGpsRilInterface* sAGpsRilInterface = NULL;
     67 static const GpsGeofencingInterface* sGpsGeofencingInterface = NULL;
     68 static const GpsMeasurementInterface* sGpsMeasurementInterface = NULL;
     69 static const GpsNavigationMessageInterface* sGpsNavigationMessageInterface = NULL;
     70 static const GnssConfigurationInterface* sGnssConfigurationInterface = NULL;
     71 
     72 #define GPS_MAX_SATELLITE_COUNT 32
     73 #define GNSS_MAX_SATELLITE_COUNT 64
     74 
     75 // Let these through, with ID remapped down to 1, 2... by offset
     76 #define GLONASS_SVID_OFFSET 64
     77 #define GLONASS_SVID_COUNT 24
     78 #define BEIDOU_SVID_OFFSET 200
     79 #define BEIDOU_SVID_COUNT 35
     80 
     81 // Let these through, with ID remapped up (33->120 ... 64->151, etc.)
     82 #define SBAS_SVID_MIN 33
     83 #define SBAS_SVID_MAX 64
     84 #define SBAS_SVID_ADD 87
     85 
     86 // Let these through, with no ID remapping
     87 #define QZSS_SVID_MIN 193
     88 #define QZSS_SVID_MAX 200
     89 
     90 #define SVID_SHIFT_WIDTH 7
     91 #define CONSTELLATION_TYPE_SHIFT_WIDTH 3
     92 
     93 // temporary storage for GPS callbacks
     94 static GnssSvInfo sGnssSvList[GNSS_MAX_SATELLITE_COUNT];
     95 static size_t sGnssSvListSize;
     96 static const char* sNmeaString;
     97 static int sNmeaStringLength;
     98 
     99 #define WAKE_LOCK_NAME  "GPS"
    100 
    101 namespace android {
    102 
    103 static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
    104     if (env->ExceptionCheck()) {
    105         ALOGE("An exception was thrown by callback '%s'.", methodName);
    106         LOGE_EX(env);
    107         env->ExceptionClear();
    108     }
    109 }
    110 
    111 static void location_callback(GpsLocation* location)
    112 {
    113     JNIEnv* env = AndroidRuntime::getJNIEnv();
    114     env->CallVoidMethod(mCallbacksObj, method_reportLocation, location->flags,
    115             (jdouble)location->latitude, (jdouble)location->longitude,
    116             (jdouble)location->altitude,
    117             (jfloat)location->speed, (jfloat)location->bearing,
    118             (jfloat)location->accuracy, (jlong)location->timestamp);
    119     checkAndClearExceptionFromCallback(env, __FUNCTION__);
    120 }
    121 
    122 static void status_callback(GpsStatus* status)
    123 {
    124     JNIEnv* env = AndroidRuntime::getJNIEnv();
    125     env->CallVoidMethod(mCallbacksObj, method_reportStatus, status->status);
    126     checkAndClearExceptionFromCallback(env, __FUNCTION__);
    127 }
    128 
    129 static void sv_status_callback(GpsSvStatus* sv_status)
    130 {
    131     JNIEnv* env = AndroidRuntime::getJNIEnv();
    132     size_t status_size = sv_status->size;
    133     // Some drives doesn't set the size field correctly. Assume GpsSvStatus_v1
    134     // if it doesn't provide a valid size.
    135     if (status_size == 0) {
    136         ALOGW("Invalid size of GpsSvStatus found: %zd.", status_size);
    137     }
    138     sGnssSvListSize = sv_status->num_svs;
    139     // Clamp the list size. Legacy GpsSvStatus has only 32 elements in sv_list.
    140     if (sGnssSvListSize > GPS_MAX_SATELLITE_COUNT) {
    141         ALOGW("Too many satellites %zd. Clamps to %d.",
    142               sGnssSvListSize,
    143               GPS_MAX_SATELLITE_COUNT);
    144         sGnssSvListSize = GPS_MAX_SATELLITE_COUNT;
    145     }
    146     uint32_t ephemeris_mask = sv_status->ephemeris_mask;
    147     uint32_t almanac_mask = sv_status->almanac_mask;
    148     uint32_t used_in_fix_mask = sv_status->used_in_fix_mask;
    149     for (size_t i = 0; i < sGnssSvListSize; i++) {
    150         GnssSvInfo& info = sGnssSvList[i];
    151         info.svid = sv_status->sv_list[i].prn;
    152         // Defacto mapping from the overused API that was designed for GPS-only
    153         if (info.svid >=1 && info.svid <= 32) {
    154             info.constellation = GNSS_CONSTELLATION_GPS;
    155         } else if (info.svid > GLONASS_SVID_OFFSET &&
    156                    info.svid <= GLONASS_SVID_OFFSET + GLONASS_SVID_COUNT) {
    157             info.constellation = GNSS_CONSTELLATION_GLONASS;
    158             info.svid -= GLONASS_SVID_OFFSET;
    159         } else if (info.svid > BEIDOU_SVID_OFFSET &&
    160                    info.svid <= BEIDOU_SVID_OFFSET + BEIDOU_SVID_COUNT) {
    161             info.constellation = GNSS_CONSTELLATION_BEIDOU;
    162             info.svid -= BEIDOU_SVID_OFFSET;
    163         } else if (info.svid >= SBAS_SVID_MIN && info.svid <= SBAS_SVID_MAX) {
    164             info.constellation = GNSS_CONSTELLATION_SBAS;
    165             info.svid += SBAS_SVID_ADD;
    166         } else if (info.svid >= QZSS_SVID_MIN && info.svid <= QZSS_SVID_MAX) {
    167             info.constellation = GNSS_CONSTELLATION_QZSS;
    168         } else {
    169             ALOGD("Unknown constellation type with Svid = %d.", info.svid);
    170             info.constellation = GNSS_CONSTELLATION_UNKNOWN;
    171         }
    172         info.c_n0_dbhz = sv_status->sv_list[i].snr;
    173         info.elevation = sv_status->sv_list[i].elevation;
    174         info.azimuth = sv_status->sv_list[i].azimuth;
    175         info.flags = GNSS_SV_FLAGS_NONE;
    176         // Only GPS info is valid for these fields, as these masks are just 32 bits, by GPS prn
    177         if (info.constellation == GNSS_CONSTELLATION_GPS) {
    178             int32_t this_svid_mask = (1 << (info.svid - 1));
    179             if ((ephemeris_mask & this_svid_mask) != 0) {
    180                 info.flags |= GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA;
    181             }
    182             if ((almanac_mask & this_svid_mask) != 0) {
    183                 info.flags |= GNSS_SV_FLAGS_HAS_ALMANAC_DATA;
    184             }
    185             if ((used_in_fix_mask & this_svid_mask) != 0) {
    186                 info.flags |= GNSS_SV_FLAGS_USED_IN_FIX;
    187             }
    188         }
    189     }
    190     env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
    191     checkAndClearExceptionFromCallback(env, __FUNCTION__);
    192 }
    193 
    194 static void gnss_sv_status_callback(GnssSvStatus* sv_status) {
    195     JNIEnv* env = AndroidRuntime::getJNIEnv();
    196     size_t status_size = sv_status->size;
    197     // Check the size, and reject the object that has invalid size.
    198     if (status_size != sizeof(GnssSvStatus)) {
    199         ALOGE("Invalid size of GnssSvStatus found: %zd.", status_size);
    200         return;
    201     }
    202     sGnssSvListSize = sv_status->num_svs;
    203     // Clamp the list size
    204     if (sGnssSvListSize > GNSS_MAX_SATELLITE_COUNT) {
    205         ALOGD("Too many satellites %zd. Clamps to %d.",
    206               sGnssSvListSize,
    207               GNSS_MAX_SATELLITE_COUNT);
    208         sGnssSvListSize = GNSS_MAX_SATELLITE_COUNT;
    209     }
    210     // Copy GNSS SV info into sGnssSvList, if any.
    211     if (sGnssSvListSize > 0) {
    212         memcpy(sGnssSvList,
    213                sv_status->gnss_sv_list,
    214                sizeof(GnssSvInfo) * sGnssSvListSize);
    215     }
    216     env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
    217     checkAndClearExceptionFromCallback(env, __FUNCTION__);
    218 }
    219 
    220 static void nmea_callback(GpsUtcTime timestamp, const char* nmea, int length)
    221 {
    222     JNIEnv* env = AndroidRuntime::getJNIEnv();
    223     // The Java code will call back to read these values
    224     // We do this to avoid creating unnecessary String objects
    225     sNmeaString = nmea;
    226     sNmeaStringLength = length;
    227     env->CallVoidMethod(mCallbacksObj, method_reportNmea, timestamp);
    228     checkAndClearExceptionFromCallback(env, __FUNCTION__);
    229 }
    230 
    231 static void set_system_info_callback(const GnssSystemInfo* info) {
    232     ALOGD("set_system_info_callback: year_of_hw=%d\n", info->year_of_hw);
    233     JNIEnv* env = AndroidRuntime::getJNIEnv();
    234     env->CallVoidMethod(mCallbacksObj, method_setGnssYearOfHardware,
    235                         info->year_of_hw);
    236     checkAndClearExceptionFromCallback(env, __FUNCTION__);
    237 }
    238 
    239 static void set_capabilities_callback(uint32_t capabilities)
    240 {
    241     ALOGD("set_capabilities_callback: %du\n", capabilities);
    242     JNIEnv* env = AndroidRuntime::getJNIEnv();
    243     env->CallVoidMethod(mCallbacksObj, method_setEngineCapabilities, capabilities);
    244     checkAndClearExceptionFromCallback(env, __FUNCTION__);
    245 }
    246 
    247 static void acquire_wakelock_callback()
    248 {
    249     acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
    250 }
    251 
    252 static void release_wakelock_callback()
    253 {
    254     release_wake_lock(WAKE_LOCK_NAME);
    255 }
    256 
    257 static void request_utc_time_callback()
    258 {
    259     JNIEnv* env = AndroidRuntime::getJNIEnv();
    260     env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
    261     checkAndClearExceptionFromCallback(env, __FUNCTION__);
    262 }
    263 
    264 static pthread_t create_thread_callback(const char* name, void (*start)(void *), void* arg)
    265 {
    266     return (pthread_t)AndroidRuntime::createJavaThread(name, start, arg);
    267 }
    268 
    269 GpsCallbacks sGpsCallbacks = {
    270     sizeof(GpsCallbacks),
    271     location_callback,
    272     status_callback,
    273     sv_status_callback,
    274     nmea_callback,
    275     set_capabilities_callback,
    276     acquire_wakelock_callback,
    277     release_wakelock_callback,
    278     create_thread_callback,
    279     request_utc_time_callback,
    280     set_system_info_callback,
    281     gnss_sv_status_callback,
    282 };
    283 
    284 static void xtra_download_request_callback()
    285 {
    286     JNIEnv* env = AndroidRuntime::getJNIEnv();
    287     env->CallVoidMethod(mCallbacksObj, method_xtraDownloadRequest);
    288     checkAndClearExceptionFromCallback(env, __FUNCTION__);
    289 }
    290 
    291 GpsXtraCallbacks sGpsXtraCallbacks = {
    292     xtra_download_request_callback,
    293     create_thread_callback,
    294 };
    295 
    296 static jbyteArray convert_to_ipv4(uint32_t ip, bool net_order)
    297 {
    298     if (INADDR_NONE == ip) {
    299         return NULL;
    300     }
    301 
    302     JNIEnv* env = AndroidRuntime::getJNIEnv();
    303     jbyteArray byteArray = env->NewByteArray(4);
    304     if (byteArray == NULL) {
    305         ALOGE("Unable to allocate byte array for IPv4 address");
    306         return NULL;
    307     }
    308 
    309     jbyte ipv4[4];
    310     if (net_order) {
    311         ALOGV("Converting IPv4 address(net_order) %x", ip);
    312         memcpy(ipv4, &ip, sizeof(ipv4));
    313     } else {
    314         ALOGV("Converting IPv4 address(host_order) %x", ip);
    315         //endianess transparent conversion from int to char[]
    316         ipv4[0] = (jbyte) (ip & 0xFF);
    317         ipv4[1] = (jbyte)((ip>>8) & 0xFF);
    318         ipv4[2] = (jbyte)((ip>>16) & 0xFF);
    319         ipv4[3] = (jbyte) (ip>>24);
    320     }
    321 
    322     env->SetByteArrayRegion(byteArray, 0, 4, (const jbyte*) ipv4);
    323     return byteArray;
    324 }
    325 
    326 static void agps_status_callback(AGpsStatus* agps_status)
    327 {
    328     JNIEnv* env = AndroidRuntime::getJNIEnv();
    329     jbyteArray byteArray = NULL;
    330     bool isSupported = false;
    331 
    332     size_t status_size = agps_status->size;
    333     if (status_size == sizeof(AGpsStatus)) {
    334       ALOGV("AGpsStatus is V3: %zd", status_size);
    335       switch (agps_status->addr.ss_family)
    336       {
    337       case AF_INET:
    338           {
    339             struct sockaddr_in *in = (struct sockaddr_in*)&(agps_status->addr);
    340             uint32_t ipAddr = *(uint32_t*)&(in->sin_addr);
    341             byteArray = convert_to_ipv4(ipAddr, true /* net_order */);
    342             if (ipAddr == INADDR_NONE || byteArray != NULL) {
    343                 isSupported = true;
    344             }
    345             IF_ALOGD() {
    346                 // log the IP for reference in case there is a bogus value pushed by HAL
    347                 char str[INET_ADDRSTRLEN];
    348                 inet_ntop(AF_INET, &(in->sin_addr), str, INET_ADDRSTRLEN);
    349                 ALOGD("AGPS IP is v4: %s", str);
    350             }
    351           }
    352           break;
    353       case AF_INET6:
    354           {
    355             struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&(agps_status->addr);
    356             byteArray = env->NewByteArray(16);
    357             if (byteArray != NULL) {
    358                 env->SetByteArrayRegion(byteArray, 0, 16, (const jbyte *)&(in6->sin6_addr));
    359                 isSupported = true;
    360             } else {
    361                 ALOGE("Unable to allocate byte array for IPv6 address.");
    362             }
    363             IF_ALOGD() {
    364                 // log the IP for reference in case there is a bogus value pushed by HAL
    365                 char str[INET6_ADDRSTRLEN];
    366                 inet_ntop(AF_INET6, &(in6->sin6_addr), str, INET6_ADDRSTRLEN);
    367                 ALOGD("AGPS IP is v6: %s", str);
    368             }
    369           }
    370           break;
    371       default:
    372           ALOGE("Invalid ss_family found: %d", agps_status->addr.ss_family);
    373           break;
    374       }
    375     } else if (status_size >= sizeof(AGpsStatus_v2)) {
    376       ALOGV("AGpsStatus is V2+: %zd", status_size);
    377       // for back-compatibility reasons we check in v2 that the data structure size is greater or
    378       // equal to the declared size in gps.h
    379       uint32_t ipaddr = agps_status->ipaddr;
    380       ALOGV("AGPS IP is v4: %x", ipaddr);
    381       byteArray = convert_to_ipv4(ipaddr, false /* net_order */);
    382       if (ipaddr == INADDR_NONE || byteArray != NULL) {
    383           isSupported = true;
    384       }
    385     } else if (status_size >= sizeof(AGpsStatus_v1)) {
    386         ALOGV("AGpsStatus is V1+: %zd", status_size);
    387         // because we have to check for >= with regards to v2, we also need to relax the check here
    388         // and only make sure that the size is at least what we expect
    389         isSupported = true;
    390     } else {
    391         ALOGE("Invalid size of AGpsStatus found: %zd.", status_size);
    392     }
    393 
    394     if (isSupported) {
    395         jsize byteArrayLength = byteArray != NULL ? env->GetArrayLength(byteArray) : 0;
    396         ALOGV("Passing AGPS IP addr: size %d", byteArrayLength);
    397         env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus, agps_status->type,
    398                             agps_status->status, byteArray);
    399 
    400         checkAndClearExceptionFromCallback(env, __FUNCTION__);
    401     } else {
    402         ALOGD("Skipping calling method_reportAGpsStatus.");
    403     }
    404 
    405     if (byteArray) {
    406         env->DeleteLocalRef(byteArray);
    407     }
    408 }
    409 
    410 AGpsCallbacks sAGpsCallbacks = {
    411     agps_status_callback,
    412     create_thread_callback,
    413 };
    414 
    415 static void gps_ni_notify_callback(GpsNiNotification *notification)
    416 {
    417     ALOGD("gps_ni_notify_callback\n");
    418     JNIEnv* env = AndroidRuntime::getJNIEnv();
    419     jstring requestor_id = env->NewStringUTF(notification->requestor_id);
    420     jstring text = env->NewStringUTF(notification->text);
    421     jstring extras = env->NewStringUTF(notification->extras);
    422 
    423     if (requestor_id && text && extras) {
    424         env->CallVoidMethod(mCallbacksObj, method_reportNiNotification,
    425             notification->notification_id, notification->ni_type,
    426             notification->notify_flags, notification->timeout,
    427             notification->default_response, requestor_id, text,
    428             notification->requestor_id_encoding,
    429             notification->text_encoding, extras);
    430     } else {
    431         ALOGE("out of memory in gps_ni_notify_callback\n");
    432     }
    433 
    434     if (requestor_id)
    435         env->DeleteLocalRef(requestor_id);
    436     if (text)
    437         env->DeleteLocalRef(text);
    438     if (extras)
    439         env->DeleteLocalRef(extras);
    440     checkAndClearExceptionFromCallback(env, __FUNCTION__);
    441 }
    442 
    443 GpsNiCallbacks sGpsNiCallbacks = {
    444     gps_ni_notify_callback,
    445     create_thread_callback,
    446 };
    447 
    448 static void agps_request_set_id(uint32_t flags)
    449 {
    450     JNIEnv* env = AndroidRuntime::getJNIEnv();
    451     env->CallVoidMethod(mCallbacksObj, method_requestSetID, flags);
    452     checkAndClearExceptionFromCallback(env, __FUNCTION__);
    453 }
    454 
    455 static void agps_request_ref_location(uint32_t flags)
    456 {
    457     JNIEnv* env = AndroidRuntime::getJNIEnv();
    458     env->CallVoidMethod(mCallbacksObj, method_requestRefLocation, flags);
    459     checkAndClearExceptionFromCallback(env, __FUNCTION__);
    460 }
    461 
    462 AGpsRilCallbacks sAGpsRilCallbacks = {
    463     agps_request_set_id,
    464     agps_request_ref_location,
    465     create_thread_callback,
    466 };
    467 
    468 static void gps_geofence_transition_callback(int32_t geofence_id,  GpsLocation* location,
    469         int32_t transition, GpsUtcTime timestamp)
    470 {
    471     JNIEnv* env = AndroidRuntime::getJNIEnv();
    472 
    473     env->CallVoidMethod(mCallbacksObj, method_reportGeofenceTransition, geofence_id,
    474             location->flags, (jdouble)location->latitude, (jdouble)location->longitude,
    475             (jdouble)location->altitude,
    476             (jfloat)location->speed, (jfloat)location->bearing,
    477             (jfloat)location->accuracy, (jlong)location->timestamp,
    478             transition, timestamp);
    479     checkAndClearExceptionFromCallback(env, __FUNCTION__);
    480 };
    481 
    482 static void gps_geofence_status_callback(int32_t status, GpsLocation* location)
    483 {
    484     JNIEnv* env = AndroidRuntime::getJNIEnv();
    485     jint flags = 0;
    486     jdouble latitude = 0;
    487     jdouble longitude = 0;
    488     jdouble altitude = 0;
    489     jfloat speed = 0;
    490     jfloat bearing = 0;
    491     jfloat accuracy = 0;
    492     jlong timestamp = 0;
    493     if (location != NULL) {
    494         flags = location->flags;
    495         latitude = location->latitude;
    496         longitude = location->longitude;
    497         altitude = location->altitude;
    498         speed = location->speed;
    499         bearing = location->bearing;
    500         accuracy = location->accuracy;
    501         timestamp = location->timestamp;
    502     }
    503 
    504     env->CallVoidMethod(mCallbacksObj, method_reportGeofenceStatus, status,
    505             flags, latitude, longitude, altitude, speed, bearing, accuracy, timestamp);
    506     checkAndClearExceptionFromCallback(env, __FUNCTION__);
    507 };
    508 
    509 static void gps_geofence_add_callback(int32_t geofence_id, int32_t status)
    510 {
    511     JNIEnv* env = AndroidRuntime::getJNIEnv();
    512     if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
    513         ALOGE("Error in geofence_add_callback: %d\n", status);
    514     }
    515     env->CallVoidMethod(mCallbacksObj, method_reportGeofenceAddStatus, geofence_id, status);
    516     checkAndClearExceptionFromCallback(env, __FUNCTION__);
    517 };
    518 
    519 static void gps_geofence_remove_callback(int32_t geofence_id, int32_t status)
    520 {
    521     JNIEnv* env = AndroidRuntime::getJNIEnv();
    522     if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
    523         ALOGE("Error in geofence_remove_callback: %d\n", status);
    524     }
    525     env->CallVoidMethod(mCallbacksObj, method_reportGeofenceRemoveStatus, geofence_id, status);
    526     checkAndClearExceptionFromCallback(env, __FUNCTION__);
    527 };
    528 
    529 static void gps_geofence_resume_callback(int32_t geofence_id, int32_t status)
    530 {
    531     JNIEnv* env = AndroidRuntime::getJNIEnv();
    532     if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
    533         ALOGE("Error in geofence_resume_callback: %d\n", status);
    534     }
    535     env->CallVoidMethod(mCallbacksObj, method_reportGeofenceResumeStatus, geofence_id, status);
    536     checkAndClearExceptionFromCallback(env, __FUNCTION__);
    537 };
    538 
    539 static void gps_geofence_pause_callback(int32_t geofence_id, int32_t status)
    540 {
    541     JNIEnv* env = AndroidRuntime::getJNIEnv();
    542     if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
    543         ALOGE("Error in geofence_pause_callback: %d\n", status);
    544     }
    545     env->CallVoidMethod(mCallbacksObj, method_reportGeofencePauseStatus, geofence_id, status);
    546     checkAndClearExceptionFromCallback(env, __FUNCTION__);
    547 };
    548 
    549 GpsGeofenceCallbacks sGpsGeofenceCallbacks = {
    550     gps_geofence_transition_callback,
    551     gps_geofence_status_callback,
    552     gps_geofence_add_callback,
    553     gps_geofence_remove_callback,
    554     gps_geofence_pause_callback,
    555     gps_geofence_resume_callback,
    556     create_thread_callback,
    557 };
    558 
    559 static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
    560     int err;
    561     hw_module_t* module;
    562 
    563     method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
    564     method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
    565     method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");
    566     method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V");
    567     method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");
    568     method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V");
    569     method_setGnssYearOfHardware = env->GetMethodID(clazz, "setGnssYearOfHardware", "(I)V");
    570     method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
    571     method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",
    572             "(IIIIILjava/lang/String;Ljava/lang/String;IILjava/lang/String;)V");
    573     method_requestRefLocation = env->GetMethodID(clazz,"requestRefLocation","(I)V");
    574     method_requestSetID = env->GetMethodID(clazz,"requestSetID","(I)V");
    575     method_requestUtcTime = env->GetMethodID(clazz,"requestUtcTime","()V");
    576     method_reportGeofenceTransition = env->GetMethodID(clazz,"reportGeofenceTransition",
    577             "(IIDDDFFFJIJ)V");
    578     method_reportGeofenceStatus = env->GetMethodID(clazz,"reportGeofenceStatus",
    579             "(IIDDDFFFJ)V");
    580     method_reportGeofenceAddStatus = env->GetMethodID(clazz,"reportGeofenceAddStatus",
    581             "(II)V");
    582     method_reportGeofenceRemoveStatus = env->GetMethodID(clazz,"reportGeofenceRemoveStatus",
    583             "(II)V");
    584     method_reportGeofenceResumeStatus = env->GetMethodID(clazz,"reportGeofenceResumeStatus",
    585             "(II)V");
    586     method_reportGeofencePauseStatus = env->GetMethodID(clazz,"reportGeofencePauseStatus",
    587             "(II)V");
    588     method_reportMeasurementData = env->GetMethodID(
    589             clazz,
    590             "reportMeasurementData",
    591             "(Landroid/location/GnssMeasurementsEvent;)V");
    592     method_reportNavigationMessages = env->GetMethodID(
    593             clazz,
    594             "reportNavigationMessage",
    595             "(Landroid/location/GnssNavigationMessage;)V");
    596 
    597     err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
    598     if (err == 0) {
    599         hw_device_t* device;
    600         err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
    601         if (err == 0) {
    602             gps_device_t* gps_device = (gps_device_t *)device;
    603             sGpsInterface = gps_device->get_gps_interface(gps_device);
    604         }
    605     }
    606     if (sGpsInterface) {
    607         sGpsXtraInterface =
    608             (const GpsXtraInterface*)sGpsInterface->get_extension(GPS_XTRA_INTERFACE);
    609         sAGpsInterface =
    610             (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
    611         sGpsNiInterface =
    612             (const GpsNiInterface*)sGpsInterface->get_extension(GPS_NI_INTERFACE);
    613         sGpsDebugInterface =
    614             (const GpsDebugInterface*)sGpsInterface->get_extension(GPS_DEBUG_INTERFACE);
    615         sAGpsRilInterface =
    616             (const AGpsRilInterface*)sGpsInterface->get_extension(AGPS_RIL_INTERFACE);
    617         sGpsGeofencingInterface =
    618             (const GpsGeofencingInterface*)sGpsInterface->get_extension(GPS_GEOFENCING_INTERFACE);
    619         sGpsMeasurementInterface =
    620             (const GpsMeasurementInterface*)sGpsInterface->get_extension(GPS_MEASUREMENT_INTERFACE);
    621         sGpsNavigationMessageInterface =
    622             (const GpsNavigationMessageInterface*)sGpsInterface->get_extension(
    623                     GPS_NAVIGATION_MESSAGE_INTERFACE);
    624         sGnssConfigurationInterface =
    625             (const GnssConfigurationInterface*)sGpsInterface->get_extension(
    626                     GNSS_CONFIGURATION_INTERFACE);
    627     }
    628 }
    629 
    630 static jboolean android_location_GnssLocationProvider_is_supported(
    631         JNIEnv* /* env */, jclass /* clazz */)
    632 {
    633     return (sGpsInterface != NULL) ?  JNI_TRUE : JNI_FALSE;
    634 }
    635 
    636 static jboolean android_location_GnssLocationProvider_is_agps_ril_supported(
    637         JNIEnv* /* env */, jclass /* clazz */)
    638 {
    639     return (sAGpsRilInterface != NULL) ? JNI_TRUE : JNI_FALSE;
    640 }
    641 
    642 static jboolean android_location_gpsLocationProvider_is_gnss_configuration_supported(
    643         JNIEnv* /* env */, jclass /* jclazz */)
    644 {
    645     return (sGnssConfigurationInterface != NULL) ? JNI_TRUE : JNI_FALSE;
    646 }
    647 
    648 static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject obj)
    649 {
    650     // this must be set before calling into the HAL library
    651     if (!mCallbacksObj)
    652         mCallbacksObj = env->NewGlobalRef(obj);
    653 
    654     // fail if the main interface fails to initialize
    655     if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
    656         return JNI_FALSE;
    657 
    658     // if XTRA initialization fails we will disable it by sGpsXtraInterface to NULL,
    659     // but continue to allow the rest of the GPS interface to work.
    660     if (sGpsXtraInterface && sGpsXtraInterface->init(&sGpsXtraCallbacks) != 0)
    661         sGpsXtraInterface = NULL;
    662     if (sAGpsInterface)
    663         sAGpsInterface->init(&sAGpsCallbacks);
    664     if (sGpsNiInterface)
    665         sGpsNiInterface->init(&sGpsNiCallbacks);
    666     if (sAGpsRilInterface)
    667         sAGpsRilInterface->init(&sAGpsRilCallbacks);
    668     if (sGpsGeofencingInterface)
    669         sGpsGeofencingInterface->init(&sGpsGeofenceCallbacks);
    670 
    671     return JNI_TRUE;
    672 }
    673 
    674 static void android_location_GnssLocationProvider_cleanup(JNIEnv* /* env */, jobject /* obj */)
    675 {
    676     if (sGpsInterface)
    677         sGpsInterface->cleanup();
    678 }
    679 
    680 static jboolean android_location_GnssLocationProvider_set_position_mode(JNIEnv* /* env */,
    681         jobject /* obj */, jint mode, jint recurrence, jint min_interval, jint preferred_accuracy,
    682         jint preferred_time)
    683 {
    684     if (sGpsInterface) {
    685         if (sGpsInterface->set_position_mode(mode, recurrence, min_interval, preferred_accuracy,
    686                 preferred_time) == 0) {
    687             return JNI_TRUE;
    688         } else {
    689             return JNI_FALSE;
    690         }
    691     }
    692     else
    693         return JNI_FALSE;
    694 }
    695 
    696 static jboolean android_location_GnssLocationProvider_start(JNIEnv* /* env */, jobject /* obj */)
    697 {
    698     if (sGpsInterface) {
    699         if (sGpsInterface->start() == 0) {
    700             return JNI_TRUE;
    701         } else {
    702             return JNI_FALSE;
    703         }
    704     }
    705     else
    706         return JNI_FALSE;
    707 }
    708 
    709 static jboolean android_location_GnssLocationProvider_stop(JNIEnv* /* env */, jobject /* obj */)
    710 {
    711     if (sGpsInterface) {
    712         if (sGpsInterface->stop() == 0) {
    713             return JNI_TRUE;
    714         } else {
    715             return JNI_FALSE;
    716         }
    717     }
    718     else
    719         return JNI_FALSE;
    720 }
    721 
    722 static void android_location_GnssLocationProvider_delete_aiding_data(JNIEnv* /* env */,
    723                                                                     jobject /* obj */,
    724                                                                     jint flags)
    725 {
    726     if (sGpsInterface)
    727         sGpsInterface->delete_aiding_data(flags);
    728 }
    729 
    730 static jint android_location_GnssLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */,
    731         jintArray svidWithFlagArray, jfloatArray cn0Array, jfloatArray elevArray,
    732         jfloatArray azumArray)
    733 {
    734     // this should only be called from within a call to reportSvStatus
    735     jint* svidWithFlags = env->GetIntArrayElements(svidWithFlagArray, 0);
    736     jfloat* cn0s = env->GetFloatArrayElements(cn0Array, 0);
    737     jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
    738     jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
    739 
    740     // GNSS SV info.
    741     for (size_t i = 0; i < sGnssSvListSize; ++i) {
    742         const GnssSvInfo& info = sGnssSvList[i];
    743         svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) |
    744             (info.constellation << CONSTELLATION_TYPE_SHIFT_WIDTH) |
    745             info.flags;
    746         cn0s[i] = info.c_n0_dbhz;
    747         elev[i] = info.elevation;
    748         azim[i] = info.azimuth;
    749     }
    750 
    751     env->ReleaseIntArrayElements(svidWithFlagArray, svidWithFlags, 0);
    752     env->ReleaseFloatArrayElements(cn0Array, cn0s, 0);
    753     env->ReleaseFloatArrayElements(elevArray, elev, 0);
    754     env->ReleaseFloatArrayElements(azumArray, azim, 0);
    755     return (jint) sGnssSvListSize;
    756 }
    757 
    758 static void android_location_GnssLocationProvider_agps_set_reference_location_cellid(
    759         JNIEnv* /* env */, jobject /* obj */, jint type, jint mcc, jint mnc, jint lac, jint cid)
    760 {
    761     AGpsRefLocation location;
    762 
    763     if (!sAGpsRilInterface) {
    764         ALOGE("no AGPS RIL interface in agps_set_reference_location_cellid");
    765         return;
    766     }
    767 
    768     switch(type) {
    769         case AGPS_REF_LOCATION_TYPE_GSM_CELLID:
    770         case AGPS_REF_LOCATION_TYPE_UMTS_CELLID:
    771             location.type = type;
    772             location.u.cellID.mcc = mcc;
    773             location.u.cellID.mnc = mnc;
    774             location.u.cellID.lac = lac;
    775             location.u.cellID.cid = cid;
    776             break;
    777         default:
    778             ALOGE("Neither a GSM nor a UMTS cellid (%s:%d).",__FUNCTION__,__LINE__);
    779             return;
    780             break;
    781     }
    782     sAGpsRilInterface->set_ref_location(&location, sizeof(location));
    783 }
    784 
    785 static void android_location_GnssLocationProvider_agps_send_ni_message(JNIEnv* env,
    786         jobject /* obj */, jbyteArray ni_msg, jint size)
    787 {
    788     size_t sz;
    789 
    790     if (!sAGpsRilInterface) {
    791         ALOGE("no AGPS RIL interface in send_ni_message");
    792         return;
    793     }
    794     if (size < 0)
    795         return;
    796     sz = (size_t)size;
    797     jbyte* b = env->GetByteArrayElements(ni_msg, 0);
    798     sAGpsRilInterface->ni_message((uint8_t *)b,sz);
    799     env->ReleaseByteArrayElements(ni_msg,b,0);
    800 }
    801 
    802 static void android_location_GnssLocationProvider_agps_set_id(JNIEnv *env, jobject /* obj */,
    803                                                              jint type, jstring  setid_string)
    804 {
    805     if (!sAGpsRilInterface) {
    806         ALOGE("no AGPS RIL interface in agps_set_id");
    807         return;
    808     }
    809 
    810     const char *setid = env->GetStringUTFChars(setid_string, NULL);
    811     sAGpsRilInterface->set_set_id(type, setid);
    812     env->ReleaseStringUTFChars(setid_string, setid);
    813 }
    814 
    815 static jint android_location_GnssLocationProvider_read_nmea(JNIEnv* env, jobject /* obj */,
    816                                             jbyteArray nmeaArray, jint buffer_size)
    817 {
    818     // this should only be called from within a call to reportNmea
    819     jbyte* nmea = (jbyte *)env->GetPrimitiveArrayCritical(nmeaArray, 0);
    820     int length = sNmeaStringLength;
    821     if (length > buffer_size)
    822         length = buffer_size;
    823     memcpy(nmea, sNmeaString, length);
    824     env->ReleasePrimitiveArrayCritical(nmeaArray, nmea, JNI_ABORT);
    825     return (jint) length;
    826 }
    827 
    828 static void android_location_GnssLocationProvider_inject_time(JNIEnv* /* env */, jobject /* obj */,
    829         jlong time, jlong timeReference, jint uncertainty)
    830 {
    831     if (sGpsInterface)
    832         sGpsInterface->inject_time(time, timeReference, uncertainty);
    833 }
    834 
    835 static void android_location_GnssLocationProvider_inject_location(JNIEnv* /* env */,
    836         jobject /* obj */, jdouble latitude, jdouble longitude, jfloat accuracy)
    837 {
    838     if (sGpsInterface)
    839         sGpsInterface->inject_location(latitude, longitude, accuracy);
    840 }
    841 
    842 static jboolean android_location_GnssLocationProvider_supports_xtra(
    843         JNIEnv* /* env */, jobject /* obj */)
    844 {
    845     return (sGpsXtraInterface != NULL) ? JNI_TRUE : JNI_FALSE;
    846 }
    847 
    848 static void android_location_GnssLocationProvider_inject_xtra_data(JNIEnv* env, jobject /* obj */,
    849         jbyteArray data, jint length)
    850 {
    851     if (!sGpsXtraInterface) {
    852         ALOGE("no XTRA interface in inject_xtra_data");
    853         return;
    854     }
    855 
    856     jbyte* bytes = (jbyte *)env->GetPrimitiveArrayCritical(data, 0);
    857     sGpsXtraInterface->inject_xtra_data((char *)bytes, length);
    858     env->ReleasePrimitiveArrayCritical(data, bytes, JNI_ABORT);
    859 }
    860 
    861 static void android_location_GnssLocationProvider_agps_data_conn_open(
    862         JNIEnv* env, jobject /* obj */, jstring apn, jint apnIpType)
    863 {
    864     if (!sAGpsInterface) {
    865         ALOGE("no AGPS interface in agps_data_conn_open");
    866         return;
    867     }
    868     if (apn == NULL) {
    869         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
    870         return;
    871     }
    872 
    873     const char *apnStr = env->GetStringUTFChars(apn, NULL);
    874 
    875     size_t interface_size = sAGpsInterface->size;
    876     if (interface_size == sizeof(AGpsInterface)) {
    877         sAGpsInterface->data_conn_open_with_apn_ip_type(apnStr, apnIpType);
    878     } else if (interface_size == sizeof(AGpsInterface_v1)) {
    879         sAGpsInterface->data_conn_open(apnStr);
    880     } else {
    881         ALOGE("Invalid size of AGpsInterface found: %zd.", interface_size);
    882     }
    883 
    884     env->ReleaseStringUTFChars(apn, apnStr);
    885 }
    886 
    887 static void android_location_GnssLocationProvider_agps_data_conn_closed(JNIEnv* /* env */,
    888                                                                        jobject /* obj */)
    889 {
    890     if (!sAGpsInterface) {
    891         ALOGE("no AGPS interface in agps_data_conn_closed");
    892         return;
    893     }
    894     sAGpsInterface->data_conn_closed();
    895 }
    896 
    897 static void android_location_GnssLocationProvider_agps_data_conn_failed(JNIEnv* /* env */,
    898                                                                        jobject /* obj */)
    899 {
    900     if (!sAGpsInterface) {
    901         ALOGE("no AGPS interface in agps_data_conn_failed");
    902         return;
    903     }
    904     sAGpsInterface->data_conn_failed();
    905 }
    906 
    907 static void android_location_GnssLocationProvider_set_agps_server(JNIEnv* env, jobject /* obj */,
    908         jint type, jstring hostname, jint port)
    909 {
    910     if (!sAGpsInterface) {
    911         ALOGE("no AGPS interface in set_agps_server");
    912         return;
    913     }
    914     const char *c_hostname = env->GetStringUTFChars(hostname, NULL);
    915     sAGpsInterface->set_server(type, c_hostname, port);
    916     env->ReleaseStringUTFChars(hostname, c_hostname);
    917 }
    918 
    919 static void android_location_GnssLocationProvider_send_ni_response(JNIEnv* /* env */,
    920       jobject /* obj */, jint notifId, jint response)
    921 {
    922     if (!sGpsNiInterface) {
    923         ALOGE("no NI interface in send_ni_response");
    924         return;
    925     }
    926 
    927     sGpsNiInterface->respond(notifId, response);
    928 }
    929 
    930 static jstring android_location_GnssLocationProvider_get_internal_state(JNIEnv* env,
    931                                                                        jobject /* obj */) {
    932     jstring result = NULL;
    933     if (sGpsDebugInterface) {
    934         const size_t maxLength = 2047;
    935         char buffer[maxLength+1];
    936         size_t length = sGpsDebugInterface->get_internal_state(buffer, maxLength);
    937         if (length > maxLength) length = maxLength;
    938         buffer[length] = 0;
    939         result = env->NewStringUTF(buffer);
    940     }
    941     return result;
    942 }
    943 
    944 static void android_location_GnssLocationProvider_update_network_state(JNIEnv* env, jobject /* obj */,
    945         jboolean connected, jint type, jboolean roaming, jboolean available, jstring extraInfo, jstring apn)
    946 {
    947 
    948     if (sAGpsRilInterface && sAGpsRilInterface->update_network_state) {
    949         if (extraInfo) {
    950             const char *extraInfoStr = env->GetStringUTFChars(extraInfo, NULL);
    951             sAGpsRilInterface->update_network_state(connected, type, roaming, extraInfoStr);
    952             env->ReleaseStringUTFChars(extraInfo, extraInfoStr);
    953         } else {
    954             sAGpsRilInterface->update_network_state(connected, type, roaming, NULL);
    955         }
    956 
    957         // update_network_availability callback was not included in original AGpsRilInterface
    958         if (sAGpsRilInterface->size >= sizeof(AGpsRilInterface)
    959                 && sAGpsRilInterface->update_network_availability) {
    960             const char *c_apn = env->GetStringUTFChars(apn, NULL);
    961             sAGpsRilInterface->update_network_availability(available, c_apn);
    962             env->ReleaseStringUTFChars(apn, c_apn);
    963         }
    964     }
    965 }
    966 
    967 static jboolean android_location_GnssLocationProvider_is_geofence_supported(
    968         JNIEnv* /* env */, jobject /* obj */)
    969 {
    970     return (sGpsGeofencingInterface != NULL) ? JNI_TRUE : JNI_FALSE;
    971 }
    972 
    973 static jboolean android_location_GnssLocationProvider_add_geofence(JNIEnv* /* env */,
    974         jobject /* obj */, jint geofence_id, jdouble latitude, jdouble longitude, jdouble radius,
    975         jint last_transition, jint monitor_transition, jint notification_responsiveness,
    976         jint unknown_timer) {
    977     if (sGpsGeofencingInterface != NULL) {
    978         sGpsGeofencingInterface->add_geofence_area(geofence_id, latitude, longitude,
    979                 radius, last_transition, monitor_transition, notification_responsiveness,
    980                 unknown_timer);
    981         return JNI_TRUE;
    982     } else {
    983         ALOGE("Geofence interface not available");
    984     }
    985     return JNI_FALSE;
    986 }
    987 
    988 static jboolean android_location_GnssLocationProvider_remove_geofence(JNIEnv* /* env */,
    989         jobject /* obj */, jint geofence_id) {
    990     if (sGpsGeofencingInterface != NULL) {
    991         sGpsGeofencingInterface->remove_geofence_area(geofence_id);
    992         return JNI_TRUE;
    993     } else {
    994         ALOGE("Geofence interface not available");
    995     }
    996     return JNI_FALSE;
    997 }
    998 
    999 static jboolean android_location_GnssLocationProvider_pause_geofence(JNIEnv* /* env */,
   1000         jobject /* obj */, jint geofence_id) {
   1001     if (sGpsGeofencingInterface != NULL) {
   1002         sGpsGeofencingInterface->pause_geofence(geofence_id);
   1003         return JNI_TRUE;
   1004     } else {
   1005         ALOGE("Geofence interface not available");
   1006     }
   1007     return JNI_FALSE;
   1008 }
   1009 
   1010 static jboolean android_location_GnssLocationProvider_resume_geofence(JNIEnv* /* env */,
   1011         jobject /* obj */, jint geofence_id, jint monitor_transition) {
   1012     if (sGpsGeofencingInterface != NULL) {
   1013         sGpsGeofencingInterface->resume_geofence(geofence_id, monitor_transition);
   1014         return JNI_TRUE;
   1015     } else {
   1016         ALOGE("Geofence interface not available");
   1017     }
   1018     return JNI_FALSE;
   1019 }
   1020 
   1021 template<class T>
   1022 class JavaMethodHelper {
   1023   public:
   1024    // Helper function to call setter on a Java object.
   1025    static void callJavaMethod(
   1026            JNIEnv* env,
   1027            jclass clazz,
   1028            jobject object,
   1029            const char* method_name,
   1030            T value);
   1031 
   1032   private:
   1033     static const char *const signature_;
   1034 };
   1035 
   1036 template<class T>
   1037 void JavaMethodHelper<T>::callJavaMethod(
   1038         JNIEnv* env,
   1039         jclass clazz,
   1040         jobject object,
   1041         const char* method_name,
   1042         T value) {
   1043     jmethodID method = env->GetMethodID(clazz, method_name, signature_);
   1044     env->CallVoidMethod(object, method, value);
   1045 }
   1046 
   1047 class JavaObject {
   1048   public:
   1049    JavaObject(JNIEnv* env, const char* class_name);
   1050    virtual ~JavaObject();
   1051 
   1052    template<class T>
   1053    void callSetter(const char* method_name, T value);
   1054    template<class T>
   1055    void callSetter(const char* method_name, T* value, size_t size);
   1056    jobject get();
   1057 
   1058   private:
   1059    JNIEnv* env_;
   1060    jclass clazz_;
   1061    jobject object_;
   1062 };
   1063 
   1064 JavaObject::JavaObject(JNIEnv* env, const char* class_name) : env_(env) {
   1065     clazz_ = env_->FindClass(class_name);
   1066     jmethodID ctor = env->GetMethodID(clazz_, "<init>", "()V");
   1067     object_ = env_->NewObject(clazz_, ctor);
   1068 }
   1069 
   1070 JavaObject::~JavaObject() {
   1071     env_->DeleteLocalRef(clazz_);
   1072 }
   1073 
   1074 template<class T>
   1075 void JavaObject::callSetter(const char* method_name, T value) {
   1076     JavaMethodHelper<T>::callJavaMethod(
   1077             env_, clazz_, object_, method_name, value);
   1078 }
   1079 
   1080 template<>
   1081 void JavaObject::callSetter(
   1082         const char* method_name, uint8_t* value, size_t size) {
   1083     jbyteArray array = env_->NewByteArray(size);
   1084     env_->SetByteArrayRegion(array, 0, size, (jbyte*) value);
   1085     jmethodID method = env_->GetMethodID(
   1086             clazz_,
   1087             method_name,
   1088             "([B)V");
   1089     env_->CallVoidMethod(object_, method, array);
   1090 }
   1091 
   1092 jobject JavaObject::get() {
   1093     return object_;
   1094 }
   1095 
   1096 // Define Java method signatures for all known types.
   1097 
   1098 template<>
   1099 const char *const JavaMethodHelper<uint8_t>::signature_ = "(B)V";
   1100 template<>
   1101 const char *const JavaMethodHelper<int8_t>::signature_ = "(B)V";
   1102 template<>
   1103 const char *const JavaMethodHelper<int16_t>::signature_ = "(S)V";
   1104 template<>
   1105 const char *const JavaMethodHelper<uint16_t>::signature_ = "(S)V";
   1106 template<>
   1107 const char *const JavaMethodHelper<int32_t>::signature_ = "(I)V";
   1108 template<>
   1109 const char *const JavaMethodHelper<uint32_t>::signature_ = "(I)V";
   1110 template<>
   1111 const char *const JavaMethodHelper<int64_t>::signature_ = "(J)V";
   1112 template<>
   1113 const char *const JavaMethodHelper<float>::signature_ = "(F)V";
   1114 template<>
   1115 const char *const JavaMethodHelper<double>::signature_ = "(D)V";
   1116 template<>
   1117 const char *const JavaMethodHelper<bool>::signature_ = "(Z)V";
   1118 
   1119 #define SET(setter, value) object.callSetter("set" # setter, (value))
   1120 
   1121 // If you want to check if a flag is not set, use SET_IF_NOT(FLAG, setter,
   1122 // value) to do that. SET_IF(!FLAG, setter, value) won't compile.
   1123 //
   1124 // This macros generates compilation error if the provided 'flag' is not a
   1125 // single token. For example, 'GNSS_CLOCK_HAS_BIAS' can be accepted, but
   1126 // '!GNSS_CLOCK_HAS_DRIFT' will fail to compile.
   1127 #define SET_IF(flag, setter, value) do { \
   1128         if (flags & flag) { \
   1129             JavaObject& name_check_##flag = object; \
   1130             name_check_##flag.callSetter("set" # setter, (value)); \
   1131         } \
   1132     } while (false)
   1133 #define SET_IF_NOT(flag, setter, value) do { \
   1134         if (!(flags & flag)) { \
   1135             JavaObject& name_check_##flag = object; \
   1136             name_check_##flag.callSetter("set" # setter, (value)); \
   1137         } \
   1138     } while (false)
   1139 
   1140 static jobject translate_gps_clock(JNIEnv* env, GpsClock* clock) {
   1141     static uint32_t discontinuity_count_to_handle_old_clock_type = 0;
   1142     JavaObject object(env, "android/location/GnssClock");
   1143     GpsClockFlags flags = clock->flags;
   1144 
   1145     SET_IF(GPS_CLOCK_HAS_LEAP_SECOND,
   1146            LeapSecond,
   1147            static_cast<int32_t>(clock->leap_second));
   1148 
   1149     // GnssClock only supports the more effective HW_CLOCK type, so type
   1150     // handling and documentation complexity has been removed.  To convert the
   1151     // old GPS_CLOCK types (active only in a limited number of older devices),
   1152     // the GPS time information is handled as an always discontinuous HW clock,
   1153     // with the GPS time information put into the full_bias_ns instead - so that
   1154     // time_ns - full_bias_ns = local estimate of GPS time. Additionally, the
   1155     // sign of full_bias_ns and bias_ns has flipped between GpsClock &
   1156     // GnssClock, so that is also handled below.
   1157     switch (clock->type) {
   1158       case GPS_CLOCK_TYPE_UNKNOWN:
   1159         // Clock type unsupported.
   1160         ALOGE("Unknown clock type provided.");
   1161         break;
   1162       case GPS_CLOCK_TYPE_LOCAL_HW_TIME:
   1163         // Already local hardware time. No need to do anything.
   1164         break;
   1165       case GPS_CLOCK_TYPE_GPS_TIME:
   1166         // GPS time, need to convert.
   1167         flags |= GPS_CLOCK_HAS_FULL_BIAS;
   1168         clock->full_bias_ns = clock->time_ns;
   1169         clock->time_ns = 0;
   1170         SET(HardwareClockDiscontinuityCount,
   1171             discontinuity_count_to_handle_old_clock_type++);
   1172         break;
   1173     }
   1174 
   1175     SET(TimeNanos, clock->time_ns);
   1176     SET_IF(GPS_CLOCK_HAS_TIME_UNCERTAINTY,
   1177            TimeUncertaintyNanos,
   1178            clock->time_uncertainty_ns);
   1179 
   1180     // Definition of sign for full_bias_ns & bias_ns has been changed since N,
   1181     // so flip signs here.
   1182     SET_IF(GPS_CLOCK_HAS_FULL_BIAS, FullBiasNanos, -(clock->full_bias_ns));
   1183     SET_IF(GPS_CLOCK_HAS_BIAS, BiasNanos, -(clock->bias_ns));
   1184 
   1185     SET_IF(GPS_CLOCK_HAS_BIAS_UNCERTAINTY,
   1186            BiasUncertaintyNanos,
   1187            clock->bias_uncertainty_ns);
   1188     SET_IF(GPS_CLOCK_HAS_DRIFT, DriftNanosPerSecond, clock->drift_nsps);
   1189     SET_IF(GPS_CLOCK_HAS_DRIFT_UNCERTAINTY,
   1190            DriftUncertaintyNanosPerSecond,
   1191            clock->drift_uncertainty_nsps);
   1192 
   1193     return object.get();
   1194 }
   1195 
   1196 static jobject translate_gnss_clock(JNIEnv* env, GnssClock* clock) {
   1197     JavaObject object(env, "android/location/GnssClock");
   1198     GnssClockFlags flags = clock->flags;
   1199 
   1200     SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND,
   1201            LeapSecond,
   1202            static_cast<int32_t>(clock->leap_second));
   1203     SET(TimeNanos, clock->time_ns);
   1204     SET_IF(GNSS_CLOCK_HAS_TIME_UNCERTAINTY,
   1205            TimeUncertaintyNanos,
   1206            clock->time_uncertainty_ns);
   1207     SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasNanos, clock->full_bias_ns);
   1208     SET_IF(GNSS_CLOCK_HAS_BIAS, BiasNanos, clock->bias_ns);
   1209     SET_IF(GNSS_CLOCK_HAS_BIAS_UNCERTAINTY,
   1210            BiasUncertaintyNanos,
   1211            clock->bias_uncertainty_ns);
   1212     SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftNanosPerSecond, clock->drift_nsps);
   1213     SET_IF(GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY,
   1214            DriftUncertaintyNanosPerSecond,
   1215            clock->drift_uncertainty_nsps);
   1216 
   1217     SET(HardwareClockDiscontinuityCount, clock->hw_clock_discontinuity_count);
   1218 
   1219     return object.get();
   1220 }
   1221 
   1222 static jobject translate_gps_measurement(JNIEnv* env,
   1223                                          GpsMeasurement* measurement) {
   1224     JavaObject object(env, "android/location/GnssMeasurement");
   1225     GpsMeasurementFlags flags = measurement->flags;
   1226     SET(Svid, static_cast<int32_t>(measurement->prn));
   1227     if (measurement->prn >= 1 && measurement->prn <= 32) {
   1228         SET(ConstellationType, static_cast<int32_t>(GNSS_CONSTELLATION_GPS));
   1229     } else {
   1230         ALOGD("Unknown constellation type with Svid = %d.", measurement->prn);
   1231         SET(ConstellationType,
   1232             static_cast<int32_t>(GNSS_CONSTELLATION_UNKNOWN));
   1233     }
   1234     SET(TimeOffsetNanos, measurement->time_offset_ns);
   1235     SET(State, static_cast<int32_t>(measurement->state));
   1236     SET(ReceivedSvTimeNanos, measurement->received_gps_tow_ns);
   1237     SET(ReceivedSvTimeUncertaintyNanos,
   1238         measurement->received_gps_tow_uncertainty_ns);
   1239     SET(Cn0DbHz, measurement->c_n0_dbhz);
   1240     SET(PseudorangeRateMetersPerSecond, measurement->pseudorange_rate_mps);
   1241     SET(PseudorangeRateUncertaintyMetersPerSecond,
   1242         measurement->pseudorange_rate_uncertainty_mps);
   1243     SET(AccumulatedDeltaRangeState,
   1244         static_cast<int32_t>(measurement->accumulated_delta_range_state));
   1245     SET(AccumulatedDeltaRangeMeters, measurement->accumulated_delta_range_m);
   1246     SET(AccumulatedDeltaRangeUncertaintyMeters,
   1247         measurement->accumulated_delta_range_uncertainty_m);
   1248     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
   1249            CarrierFrequencyHz,
   1250            measurement->carrier_frequency_hz);
   1251     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
   1252            CarrierCycles,
   1253            measurement->carrier_cycles);
   1254     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE,
   1255            CarrierPhase,
   1256            measurement->carrier_phase);
   1257     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
   1258            CarrierPhaseUncertainty,
   1259            measurement->carrier_phase_uncertainty);
   1260     SET(MultipathIndicator,
   1261         static_cast<int32_t>(measurement->multipath_indicator));
   1262     SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
   1263 
   1264     return object.get();
   1265 }
   1266 
   1267 static jobject translate_gnss_measurement(JNIEnv* env,
   1268                                           GnssMeasurement* measurement) {
   1269     JavaObject object(env, "android/location/GnssMeasurement");
   1270 
   1271     GnssMeasurementFlags flags = measurement->flags;
   1272 
   1273     SET(Svid, static_cast<int32_t>(measurement->svid));
   1274     SET(ConstellationType, static_cast<int32_t>(measurement->constellation));
   1275     SET(TimeOffsetNanos, measurement->time_offset_ns);
   1276     SET(State, static_cast<int32_t>(measurement->state));
   1277     SET(ReceivedSvTimeNanos, measurement->received_sv_time_in_ns);
   1278     SET(ReceivedSvTimeUncertaintyNanos,
   1279         measurement->received_sv_time_uncertainty_in_ns);
   1280     SET(Cn0DbHz, measurement->c_n0_dbhz);
   1281     SET(PseudorangeRateMetersPerSecond, measurement->pseudorange_rate_mps);
   1282     SET(PseudorangeRateUncertaintyMetersPerSecond,
   1283         measurement->pseudorange_rate_uncertainty_mps);
   1284     SET(AccumulatedDeltaRangeState,
   1285         static_cast<int32_t>(measurement->accumulated_delta_range_state));
   1286     SET(AccumulatedDeltaRangeMeters, measurement->accumulated_delta_range_m);
   1287     SET(AccumulatedDeltaRangeUncertaintyMeters,
   1288         measurement->accumulated_delta_range_uncertainty_m);
   1289     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
   1290            CarrierFrequencyHz,
   1291            measurement->carrier_frequency_hz);
   1292     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
   1293            CarrierCycles,
   1294            measurement->carrier_cycles);
   1295     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE,
   1296            CarrierPhase,
   1297            measurement->carrier_phase);
   1298     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
   1299            CarrierPhaseUncertainty,
   1300            measurement->carrier_phase_uncertainty);
   1301     SET(MultipathIndicator,
   1302         static_cast<int32_t>(measurement->multipath_indicator));
   1303     SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
   1304 
   1305     return object.get();
   1306 }
   1307 
   1308 static jobjectArray translate_gps_measurements(JNIEnv* env,
   1309                                                GpsMeasurement* measurements,
   1310                                                size_t count) {
   1311     if (count == 0) {
   1312         return NULL;
   1313     }
   1314 
   1315     jclass gnssMeasurementClass = env->FindClass(
   1316             "android/location/GnssMeasurement");
   1317     jobjectArray gnssMeasurementArray = env->NewObjectArray(
   1318             count,
   1319             gnssMeasurementClass,
   1320             NULL /* initialElement */);
   1321 
   1322     for (uint16_t i = 0; i < count; ++i) {
   1323         jobject gnssMeasurement = translate_gps_measurement(
   1324             env,
   1325             &measurements[i]);
   1326         env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
   1327         env->DeleteLocalRef(gnssMeasurement);
   1328     }
   1329 
   1330     env->DeleteLocalRef(gnssMeasurementClass);
   1331     return gnssMeasurementArray;
   1332 }
   1333 
   1334 static jobjectArray translate_gnss_measurements(JNIEnv* env,
   1335                                                 GnssMeasurement* measurements,
   1336                                                 size_t count) {
   1337     if (count == 0) {
   1338         return NULL;
   1339     }
   1340 
   1341     jclass gnssMeasurementClass = env->FindClass(
   1342             "android/location/GnssMeasurement");
   1343     jobjectArray gnssMeasurementArray = env->NewObjectArray(
   1344             count,
   1345             gnssMeasurementClass,
   1346             NULL /* initialElement */);
   1347 
   1348     for (uint16_t i = 0; i < count; ++i) {
   1349         jobject gnssMeasurement = translate_gnss_measurement(
   1350             env,
   1351             &measurements[i]);
   1352         env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
   1353         env->DeleteLocalRef(gnssMeasurement);
   1354     }
   1355 
   1356     env->DeleteLocalRef(gnssMeasurementClass);
   1357     return gnssMeasurementArray;
   1358 }
   1359 
   1360 static void set_measurement_data(JNIEnv *env,
   1361                                  jobject clock,
   1362                                  jobjectArray measurementArray) {
   1363     jclass gnssMeasurementsEventClass = env->FindClass(
   1364             "android/location/GnssMeasurementsEvent");
   1365     jmethodID gnssMeasurementsEventCtor = env->GetMethodID(
   1366         gnssMeasurementsEventClass,
   1367         "<init>",
   1368         "(Landroid/location/GnssClock;[Landroid/location/GnssMeasurement;)V");
   1369 
   1370     jobject gnssMeasurementsEvent = env->NewObject(
   1371         gnssMeasurementsEventClass,
   1372         gnssMeasurementsEventCtor,
   1373         clock,
   1374         measurementArray);
   1375     env->CallVoidMethod(mCallbacksObj,
   1376                         method_reportMeasurementData,
   1377                         gnssMeasurementsEvent);
   1378     checkAndClearExceptionFromCallback(env, __FUNCTION__);
   1379     env->DeleteLocalRef(gnssMeasurementsEventClass);
   1380     env->DeleteLocalRef(gnssMeasurementsEvent);
   1381 }
   1382 
   1383 static void measurement_callback(GpsData* data) {
   1384     JNIEnv* env = AndroidRuntime::getJNIEnv();
   1385     if (data == NULL) {
   1386         ALOGE("Invalid data provided to gps_measurement_callback");
   1387         return;
   1388     }
   1389     if (data->size != sizeof(GpsData)) {
   1390         ALOGE("Invalid GpsData size found in gps_measurement_callback, "
   1391               "size=%zd",
   1392               data->size);
   1393         return;
   1394     }
   1395 
   1396     jobject clock;
   1397     jobjectArray measurementArray;
   1398     clock = translate_gps_clock(env, &data->clock);
   1399     measurementArray = translate_gps_measurements(
   1400             env, data->measurements, data->measurement_count);
   1401     set_measurement_data(env, clock, measurementArray);
   1402 
   1403     env->DeleteLocalRef(clock);
   1404     env->DeleteLocalRef(measurementArray);
   1405 }
   1406 
   1407 static void gnss_measurement_callback(GnssData* data) {
   1408     JNIEnv* env = AndroidRuntime::getJNIEnv();
   1409     if (data == NULL) {
   1410         ALOGE("Invalid data provided to gps_measurement_callback");
   1411         return;
   1412     }
   1413     if (data->size != sizeof(GnssData)) {
   1414         ALOGE("Invalid GnssData size found in gnss_measurement_callback, "
   1415               "size=%zd",
   1416               data->size);
   1417         return;
   1418     }
   1419 
   1420     jobject clock;
   1421     jobjectArray measurementArray;
   1422     clock = translate_gnss_clock(env, &data->clock);
   1423     measurementArray = translate_gnss_measurements(
   1424             env, data->measurements, data->measurement_count);
   1425     set_measurement_data(env, clock, measurementArray);
   1426 
   1427     env->DeleteLocalRef(clock);
   1428     env->DeleteLocalRef(measurementArray);
   1429 }
   1430 
   1431 GpsMeasurementCallbacks sGpsMeasurementCallbacks = {
   1432     sizeof(GpsMeasurementCallbacks),
   1433     measurement_callback,
   1434     gnss_measurement_callback,
   1435 };
   1436 
   1437 static jboolean android_location_GnssLocationProvider_is_measurement_supported(
   1438         JNIEnv* env,
   1439         jclass clazz) {
   1440     if (sGpsMeasurementInterface != NULL) {
   1441         return JNI_TRUE;
   1442     }
   1443     return JNI_FALSE;
   1444 }
   1445 
   1446 static jboolean android_location_GnssLocationProvider_start_measurement_collection(
   1447         JNIEnv* env,
   1448         jobject obj) {
   1449     if (sGpsMeasurementInterface == NULL) {
   1450         ALOGE("Measurement interface is not available.");
   1451         return JNI_FALSE;
   1452     }
   1453 
   1454     int result = sGpsMeasurementInterface->init(&sGpsMeasurementCallbacks);
   1455     if (result != GPS_GEOFENCE_OPERATION_SUCCESS) {
   1456         ALOGE("An error has been found on GpsMeasurementInterface::init, status=%d", result);
   1457         return JNI_FALSE;
   1458     }
   1459 
   1460     return JNI_TRUE;
   1461 }
   1462 
   1463 static jboolean android_location_GnssLocationProvider_stop_measurement_collection(
   1464         JNIEnv* env,
   1465         jobject obj) {
   1466     if (sGpsMeasurementInterface == NULL) {
   1467         ALOGE("Measurement interface not available");
   1468         return JNI_FALSE;
   1469     }
   1470 
   1471     sGpsMeasurementInterface->close();
   1472     return JNI_TRUE;
   1473 }
   1474 
   1475 static jobject translate_gps_navigation_message(JNIEnv* env, GpsNavigationMessage* message) {
   1476     size_t dataLength = message->data_length;
   1477     uint8_t* data = message->data;
   1478     if (dataLength == 0 || data == NULL) {
   1479         ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
   1480         return NULL;
   1481     }
   1482     JavaObject object(env, "android/location/GnssNavigationMessage");
   1483     SET(Svid, static_cast<int32_t>(message->prn));
   1484     if (message->prn >=1 && message->prn <= 32) {
   1485         SET(ConstellationType, static_cast<int32_t>(GNSS_CONSTELLATION_GPS));
   1486         // Legacy driver doesn't set the higher byte to constellation type
   1487         // correctly. Set the higher byte to 'GPS'.
   1488         SET(Type, static_cast<int32_t>(message->type | 0x0100));
   1489     } else {
   1490         ALOGD("Unknown constellation type with Svid = %d.", message->prn);
   1491         SET(ConstellationType,
   1492             static_cast<int32_t>(GNSS_CONSTELLATION_UNKNOWN));
   1493         SET(Type, static_cast<int32_t>(GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN));
   1494     }
   1495     SET(MessageId, static_cast<int32_t>(message->message_id));
   1496     SET(SubmessageId, static_cast<int32_t>(message->submessage_id));
   1497     object.callSetter("setData", data, dataLength);
   1498     SET(Status, static_cast<int32_t>(message->status));
   1499     return object.get();
   1500 }
   1501 
   1502 static jobject translate_gnss_navigation_message(
   1503         JNIEnv* env, GnssNavigationMessage* message) {
   1504     size_t dataLength = message->data_length;
   1505     uint8_t* data = message->data;
   1506     if (dataLength == 0 || data == NULL) {
   1507         ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
   1508         return NULL;
   1509     }
   1510     JavaObject object(env, "android/location/GnssNavigationMessage");
   1511     SET(Type, static_cast<int32_t>(message->type));
   1512     SET(Svid, static_cast<int32_t>(message->svid));
   1513     SET(MessageId, static_cast<int32_t>(message->message_id));
   1514     SET(SubmessageId, static_cast<int32_t>(message->submessage_id));
   1515     object.callSetter("setData", data, dataLength);
   1516     SET(Status, static_cast<int32_t>(message->status));
   1517     return object.get();
   1518 }
   1519 
   1520 static void navigation_message_callback(GpsNavigationMessage* message) {
   1521     if (message == NULL) {
   1522         ALOGE("Invalid Navigation Message provided to callback");
   1523         return;
   1524     }
   1525     if (message->size != sizeof(GpsNavigationMessage)) {
   1526         ALOGE("Invalid GpsNavigationMessage size found: %zd", message->size);
   1527         return;
   1528     }
   1529     JNIEnv* env = AndroidRuntime::getJNIEnv();
   1530     jobject navigationMessage = translate_gps_navigation_message(env, message);
   1531     env->CallVoidMethod(mCallbacksObj,
   1532                         method_reportNavigationMessages,
   1533                         navigationMessage);
   1534     env->DeleteLocalRef(navigationMessage);
   1535 }
   1536 
   1537 static void gnss_navigation_message_callback(GnssNavigationMessage* message) {
   1538     if (message == NULL) {
   1539         ALOGE("Invalid Navigation Message provided to callback");
   1540         return;
   1541     }
   1542     if (message->size != sizeof(GnssNavigationMessage)) {
   1543         ALOGE("Invalid GnssNavigationMessage size found: %zd", message->size);
   1544         return;
   1545     }
   1546     JNIEnv* env = AndroidRuntime::getJNIEnv();
   1547     jobject navigationMessage = translate_gnss_navigation_message(env, message);
   1548     env->CallVoidMethod(mCallbacksObj,
   1549                         method_reportNavigationMessages,
   1550                         navigationMessage);
   1551     env->DeleteLocalRef(navigationMessage);
   1552 }
   1553 
   1554 GpsNavigationMessageCallbacks sGpsNavigationMessageCallbacks = {
   1555     sizeof(GpsNavigationMessageCallbacks),
   1556     navigation_message_callback,
   1557     gnss_navigation_message_callback,
   1558 };
   1559 
   1560 static jboolean android_location_GnssLocationProvider_is_navigation_message_supported(
   1561         JNIEnv* env,
   1562         jclass clazz) {
   1563     if(sGpsNavigationMessageInterface != NULL) {
   1564         return JNI_TRUE;
   1565     }
   1566     return JNI_FALSE;
   1567 }
   1568 
   1569 static jboolean android_location_GnssLocationProvider_start_navigation_message_collection(
   1570         JNIEnv* env,
   1571         jobject obj) {
   1572     if (sGpsNavigationMessageInterface == NULL) {
   1573         ALOGE("Navigation Message interface is not available.");
   1574         return JNI_FALSE;
   1575     }
   1576 
   1577     int result = sGpsNavigationMessageInterface->init(&sGpsNavigationMessageCallbacks);
   1578     if (result != GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS) {
   1579         ALOGE("An error has been found in %s: %d", __FUNCTION__, result);
   1580         return JNI_FALSE;
   1581     }
   1582 
   1583     return JNI_TRUE;
   1584 }
   1585 
   1586 static jboolean android_location_GnssLocationProvider_stop_navigation_message_collection(
   1587         JNIEnv* env,
   1588         jobject obj) {
   1589     if (sGpsNavigationMessageInterface == NULL) {
   1590         ALOGE("Navigation Message interface is not available.");
   1591         return JNI_FALSE;
   1592     }
   1593 
   1594     sGpsNavigationMessageInterface->close();
   1595     return JNI_TRUE;
   1596 }
   1597 
   1598 static void android_location_GnssLocationProvider_configuration_update(JNIEnv* env, jobject obj,
   1599         jstring config_content)
   1600 {
   1601     if (!sGnssConfigurationInterface) {
   1602         ALOGE("no GPS configuration interface in configuraiton_update");
   1603         return;
   1604     }
   1605     const char *data = env->GetStringUTFChars(config_content, NULL);
   1606     ALOGD("GPS configuration:\n %s", data);
   1607     sGnssConfigurationInterface->configuration_update(
   1608             data, env->GetStringUTFLength(config_content));
   1609     env->ReleaseStringUTFChars(config_content, data);
   1610 }
   1611 
   1612 static const JNINativeMethod sMethods[] = {
   1613      /* name, signature, funcPtr */
   1614     {"class_init_native", "()V", (void *)android_location_GnssLocationProvider_class_init_native},
   1615     {"native_is_supported", "()Z", (void*)android_location_GnssLocationProvider_is_supported},
   1616     {"native_is_agps_ril_supported", "()Z",
   1617             (void*)android_location_GnssLocationProvider_is_agps_ril_supported},
   1618     {"native_is_gnss_configuration_supported", "()Z",
   1619             (void*)android_location_gpsLocationProvider_is_gnss_configuration_supported},
   1620     {"native_init", "()Z", (void*)android_location_GnssLocationProvider_init},
   1621     {"native_cleanup", "()V", (void*)android_location_GnssLocationProvider_cleanup},
   1622     {"native_set_position_mode",
   1623             "(IIIII)Z",
   1624             (void*)android_location_GnssLocationProvider_set_position_mode},
   1625     {"native_start", "()Z", (void*)android_location_GnssLocationProvider_start},
   1626     {"native_stop", "()Z", (void*)android_location_GnssLocationProvider_stop},
   1627     {"native_delete_aiding_data",
   1628             "(I)V",
   1629             (void*)android_location_GnssLocationProvider_delete_aiding_data},
   1630     {"native_read_sv_status",
   1631             "([I[F[F[F)I",
   1632             (void*)android_location_GnssLocationProvider_read_sv_status},
   1633     {"native_read_nmea", "([BI)I", (void*)android_location_GnssLocationProvider_read_nmea},
   1634     {"native_inject_time", "(JJI)V", (void*)android_location_GnssLocationProvider_inject_time},
   1635     {"native_inject_location",
   1636             "(DDF)V",
   1637             (void*)android_location_GnssLocationProvider_inject_location},
   1638     {"native_supports_xtra", "()Z", (void*)android_location_GnssLocationProvider_supports_xtra},
   1639     {"native_inject_xtra_data",
   1640             "([BI)V",
   1641             (void*)android_location_GnssLocationProvider_inject_xtra_data},
   1642     {"native_agps_data_conn_open",
   1643             "(Ljava/lang/String;I)V",
   1644             (void*)android_location_GnssLocationProvider_agps_data_conn_open},
   1645     {"native_agps_data_conn_closed",
   1646             "()V",
   1647             (void*)android_location_GnssLocationProvider_agps_data_conn_closed},
   1648     {"native_agps_data_conn_failed",
   1649             "()V",
   1650             (void*)android_location_GnssLocationProvider_agps_data_conn_failed},
   1651     {"native_agps_set_id",
   1652             "(ILjava/lang/String;)V",
   1653             (void*)android_location_GnssLocationProvider_agps_set_id},
   1654     {"native_agps_set_ref_location_cellid",
   1655             "(IIIII)V",
   1656             (void*)android_location_GnssLocationProvider_agps_set_reference_location_cellid},
   1657     {"native_set_agps_server",
   1658             "(ILjava/lang/String;I)V",
   1659             (void*)android_location_GnssLocationProvider_set_agps_server},
   1660     {"native_send_ni_response",
   1661             "(II)V",
   1662             (void*)android_location_GnssLocationProvider_send_ni_response},
   1663     {"native_agps_ni_message",
   1664             "([BI)V",
   1665             (void *)android_location_GnssLocationProvider_agps_send_ni_message},
   1666     {"native_get_internal_state",
   1667             "()Ljava/lang/String;",
   1668             (void*)android_location_GnssLocationProvider_get_internal_state},
   1669     {"native_update_network_state",
   1670             "(ZIZZLjava/lang/String;Ljava/lang/String;)V",
   1671             (void*)android_location_GnssLocationProvider_update_network_state },
   1672     {"native_is_geofence_supported",
   1673             "()Z",
   1674             (void*) android_location_GnssLocationProvider_is_geofence_supported},
   1675     {"native_add_geofence",
   1676             "(IDDDIIII)Z",
   1677             (void *)android_location_GnssLocationProvider_add_geofence},
   1678     {"native_remove_geofence",
   1679             "(I)Z",
   1680             (void *)android_location_GnssLocationProvider_remove_geofence},
   1681     {"native_pause_geofence", "(I)Z", (void *)android_location_GnssLocationProvider_pause_geofence},
   1682     {"native_resume_geofence",
   1683             "(II)Z",
   1684             (void *)android_location_GnssLocationProvider_resume_geofence},
   1685     {"native_is_measurement_supported",
   1686             "()Z",
   1687             (void*) android_location_GnssLocationProvider_is_measurement_supported},
   1688     {"native_start_measurement_collection",
   1689             "()Z",
   1690             (void*) android_location_GnssLocationProvider_start_measurement_collection},
   1691     {"native_stop_measurement_collection",
   1692             "()Z",
   1693             (void*) android_location_GnssLocationProvider_stop_measurement_collection},
   1694     {"native_is_navigation_message_supported",
   1695             "()Z",
   1696             (void*) android_location_GnssLocationProvider_is_navigation_message_supported},
   1697     {"native_start_navigation_message_collection",
   1698             "()Z",
   1699             (void*) android_location_GnssLocationProvider_start_navigation_message_collection},
   1700     {"native_stop_navigation_message_collection",
   1701             "()Z",
   1702             (void*) android_location_GnssLocationProvider_stop_navigation_message_collection},
   1703     {"native_configuration_update",
   1704             "(Ljava/lang/String;)V",
   1705             (void*)android_location_GnssLocationProvider_configuration_update},
   1706 };
   1707 
   1708 int register_android_server_location_GnssLocationProvider(JNIEnv* env)
   1709 {
   1710     return jniRegisterNativeMethods(
   1711             env,
   1712             "com/android/server/location/GnssLocationProvider",
   1713             sMethods,
   1714             NELEM(sMethods));
   1715 }
   1716 
   1717 } /* namespace android */
   1718