Modify GnssLocationProvider to use Treble Gnss HAL

Test: GPS functionality tested in binderized and pass-through modes on
Angler. All interfaces except AGnssRil, GnssNavigationMessage and
GnssNi. AGnssRil and AGnssNavigationMessage are not implemented by conventional
GPS HALs in Google devices that would be upgrading to O.

Change-Id: Ie4decb4c47892725c8c89bad3f48581550facff7
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 25e819c..b0a4297 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -18,10 +18,13 @@
 
 #define LOG_NDEBUG 0
 
+#include <android/hardware/gnss/1.0/IGnss.h>
+
+#include <hwbinder/IPCThreadState.h>
+#include <hwbinder/ProcessState.h>
+
 #include "JNIHelp.h"
 #include "jni.h"
-#include "hardware/hardware.h"
-#include "hardware/gps_internal.h"
 #include "hardware_legacy/power.h"
 #include "utils/Log.h"
 #include "utils/misc.h"
@@ -34,6 +37,7 @@
 #include <linux/in6.h>
 #include <pthread.h>
 #include <string.h>
+#include <cinttypes>
 
 static jobject mCallbacksObj = NULL;
 
@@ -58,978 +62,65 @@
 static jmethodID method_reportMeasurementData;
 static jmethodID method_reportNavigationMessages;
 
-static const GpsInterface* sGpsInterface = NULL;
-static const GpsXtraInterface* sGpsXtraInterface = NULL;
-static const AGpsInterface* sAGpsInterface = NULL;
-static const GpsNiInterface* sGpsNiInterface = NULL;
-static const GpsDebugInterface* sGpsDebugInterface = NULL;
-static const AGpsRilInterface* sAGpsRilInterface = NULL;
-static const GpsGeofencingInterface* sGpsGeofencingInterface = NULL;
-static const GpsMeasurementInterface* sGpsMeasurementInterface = NULL;
-static const GpsNavigationMessageInterface* sGpsNavigationMessageInterface = NULL;
-static const GnssConfigurationInterface* sGnssConfigurationInterface = NULL;
+using android::OK;
+using android::sp;
+using android::status_t;
+using android::String16;
 
-#define GPS_MAX_SATELLITE_COUNT 32
-#define GNSS_MAX_SATELLITE_COUNT 64
+using android::hardware::IPCThreadState;
+using android::hardware::ProcessState;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::hidl_vec;
 
-// Let these through, with ID remapped down to 1, 2... by offset
-#define GLONASS_SVID_OFFSET 64
-#define GLONASS_SVID_COUNT 24
-#define BEIDOU_SVID_OFFSET 200
-#define BEIDOU_SVID_COUNT 35
+using android::hardware::gnss::V1_0::IAGnss;
+using android::hardware::gnss::V1_0::IAGnssCallback;
+using android::hardware::gnss::V1_0::IAGnssCallback;
+using android::hardware::gnss::V1_0::IAGnssRil;
+using android::hardware::gnss::V1_0::IAGnssRilCallback;
+using android::hardware::gnss::V1_0::IGnss;
+using android::hardware::gnss::V1_0::IGnssCallback;
+using android::hardware::gnss::V1_0::IGnssConfiguration;
+using android::hardware::gnss::V1_0::IGnssDebug;
+using android::hardware::gnss::V1_0::IGnssGeofenceCallback;
+using android::hardware::gnss::V1_0::IGnssGeofencing;
+using android::hardware::gnss::V1_0::IGnssMeasurement;
+using android::hardware::gnss::V1_0::IGnssMeasurementCallback;
+using android::hardware::gnss::V1_0::IGnssNavigationMessage;
+using android::hardware::gnss::V1_0::IGnssNavigationMessageCallback;
+using android::hardware::gnss::V1_0::IGnssNi;
+using android::hardware::gnss::V1_0::IGnssNiCallback;
+using android::hardware::gnss::V1_0::IGnssXtra;
+using android::hardware::gnss::V1_0::IGnssXtraCallback;
 
-// Let these through, with ID remapped up (33->120 ... 64->151, etc.)
-#define SBAS_SVID_MIN 33
-#define SBAS_SVID_MAX 64
-#define SBAS_SVID_ADD 87
 
-// Let these through, with no ID remapping
-#define QZSS_SVID_MIN 193
-#define QZSS_SVID_MAX 200
-
-#define SVID_SHIFT_WIDTH 7
-#define CONSTELLATION_TYPE_SHIFT_WIDTH 3
-
-// temporary storage for GPS callbacks
-static GnssSvInfo sGnssSvList[GNSS_MAX_SATELLITE_COUNT];
-static size_t sGnssSvListSize;
-static const char* sNmeaString;
-static int sNmeaStringLength;
+sp<IGnss> gnssHal = nullptr;
+sp<IGnssXtra> gnssXtraIface = nullptr;
+sp<IAGnssRil> agnssRilIface = nullptr;
+sp<IGnssGeofencing> gnssGeofencingIface = nullptr;
+sp<IAGnss> agnssIface = nullptr;
+sp<IGnssDebug> gnssDebugIface = nullptr;
+sp<IGnssConfiguration> gnssConfigurationIface = nullptr;
+sp<IGnssNi> gnssNiIface = nullptr;
+sp<IGnssMeasurement> gnssMeasurementIface = nullptr;
+sp<IGnssNavigationMessage> gnssNavigationMessageIface = nullptr;
 
 #define WAKE_LOCK_NAME  "GPS"
 
 namespace android {
 
-static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
-    if (env->ExceptionCheck()) {
-        ALOGE("An exception was thrown by callback '%s'.", methodName);
-        LOGE_EX(env);
-        env->ExceptionClear();
-    }
-}
-
-static void location_callback(GpsLocation* location)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(mCallbacksObj, method_reportLocation, location->flags,
-            (jdouble)location->latitude, (jdouble)location->longitude,
-            (jdouble)location->altitude,
-            (jfloat)location->speed, (jfloat)location->bearing,
-            (jfloat)location->accuracy, (jlong)location->timestamp);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void status_callback(GpsStatus* status)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(mCallbacksObj, method_reportStatus, status->status);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void sv_status_callback(GpsSvStatus* sv_status)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    size_t status_size = sv_status->size;
-    // Some drives doesn't set the size field correctly. Assume GpsSvStatus_v1
-    // if it doesn't provide a valid size.
-    if (status_size == 0) {
-        ALOGW("Invalid size of GpsSvStatus found: %zd.", status_size);
-    }
-    sGnssSvListSize = sv_status->num_svs;
-    // Clamp the list size. Legacy GpsSvStatus has only 32 elements in sv_list.
-    if (sGnssSvListSize > GPS_MAX_SATELLITE_COUNT) {
-        ALOGW("Too many satellites %zd. Clamps to %d.",
-              sGnssSvListSize,
-              GPS_MAX_SATELLITE_COUNT);
-        sGnssSvListSize = GPS_MAX_SATELLITE_COUNT;
-    }
-    uint32_t ephemeris_mask = sv_status->ephemeris_mask;
-    uint32_t almanac_mask = sv_status->almanac_mask;
-    uint32_t used_in_fix_mask = sv_status->used_in_fix_mask;
-    for (size_t i = 0; i < sGnssSvListSize; i++) {
-        GnssSvInfo& info = sGnssSvList[i];
-        info.svid = sv_status->sv_list[i].prn;
-        // Defacto mapping from the overused API that was designed for GPS-only
-        if (info.svid >=1 && info.svid <= 32) {
-            info.constellation = GNSS_CONSTELLATION_GPS;
-        } else if (info.svid > GLONASS_SVID_OFFSET &&
-                   info.svid <= GLONASS_SVID_OFFSET + GLONASS_SVID_COUNT) {
-            info.constellation = GNSS_CONSTELLATION_GLONASS;
-            info.svid -= GLONASS_SVID_OFFSET;
-        } else if (info.svid > BEIDOU_SVID_OFFSET &&
-                   info.svid <= BEIDOU_SVID_OFFSET + BEIDOU_SVID_COUNT) {
-            info.constellation = GNSS_CONSTELLATION_BEIDOU;
-            info.svid -= BEIDOU_SVID_OFFSET;
-        } else if (info.svid >= SBAS_SVID_MIN && info.svid <= SBAS_SVID_MAX) {
-            info.constellation = GNSS_CONSTELLATION_SBAS;
-            info.svid += SBAS_SVID_ADD;
-        } else if (info.svid >= QZSS_SVID_MIN && info.svid <= QZSS_SVID_MAX) {
-            info.constellation = GNSS_CONSTELLATION_QZSS;
-        } else {
-            ALOGD("Unknown constellation type with Svid = %d.", info.svid);
-            info.constellation = GNSS_CONSTELLATION_UNKNOWN;
-        }
-        info.c_n0_dbhz = sv_status->sv_list[i].snr;
-        info.elevation = sv_status->sv_list[i].elevation;
-        info.azimuth = sv_status->sv_list[i].azimuth;
-        info.flags = GNSS_SV_FLAGS_NONE;
-        // Only GPS info is valid for these fields, as these masks are just 32 bits, by GPS prn
-        if (info.constellation == GNSS_CONSTELLATION_GPS) {
-            int32_t this_svid_mask = (1 << (info.svid - 1));
-            if ((ephemeris_mask & this_svid_mask) != 0) {
-                info.flags |= GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA;
-            }
-            if ((almanac_mask & this_svid_mask) != 0) {
-                info.flags |= GNSS_SV_FLAGS_HAS_ALMANAC_DATA;
-            }
-            if ((used_in_fix_mask & this_svid_mask) != 0) {
-                info.flags |= GNSS_SV_FLAGS_USED_IN_FIX;
-            }
-        }
-    }
-    env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void gnss_sv_status_callback(GnssSvStatus* sv_status) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    size_t status_size = sv_status->size;
-    // Check the size, and reject the object that has invalid size.
-    if (status_size != sizeof(GnssSvStatus)) {
-        ALOGE("Invalid size of GnssSvStatus found: %zd.", status_size);
-        return;
-    }
-    sGnssSvListSize = sv_status->num_svs;
-    // Clamp the list size
-    if (sGnssSvListSize > GNSS_MAX_SATELLITE_COUNT) {
-        ALOGD("Too many satellites %zd. Clamps to %d.",
-              sGnssSvListSize,
-              GNSS_MAX_SATELLITE_COUNT);
-        sGnssSvListSize = GNSS_MAX_SATELLITE_COUNT;
-    }
-    // Copy GNSS SV info into sGnssSvList, if any.
-    if (sGnssSvListSize > 0) {
-        memcpy(sGnssSvList,
-               sv_status->gnss_sv_list,
-               sizeof(GnssSvInfo) * sGnssSvListSize);
-    }
-    env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void nmea_callback(GpsUtcTime timestamp, const char* nmea, int length)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    // The Java code will call back to read these values
-    // We do this to avoid creating unnecessary String objects
-    sNmeaString = nmea;
-    sNmeaStringLength = length;
-    env->CallVoidMethod(mCallbacksObj, method_reportNmea, timestamp);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void set_system_info_callback(const GnssSystemInfo* info) {
-    ALOGD("set_system_info_callback: year_of_hw=%d\n", info->year_of_hw);
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(mCallbacksObj, method_setGnssYearOfHardware,
-                        info->year_of_hw);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void set_capabilities_callback(uint32_t capabilities)
-{
-    ALOGD("set_capabilities_callback: %du\n", capabilities);
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(mCallbacksObj, method_setEngineCapabilities, capabilities);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void acquire_wakelock_callback()
-{
-    acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
-}
-
-static void release_wakelock_callback()
-{
-    release_wake_lock(WAKE_LOCK_NAME);
-}
-
-static void request_utc_time_callback()
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static pthread_t create_thread_callback(const char* name, void (*start)(void *), void* arg)
-{
-    return (pthread_t)AndroidRuntime::createJavaThread(name, start, arg);
-}
-
-GpsCallbacks sGpsCallbacks = {
-    sizeof(GpsCallbacks),
-    location_callback,
-    status_callback,
-    sv_status_callback,
-    nmea_callback,
-    set_capabilities_callback,
-    acquire_wakelock_callback,
-    release_wakelock_callback,
-    create_thread_callback,
-    request_utc_time_callback,
-    set_system_info_callback,
-    gnss_sv_status_callback,
-};
-
-static void xtra_download_request_callback()
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(mCallbacksObj, method_xtraDownloadRequest);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-GpsXtraCallbacks sGpsXtraCallbacks = {
-    xtra_download_request_callback,
-    create_thread_callback,
-};
-
-static jbyteArray convert_to_ipv4(uint32_t ip, bool net_order)
-{
-    if (INADDR_NONE == ip) {
-        return NULL;
-    }
-
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jbyteArray byteArray = env->NewByteArray(4);
-    if (byteArray == NULL) {
-        ALOGE("Unable to allocate byte array for IPv4 address");
-        return NULL;
-    }
-
-    jbyte ipv4[4];
-    if (net_order) {
-        ALOGV("Converting IPv4 address(net_order) %x", ip);
-        memcpy(ipv4, &ip, sizeof(ipv4));
-    } else {
-        ALOGV("Converting IPv4 address(host_order) %x", ip);
-        //endianess transparent conversion from int to char[]
-        ipv4[0] = (jbyte) (ip & 0xFF);
-        ipv4[1] = (jbyte)((ip>>8) & 0xFF);
-        ipv4[2] = (jbyte)((ip>>16) & 0xFF);
-        ipv4[3] = (jbyte) (ip>>24);
-    }
-
-    env->SetByteArrayRegion(byteArray, 0, 4, (const jbyte*) ipv4);
-    return byteArray;
-}
-
-static void agps_status_callback(AGpsStatus* agps_status)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jbyteArray byteArray = NULL;
-    bool isSupported = false;
-
-    size_t status_size = agps_status->size;
-    if (status_size == sizeof(AGpsStatus)) {
-      ALOGV("AGpsStatus is V3: %zd", status_size);
-      switch (agps_status->addr.ss_family)
-      {
-      case AF_INET:
-          {
-            struct sockaddr_in *in = (struct sockaddr_in*)&(agps_status->addr);
-            uint32_t ipAddr = *(uint32_t*)&(in->sin_addr);
-            byteArray = convert_to_ipv4(ipAddr, true /* net_order */);
-            if (ipAddr == INADDR_NONE || byteArray != NULL) {
-                isSupported = true;
-            }
-            IF_ALOGD() {
-                // log the IP for reference in case there is a bogus value pushed by HAL
-                char str[INET_ADDRSTRLEN];
-                inet_ntop(AF_INET, &(in->sin_addr), str, INET_ADDRSTRLEN);
-                ALOGD("AGPS IP is v4: %s", str);
-            }
-          }
-          break;
-      case AF_INET6:
-          {
-            struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&(agps_status->addr);
-            byteArray = env->NewByteArray(16);
-            if (byteArray != NULL) {
-                env->SetByteArrayRegion(byteArray, 0, 16, (const jbyte *)&(in6->sin6_addr));
-                isSupported = true;
-            } else {
-                ALOGE("Unable to allocate byte array for IPv6 address.");
-            }
-            IF_ALOGD() {
-                // log the IP for reference in case there is a bogus value pushed by HAL
-                char str[INET6_ADDRSTRLEN];
-                inet_ntop(AF_INET6, &(in6->sin6_addr), str, INET6_ADDRSTRLEN);
-                ALOGD("AGPS IP is v6: %s", str);
-            }
-          }
-          break;
-      default:
-          ALOGE("Invalid ss_family found: %d", agps_status->addr.ss_family);
-          break;
-      }
-    } else if (status_size >= sizeof(AGpsStatus_v2)) {
-      ALOGV("AGpsStatus is V2+: %zd", status_size);
-      // for back-compatibility reasons we check in v2 that the data structure size is greater or
-      // equal to the declared size in gps.h
-      uint32_t ipaddr = agps_status->ipaddr;
-      ALOGV("AGPS IP is v4: %x", ipaddr);
-      byteArray = convert_to_ipv4(ipaddr, false /* net_order */);
-      if (ipaddr == INADDR_NONE || byteArray != NULL) {
-          isSupported = true;
-      }
-    } else if (status_size >= sizeof(AGpsStatus_v1)) {
-        ALOGV("AGpsStatus is V1+: %zd", status_size);
-        // because we have to check for >= with regards to v2, we also need to relax the check here
-        // and only make sure that the size is at least what we expect
-        isSupported = true;
-    } else {
-        ALOGE("Invalid size of AGpsStatus found: %zd.", status_size);
-    }
-
-    if (isSupported) {
-        jsize byteArrayLength = byteArray != NULL ? env->GetArrayLength(byteArray) : 0;
-        ALOGV("Passing AGPS IP addr: size %d", byteArrayLength);
-        env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus, agps_status->type,
-                            agps_status->status, byteArray);
-
-        checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    } else {
-        ALOGD("Skipping calling method_reportAGpsStatus.");
-    }
-
-    if (byteArray) {
-        env->DeleteLocalRef(byteArray);
-    }
-}
-
-AGpsCallbacks sAGpsCallbacks = {
-    agps_status_callback,
-    create_thread_callback,
-};
-
-static void gps_ni_notify_callback(GpsNiNotification *notification)
-{
-    ALOGD("gps_ni_notify_callback\n");
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jstring requestor_id = env->NewStringUTF(notification->requestor_id);
-    jstring text = env->NewStringUTF(notification->text);
-    jstring extras = env->NewStringUTF(notification->extras);
-
-    if (requestor_id && text && extras) {
-        env->CallVoidMethod(mCallbacksObj, method_reportNiNotification,
-            notification->notification_id, notification->ni_type,
-            notification->notify_flags, notification->timeout,
-            notification->default_response, requestor_id, text,
-            notification->requestor_id_encoding,
-            notification->text_encoding, extras);
-    } else {
-        ALOGE("out of memory in gps_ni_notify_callback\n");
-    }
-
-    if (requestor_id)
-        env->DeleteLocalRef(requestor_id);
-    if (text)
-        env->DeleteLocalRef(text);
-    if (extras)
-        env->DeleteLocalRef(extras);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-GpsNiCallbacks sGpsNiCallbacks = {
-    gps_ni_notify_callback,
-    create_thread_callback,
-};
-
-static void agps_request_set_id(uint32_t flags)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(mCallbacksObj, method_requestSetID, flags);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void agps_request_ref_location(uint32_t flags)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(mCallbacksObj, method_requestRefLocation, flags);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-AGpsRilCallbacks sAGpsRilCallbacks = {
-    agps_request_set_id,
-    agps_request_ref_location,
-    create_thread_callback,
-};
-
-static void gps_geofence_transition_callback(int32_t geofence_id,  GpsLocation* location,
-        int32_t transition, GpsUtcTime timestamp)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-
-    env->CallVoidMethod(mCallbacksObj, method_reportGeofenceTransition, geofence_id,
-            location->flags, (jdouble)location->latitude, (jdouble)location->longitude,
-            (jdouble)location->altitude,
-            (jfloat)location->speed, (jfloat)location->bearing,
-            (jfloat)location->accuracy, (jlong)location->timestamp,
-            transition, timestamp);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-static void gps_geofence_status_callback(int32_t status, GpsLocation* location)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jint flags = 0;
-    jdouble latitude = 0;
-    jdouble longitude = 0;
-    jdouble altitude = 0;
-    jfloat speed = 0;
-    jfloat bearing = 0;
-    jfloat accuracy = 0;
-    jlong timestamp = 0;
-    if (location != NULL) {
-        flags = location->flags;
-        latitude = location->latitude;
-        longitude = location->longitude;
-        altitude = location->altitude;
-        speed = location->speed;
-        bearing = location->bearing;
-        accuracy = location->accuracy;
-        timestamp = location->timestamp;
-    }
-
-    env->CallVoidMethod(mCallbacksObj, method_reportGeofenceStatus, status,
-            flags, latitude, longitude, altitude, speed, bearing, accuracy, timestamp);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-static void gps_geofence_add_callback(int32_t geofence_id, int32_t status)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
-        ALOGE("Error in geofence_add_callback: %d\n", status);
-    }
-    env->CallVoidMethod(mCallbacksObj, method_reportGeofenceAddStatus, geofence_id, status);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-static void gps_geofence_remove_callback(int32_t geofence_id, int32_t status)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
-        ALOGE("Error in geofence_remove_callback: %d\n", status);
-    }
-    env->CallVoidMethod(mCallbacksObj, method_reportGeofenceRemoveStatus, geofence_id, status);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-static void gps_geofence_resume_callback(int32_t geofence_id, int32_t status)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
-        ALOGE("Error in geofence_resume_callback: %d\n", status);
-    }
-    env->CallVoidMethod(mCallbacksObj, method_reportGeofenceResumeStatus, geofence_id, status);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-static void gps_geofence_pause_callback(int32_t geofence_id, int32_t status)
-{
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
-        ALOGE("Error in geofence_pause_callback: %d\n", status);
-    }
-    env->CallVoidMethod(mCallbacksObj, method_reportGeofencePauseStatus, geofence_id, status);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-GpsGeofenceCallbacks sGpsGeofenceCallbacks = {
-    gps_geofence_transition_callback,
-    gps_geofence_status_callback,
-    gps_geofence_add_callback,
-    gps_geofence_remove_callback,
-    gps_geofence_pause_callback,
-    gps_geofence_resume_callback,
-    create_thread_callback,
-};
-
-static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
-    int err;
-    hw_module_t* module;
-
-    method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
-    method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
-    method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");
-    method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V");
-    method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");
-    method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V");
-    method_setGnssYearOfHardware = env->GetMethodID(clazz, "setGnssYearOfHardware", "(I)V");
-    method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
-    method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",
-            "(IIIIILjava/lang/String;Ljava/lang/String;IILjava/lang/String;)V");
-    method_requestRefLocation = env->GetMethodID(clazz,"requestRefLocation","(I)V");
-    method_requestSetID = env->GetMethodID(clazz,"requestSetID","(I)V");
-    method_requestUtcTime = env->GetMethodID(clazz,"requestUtcTime","()V");
-    method_reportGeofenceTransition = env->GetMethodID(clazz,"reportGeofenceTransition",
-            "(IIDDDFFFJIJ)V");
-    method_reportGeofenceStatus = env->GetMethodID(clazz,"reportGeofenceStatus",
-            "(IIDDDFFFJ)V");
-    method_reportGeofenceAddStatus = env->GetMethodID(clazz,"reportGeofenceAddStatus",
-            "(II)V");
-    method_reportGeofenceRemoveStatus = env->GetMethodID(clazz,"reportGeofenceRemoveStatus",
-            "(II)V");
-    method_reportGeofenceResumeStatus = env->GetMethodID(clazz,"reportGeofenceResumeStatus",
-            "(II)V");
-    method_reportGeofencePauseStatus = env->GetMethodID(clazz,"reportGeofencePauseStatus",
-            "(II)V");
-    method_reportMeasurementData = env->GetMethodID(
-            clazz,
-            "reportMeasurementData",
-            "(Landroid/location/GnssMeasurementsEvent;)V");
-    method_reportNavigationMessages = env->GetMethodID(
-            clazz,
-            "reportNavigationMessage",
-            "(Landroid/location/GnssNavigationMessage;)V");
-
-    err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
-    if (err == 0) {
-        hw_device_t* device;
-        err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
-        if (err == 0) {
-            gps_device_t* gps_device = (gps_device_t *)device;
-            sGpsInterface = gps_device->get_gps_interface(gps_device);
-        }
-    }
-    if (sGpsInterface) {
-        sGpsXtraInterface =
-            (const GpsXtraInterface*)sGpsInterface->get_extension(GPS_XTRA_INTERFACE);
-        sAGpsInterface =
-            (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
-        sGpsNiInterface =
-            (const GpsNiInterface*)sGpsInterface->get_extension(GPS_NI_INTERFACE);
-        sGpsDebugInterface =
-            (const GpsDebugInterface*)sGpsInterface->get_extension(GPS_DEBUG_INTERFACE);
-        sAGpsRilInterface =
-            (const AGpsRilInterface*)sGpsInterface->get_extension(AGPS_RIL_INTERFACE);
-        sGpsGeofencingInterface =
-            (const GpsGeofencingInterface*)sGpsInterface->get_extension(GPS_GEOFENCING_INTERFACE);
-        sGpsMeasurementInterface =
-            (const GpsMeasurementInterface*)sGpsInterface->get_extension(GPS_MEASUREMENT_INTERFACE);
-        sGpsNavigationMessageInterface =
-            (const GpsNavigationMessageInterface*)sGpsInterface->get_extension(
-                    GPS_NAVIGATION_MESSAGE_INTERFACE);
-        sGnssConfigurationInterface =
-            (const GnssConfigurationInterface*)sGpsInterface->get_extension(
-                    GNSS_CONFIGURATION_INTERFACE);
-    }
-}
-
-static jboolean android_location_GnssLocationProvider_is_supported(
-        JNIEnv* /* env */, jclass /* clazz */)
-{
-    return (sGpsInterface != NULL) ?  JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_is_agps_ril_supported(
-        JNIEnv* /* env */, jclass /* clazz */)
-{
-    return (sAGpsRilInterface != NULL) ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean android_location_gpsLocationProvider_is_gnss_configuration_supported(
-        JNIEnv* /* env */, jclass /* jclazz */)
-{
-    return (sGnssConfigurationInterface != NULL) ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject obj)
-{
-    // this must be set before calling into the HAL library
-    if (!mCallbacksObj)
-        mCallbacksObj = env->NewGlobalRef(obj);
-
-    // fail if the main interface fails to initialize
-    if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
-        return JNI_FALSE;
-
-    // if XTRA initialization fails we will disable it by sGpsXtraInterface to NULL,
-    // but continue to allow the rest of the GPS interface to work.
-    if (sGpsXtraInterface && sGpsXtraInterface->init(&sGpsXtraCallbacks) != 0)
-        sGpsXtraInterface = NULL;
-    if (sAGpsInterface)
-        sAGpsInterface->init(&sAGpsCallbacks);
-    if (sGpsNiInterface)
-        sGpsNiInterface->init(&sGpsNiCallbacks);
-    if (sAGpsRilInterface)
-        sAGpsRilInterface->init(&sAGpsRilCallbacks);
-    if (sGpsGeofencingInterface)
-        sGpsGeofencingInterface->init(&sGpsGeofenceCallbacks);
-
-    return JNI_TRUE;
-}
-
-static void android_location_GnssLocationProvider_cleanup(JNIEnv* /* env */, jobject /* obj */)
-{
-    if (sGpsInterface)
-        sGpsInterface->cleanup();
-}
-
-static jboolean android_location_GnssLocationProvider_set_position_mode(JNIEnv* /* env */,
-        jobject /* obj */, jint mode, jint recurrence, jint min_interval, jint preferred_accuracy,
-        jint preferred_time)
-{
-    if (sGpsInterface) {
-        if (sGpsInterface->set_position_mode(mode, recurrence, min_interval, preferred_accuracy,
-                preferred_time) == 0) {
-            return JNI_TRUE;
-        } else {
-            return JNI_FALSE;
-        }
-    }
-    else
-        return JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_start(JNIEnv* /* env */, jobject /* obj */)
-{
-    if (sGpsInterface) {
-        if (sGpsInterface->start() == 0) {
-            return JNI_TRUE;
-        } else {
-            return JNI_FALSE;
-        }
-    }
-    else
-        return JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_stop(JNIEnv* /* env */, jobject /* obj */)
-{
-    if (sGpsInterface) {
-        if (sGpsInterface->stop() == 0) {
-            return JNI_TRUE;
-        } else {
-            return JNI_FALSE;
-        }
-    }
-    else
-        return JNI_FALSE;
-}
-
-static void android_location_GnssLocationProvider_delete_aiding_data(JNIEnv* /* env */,
-                                                                    jobject /* obj */,
-                                                                    jint flags)
-{
-    if (sGpsInterface)
-        sGpsInterface->delete_aiding_data(flags);
-}
-
-static jint android_location_GnssLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */,
-        jintArray svidWithFlagArray, jfloatArray cn0Array, jfloatArray elevArray,
-        jfloatArray azumArray)
-{
-    // this should only be called from within a call to reportSvStatus
-    jint* svidWithFlags = env->GetIntArrayElements(svidWithFlagArray, 0);
-    jfloat* cn0s = env->GetFloatArrayElements(cn0Array, 0);
-    jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
-    jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
-
-    // GNSS SV info.
-    for (size_t i = 0; i < sGnssSvListSize; ++i) {
-        const GnssSvInfo& info = sGnssSvList[i];
-        svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) |
-            (info.constellation << CONSTELLATION_TYPE_SHIFT_WIDTH) |
-            info.flags;
-        cn0s[i] = info.c_n0_dbhz;
-        elev[i] = info.elevation;
-        azim[i] = info.azimuth;
-    }
-
-    env->ReleaseIntArrayElements(svidWithFlagArray, svidWithFlags, 0);
-    env->ReleaseFloatArrayElements(cn0Array, cn0s, 0);
-    env->ReleaseFloatArrayElements(elevArray, elev, 0);
-    env->ReleaseFloatArrayElements(azumArray, azim, 0);
-    return (jint) sGnssSvListSize;
-}
-
-static void android_location_GnssLocationProvider_agps_set_reference_location_cellid(
-        JNIEnv* /* env */, jobject /* obj */, jint type, jint mcc, jint mnc, jint lac, jint cid)
-{
-    AGpsRefLocation location;
-
-    if (!sAGpsRilInterface) {
-        ALOGE("no AGPS RIL interface in agps_set_reference_location_cellid");
-        return;
-    }
-
-    switch(type) {
-        case AGPS_REF_LOCATION_TYPE_GSM_CELLID:
-        case AGPS_REF_LOCATION_TYPE_UMTS_CELLID:
-            location.type = type;
-            location.u.cellID.mcc = mcc;
-            location.u.cellID.mnc = mnc;
-            location.u.cellID.lac = lac;
-            location.u.cellID.cid = cid;
-            break;
-        default:
-            ALOGE("Neither a GSM nor a UMTS cellid (%s:%d).",__FUNCTION__,__LINE__);
-            return;
-            break;
-    }
-    sAGpsRilInterface->set_ref_location(&location, sizeof(location));
-}
-
-static void android_location_GnssLocationProvider_agps_send_ni_message(JNIEnv* env,
-        jobject /* obj */, jbyteArray ni_msg, jint size)
-{
-    size_t sz;
-
-    if (!sAGpsRilInterface) {
-        ALOGE("no AGPS RIL interface in send_ni_message");
-        return;
-    }
-    if (size < 0)
-        return;
-    sz = (size_t)size;
-    jbyte* b = env->GetByteArrayElements(ni_msg, 0);
-    sAGpsRilInterface->ni_message((uint8_t *)b,sz);
-    env->ReleaseByteArrayElements(ni_msg,b,0);
-}
-
-static void android_location_GnssLocationProvider_agps_set_id(JNIEnv *env, jobject /* obj */,
-                                                             jint type, jstring  setid_string)
-{
-    if (!sAGpsRilInterface) {
-        ALOGE("no AGPS RIL interface in agps_set_id");
-        return;
-    }
-
-    const char *setid = env->GetStringUTFChars(setid_string, NULL);
-    sAGpsRilInterface->set_set_id(type, setid);
-    env->ReleaseStringUTFChars(setid_string, setid);
-}
-
-static jint android_location_GnssLocationProvider_read_nmea(JNIEnv* env, jobject /* obj */,
-                                            jbyteArray nmeaArray, jint buffer_size)
-{
-    // this should only be called from within a call to reportNmea
-    jbyte* nmea = (jbyte *)env->GetPrimitiveArrayCritical(nmeaArray, 0);
-    int length = sNmeaStringLength;
-    if (length > buffer_size)
-        length = buffer_size;
-    memcpy(nmea, sNmeaString, length);
-    env->ReleasePrimitiveArrayCritical(nmeaArray, nmea, JNI_ABORT);
-    return (jint) length;
-}
-
-static void android_location_GnssLocationProvider_inject_time(JNIEnv* /* env */, jobject /* obj */,
-        jlong time, jlong timeReference, jint uncertainty)
-{
-    if (sGpsInterface)
-        sGpsInterface->inject_time(time, timeReference, uncertainty);
-}
-
-static void android_location_GnssLocationProvider_inject_location(JNIEnv* /* env */,
-        jobject /* obj */, jdouble latitude, jdouble longitude, jfloat accuracy)
-{
-    if (sGpsInterface)
-        sGpsInterface->inject_location(latitude, longitude, accuracy);
-}
-
-static jboolean android_location_GnssLocationProvider_supports_xtra(
-        JNIEnv* /* env */, jobject /* obj */)
-{
-    return (sGpsXtraInterface != NULL) ? JNI_TRUE : JNI_FALSE;
-}
-
-static void android_location_GnssLocationProvider_inject_xtra_data(JNIEnv* env, jobject /* obj */,
-        jbyteArray data, jint length)
-{
-    if (!sGpsXtraInterface) {
-        ALOGE("no XTRA interface in inject_xtra_data");
-        return;
-    }
-
-    jbyte* bytes = (jbyte *)env->GetPrimitiveArrayCritical(data, 0);
-    sGpsXtraInterface->inject_xtra_data((char *)bytes, length);
-    env->ReleasePrimitiveArrayCritical(data, bytes, JNI_ABORT);
-}
-
-static void android_location_GnssLocationProvider_agps_data_conn_open(
-        JNIEnv* env, jobject /* obj */, jstring apn, jint apnIpType)
-{
-    if (!sAGpsInterface) {
-        ALOGE("no AGPS interface in agps_data_conn_open");
-        return;
-    }
-    if (apn == NULL) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
-        return;
-    }
-
-    const char *apnStr = env->GetStringUTFChars(apn, NULL);
-
-    size_t interface_size = sAGpsInterface->size;
-    if (interface_size == sizeof(AGpsInterface)) {
-        sAGpsInterface->data_conn_open_with_apn_ip_type(apnStr, apnIpType);
-    } else if (interface_size == sizeof(AGpsInterface_v1)) {
-        sAGpsInterface->data_conn_open(apnStr);
-    } else {
-        ALOGE("Invalid size of AGpsInterface found: %zd.", interface_size);
-    }
-
-    env->ReleaseStringUTFChars(apn, apnStr);
-}
-
-static void android_location_GnssLocationProvider_agps_data_conn_closed(JNIEnv* /* env */,
-                                                                       jobject /* obj */)
-{
-    if (!sAGpsInterface) {
-        ALOGE("no AGPS interface in agps_data_conn_closed");
-        return;
-    }
-    sAGpsInterface->data_conn_closed();
-}
-
-static void android_location_GnssLocationProvider_agps_data_conn_failed(JNIEnv* /* env */,
-                                                                       jobject /* obj */)
-{
-    if (!sAGpsInterface) {
-        ALOGE("no AGPS interface in agps_data_conn_failed");
-        return;
-    }
-    sAGpsInterface->data_conn_failed();
-}
-
-static void android_location_GnssLocationProvider_set_agps_server(JNIEnv* env, jobject /* obj */,
-        jint type, jstring hostname, jint port)
-{
-    if (!sAGpsInterface) {
-        ALOGE("no AGPS interface in set_agps_server");
-        return;
-    }
-    const char *c_hostname = env->GetStringUTFChars(hostname, NULL);
-    sAGpsInterface->set_server(type, c_hostname, port);
-    env->ReleaseStringUTFChars(hostname, c_hostname);
-}
-
-static void android_location_GnssLocationProvider_send_ni_response(JNIEnv* /* env */,
-      jobject /* obj */, jint notifId, jint response)
-{
-    if (!sGpsNiInterface) {
-        ALOGE("no NI interface in send_ni_response");
-        return;
-    }
-
-    sGpsNiInterface->respond(notifId, response);
-}
-
-static jstring android_location_GnssLocationProvider_get_internal_state(JNIEnv* env,
-                                                                       jobject /* obj */) {
-    jstring result = NULL;
-    if (sGpsDebugInterface) {
-        const size_t maxLength = 2047;
-        char buffer[maxLength+1];
-        size_t length = sGpsDebugInterface->get_internal_state(buffer, maxLength);
-        if (length > maxLength) length = maxLength;
-        buffer[length] = 0;
-        result = env->NewStringUTF(buffer);
-    }
-    return result;
-}
-
-static void android_location_GnssLocationProvider_update_network_state(JNIEnv* env, jobject /* obj */,
-        jboolean connected, jint type, jboolean roaming, jboolean available, jstring extraInfo, jstring apn)
-{
-
-    if (sAGpsRilInterface && sAGpsRilInterface->update_network_state) {
-        if (extraInfo) {
-            const char *extraInfoStr = env->GetStringUTFChars(extraInfo, NULL);
-            sAGpsRilInterface->update_network_state(connected, type, roaming, extraInfoStr);
-            env->ReleaseStringUTFChars(extraInfo, extraInfoStr);
-        } else {
-            sAGpsRilInterface->update_network_state(connected, type, roaming, NULL);
-        }
-
-        // update_network_availability callback was not included in original AGpsRilInterface
-        if (sAGpsRilInterface->size >= sizeof(AGpsRilInterface)
-                && sAGpsRilInterface->update_network_availability) {
-            const char *c_apn = env->GetStringUTFChars(apn, NULL);
-            sAGpsRilInterface->update_network_availability(available, c_apn);
-            env->ReleaseStringUTFChars(apn, c_apn);
-        }
-    }
-}
-
-static jboolean android_location_GnssLocationProvider_is_geofence_supported(
-        JNIEnv* /* env */, jobject /* obj */)
-{
-    return (sGpsGeofencingInterface != NULL) ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_add_geofence(JNIEnv* /* env */,
-        jobject /* obj */, jint geofence_id, jdouble latitude, jdouble longitude, jdouble radius,
-        jint last_transition, jint monitor_transition, jint notification_responsiveness,
-        jint unknown_timer) {
-    if (sGpsGeofencingInterface != NULL) {
-        sGpsGeofencingInterface->add_geofence_area(geofence_id, latitude, longitude,
-                radius, last_transition, monitor_transition, notification_responsiveness,
-                unknown_timer);
-        return JNI_TRUE;
-    } else {
-        ALOGE("Geofence interface not available");
-    }
-    return JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_remove_geofence(JNIEnv* /* env */,
-        jobject /* obj */, jint geofence_id) {
-    if (sGpsGeofencingInterface != NULL) {
-        sGpsGeofencingInterface->remove_geofence_area(geofence_id);
-        return JNI_TRUE;
-    } else {
-        ALOGE("Geofence interface not available");
-    }
-    return JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_pause_geofence(JNIEnv* /* env */,
-        jobject /* obj */, jint geofence_id) {
-    if (sGpsGeofencingInterface != NULL) {
-        sGpsGeofencingInterface->pause_geofence(geofence_id);
-        return JNI_TRUE;
-    } else {
-        ALOGE("Geofence interface not available");
-    }
-    return JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_resume_geofence(JNIEnv* /* env */,
-        jobject /* obj */, jint geofence_id, jint monitor_transition) {
-    if (sGpsGeofencingInterface != NULL) {
-        sGpsGeofencingInterface->resume_geofence(geofence_id, monitor_transition);
-        return JNI_TRUE;
-    } else {
-        ALOGE("Geofence interface not available");
-    }
-    return JNI_FALSE;
-}
-
 template<class T>
 class JavaMethodHelper {
-  public:
-   // Helper function to call setter on a Java object.
-   static void callJavaMethod(
+ public:
+    // Helper function to call setter on a Java object.
+    static void callJavaMethod(
            JNIEnv* env,
            jclass clazz,
            jobject object,
            const char* method_name,
            T value);
 
-  private:
+ private:
     static const char *const signature_;
 };
 
@@ -1045,20 +136,20 @@
 }
 
 class JavaObject {
-  public:
-   JavaObject(JNIEnv* env, const char* class_name);
-   virtual ~JavaObject();
+ public:
+    JavaObject(JNIEnv* env, const char* class_name);
+    virtual ~JavaObject();
 
-   template<class T>
-   void callSetter(const char* method_name, T value);
-   template<class T>
-   void callSetter(const char* method_name, T* value, size_t size);
-   jobject get();
+    template<class T>
+    void callSetter(const char* method_name, T value);
+    template<class T>
+    void callSetter(const char* method_name, T* value, size_t size);
+    jobject get();
 
-  private:
-   JNIEnv* env_;
-   jclass clazz_;
-   jobject object_;
+ private:
+    JNIEnv* env_;
+    jclass clazz_;
+    jobject object_;
 };
 
 JavaObject::JavaObject(JNIEnv* env, const char* class_name) : env_(env) {
@@ -1081,7 +172,7 @@
 void JavaObject::callSetter(
         const char* method_name, uint8_t* value, size_t size) {
     jbyteArray array = env_->NewByteArray(size);
-    env_->SetByteArrayRegion(array, 0, size, (jbyte*) value);
+    env_->SetByteArrayRegion(array, 0, size, reinterpret_cast<jbyte*>(value));
     jmethodID method = env_->GetMethodID(
             clazz_,
             method_name,
@@ -1095,7 +186,6 @@
 }
 
 // Define Java method signatures for all known types.
-
 template<>
 const char *const JavaMethodHelper<uint8_t>::signature_ = "(B)V";
 template<>
@@ -1119,209 +209,460 @@
 
 #define SET(setter, value) object.callSetter("set" # setter, (value))
 
-// If you want to check if a flag is not set, use SET_IF_NOT(FLAG, setter,
-// value) to do that. SET_IF(!FLAG, setter, value) won't compile.
-//
-// This macros generates compilation error if the provided 'flag' is not a
-// single token. For example, 'GNSS_CLOCK_HAS_BIAS' can be accepted, but
-// '!GNSS_CLOCK_HAS_DRIFT' will fail to compile.
-#define SET_IF(flag, setter, value) do { \
-        if (flags & flag) { \
-            JavaObject& name_check_##flag = object; \
-            name_check_##flag.callSetter("set" # setter, (value)); \
-        } \
-    } while (false)
-#define SET_IF_NOT(flag, setter, value) do { \
-        if (!(flags & flag)) { \
-            JavaObject& name_check_##flag = object; \
-            name_check_##flag.callSetter("set" # setter, (value)); \
-        } \
-    } while (false)
+static inline jboolean boolToJbool(bool value) {
+    return value ? JNI_TRUE : JNI_FALSE;
+}
 
-static jobject translate_gps_clock(JNIEnv* env, GpsClock* clock) {
-    static uint32_t discontinuity_count_to_handle_old_clock_type = 0;
-    JavaObject object(env, "android/location/GnssClock");
-    GpsClockFlags flags = clock->flags;
+static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
+    if (env->ExceptionCheck()) {
+        ALOGE("An exception was thrown by callback '%s'.", methodName);
+        LOGE_EX(env);
+        env->ExceptionClear();
+    }
+}
 
-    SET_IF(GPS_CLOCK_HAS_LEAP_SECOND,
-           LeapSecond,
-           static_cast<int32_t>(clock->leap_second));
+/*
+ * GnssCallback class implements the callback methods for IGnss interface.
+ */
+struct GnssCallback : public IGnssCallback {
+    Return<void> gnssLocationCb(
+          const android::hardware::gnss::V1_0::GnssLocation& location) override;
+    Return<void> gnssStatusCb(const IGnssCallback::GnssStatusValue status) override;
+    Return<void> gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) override;
+    Return<void> gnssNmeaCb(int64_t timestamp, const android::hardware::hidl_string& nmea) override;
+    Return<void> gnssSetCapabilitesCb(uint32_t capabilities) override;
+    Return<void> gnssAcquireWakelockCb() override;
+    Return<void> gnssReleaseWakelockCb() override;
+    Return<void> gnssRequestTimeCb() override;
+    Return<void> gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) override;
 
-    // GnssClock only supports the more effective HW_CLOCK type, so type
-    // handling and documentation complexity has been removed.  To convert the
-    // old GPS_CLOCK types (active only in a limited number of older devices),
-    // the GPS time information is handled as an always discontinuous HW clock,
-    // with the GPS time information put into the full_bias_ns instead - so that
-    // time_ns - full_bias_ns = local estimate of GPS time. Additionally, the
-    // sign of full_bias_ns and bias_ns has flipped between GpsClock &
-    // GnssClock, so that is also handled below.
-    switch (clock->type) {
-      case GPS_CLOCK_TYPE_UNKNOWN:
-        // Clock type unsupported.
-        ALOGE("Unknown clock type provided.");
-        break;
-      case GPS_CLOCK_TYPE_LOCAL_HW_TIME:
-        // Already local hardware time. No need to do anything.
-        break;
-      case GPS_CLOCK_TYPE_GPS_TIME:
-        // GPS time, need to convert.
-        flags |= GPS_CLOCK_HAS_FULL_BIAS;
-        clock->full_bias_ns = clock->time_ns;
-        clock->time_ns = 0;
-        SET(HardwareClockDiscontinuityCount,
-            discontinuity_count_to_handle_old_clock_type++);
-        break;
+    static GnssSvInfo sGnssSvList[static_cast<uint32_t>(
+            android::hardware::gnss::V1_0::GnssMax::SVS_COUNT)];
+    static size_t sGnssSvListSize;
+
+    static const char* sNmeaString;
+    static size_t sNmeaStringLength;
+};
+
+IGnssCallback::GnssSvInfo GnssCallback::sGnssSvList[static_cast<uint32_t>(
+        android::hardware::gnss::V1_0::GnssMax::SVS_COUNT)];
+const char* GnssCallback::sNmeaString = nullptr;
+size_t GnssCallback::sNmeaStringLength = 0;
+size_t GnssCallback::sGnssSvListSize = 0;
+
+Return<void> GnssCallback::gnssLocationCb(
+        const ::android::hardware::gnss::V1_0::GnssLocation& location) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbacksObj,
+                        method_reportLocation,
+                        location.gnssLocationFlags,
+                        static_cast<jdouble>(location.latitudeDegrees),
+                        static_cast<jdouble>(location.longitudeDegrees),
+                        static_cast<jdouble>(location.altitudeMeters),
+                        static_cast<jfloat>(location.speedMetersPerSec),
+                        static_cast<jfloat>(location.bearingDegrees),
+                        static_cast<jfloat>(location.accuracyMeters),
+                        static_cast<jlong>(location.timestamp));
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+Return<void> GnssCallback::gnssStatusCb(const IGnssCallback::GnssStatusValue status) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbacksObj, method_reportStatus, status);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+Return<void> GnssCallback::gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+    sGnssSvListSize = svStatus.numSvs;
+    if (sGnssSvListSize > static_cast<uint32_t>(
+            android::hardware::gnss::V1_0::GnssMax::SVS_COUNT)) {
+        ALOGD("Too many satellites %zd. Clamps to %u.", sGnssSvListSize,
+              static_cast<uint32_t>(android::hardware::gnss::V1_0::GnssMax::SVS_COUNT));
+        sGnssSvListSize = static_cast<uint32_t>(android::hardware::gnss::V1_0::GnssMax::SVS_COUNT);
     }
 
-    SET(TimeNanos, clock->time_ns);
-    SET_IF(GPS_CLOCK_HAS_TIME_UNCERTAINTY,
-           TimeUncertaintyNanos,
-           clock->time_uncertainty_ns);
-
-    // Definition of sign for full_bias_ns & bias_ns has been changed since N,
-    // so flip signs here.
-    SET_IF(GPS_CLOCK_HAS_FULL_BIAS, FullBiasNanos, -(clock->full_bias_ns));
-    SET_IF(GPS_CLOCK_HAS_BIAS, BiasNanos, -(clock->bias_ns));
-
-    SET_IF(GPS_CLOCK_HAS_BIAS_UNCERTAINTY,
-           BiasUncertaintyNanos,
-           clock->bias_uncertainty_ns);
-    SET_IF(GPS_CLOCK_HAS_DRIFT, DriftNanosPerSecond, clock->drift_nsps);
-    SET_IF(GPS_CLOCK_HAS_DRIFT_UNCERTAINTY,
-           DriftUncertaintyNanosPerSecond,
-           clock->drift_uncertainty_nsps);
-
-    return object.get();
-}
-
-static jobject translate_gnss_clock(JNIEnv* env, GnssClock* clock) {
-    JavaObject object(env, "android/location/GnssClock");
-    GnssClockFlags flags = clock->flags;
-
-    SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND,
-           LeapSecond,
-           static_cast<int32_t>(clock->leap_second));
-    SET(TimeNanos, clock->time_ns);
-    SET_IF(GNSS_CLOCK_HAS_TIME_UNCERTAINTY,
-           TimeUncertaintyNanos,
-           clock->time_uncertainty_ns);
-    SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasNanos, clock->full_bias_ns);
-    SET_IF(GNSS_CLOCK_HAS_BIAS, BiasNanos, clock->bias_ns);
-    SET_IF(GNSS_CLOCK_HAS_BIAS_UNCERTAINTY,
-           BiasUncertaintyNanos,
-           clock->bias_uncertainty_ns);
-    SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftNanosPerSecond, clock->drift_nsps);
-    SET_IF(GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY,
-           DriftUncertaintyNanosPerSecond,
-           clock->drift_uncertainty_nsps);
-
-    SET(HardwareClockDiscontinuityCount, clock->hw_clock_discontinuity_count);
-
-    return object.get();
-}
-
-static jobject translate_gps_measurement(JNIEnv* env,
-                                         GpsMeasurement* measurement) {
-    JavaObject object(env, "android/location/GnssMeasurement");
-    GpsMeasurementFlags flags = measurement->flags;
-    SET(Svid, static_cast<int32_t>(measurement->prn));
-    if (measurement->prn >= 1 && measurement->prn <= 32) {
-        SET(ConstellationType, static_cast<int32_t>(GNSS_CONSTELLATION_GPS));
-    } else {
-        ALOGD("Unknown constellation type with Svid = %d.", measurement->prn);
-        SET(ConstellationType,
-            static_cast<int32_t>(GNSS_CONSTELLATION_UNKNOWN));
+    // Copy GNSS SV info into sGnssSvList, if any.
+    if (svStatus.numSvs > 0) {
+        memcpy(sGnssSvList, svStatus.gnssSvList.data(), sizeof(GnssSvInfo) * sGnssSvListSize);
     }
-    SET(TimeOffsetNanos, measurement->time_offset_ns);
-    SET(State, static_cast<int32_t>(measurement->state));
-    SET(ReceivedSvTimeNanos, measurement->received_gps_tow_ns);
-    SET(ReceivedSvTimeUncertaintyNanos,
-        measurement->received_gps_tow_uncertainty_ns);
-    SET(Cn0DbHz, measurement->c_n0_dbhz);
-    SET(PseudorangeRateMetersPerSecond, measurement->pseudorange_rate_mps);
-    SET(PseudorangeRateUncertaintyMetersPerSecond,
-        measurement->pseudorange_rate_uncertainty_mps);
-    SET(AccumulatedDeltaRangeState,
-        static_cast<int32_t>(measurement->accumulated_delta_range_state));
-    SET(AccumulatedDeltaRangeMeters, measurement->accumulated_delta_range_m);
-    SET(AccumulatedDeltaRangeUncertaintyMeters,
-        measurement->accumulated_delta_range_uncertainty_m);
-    SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
-           CarrierFrequencyHz,
-           measurement->carrier_frequency_hz);
-    SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
-           CarrierCycles,
-           measurement->carrier_cycles);
-    SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE,
-           CarrierPhase,
-           measurement->carrier_phase);
-    SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
-           CarrierPhaseUncertainty,
-           measurement->carrier_phase_uncertainty);
-    SET(MultipathIndicator,
-        static_cast<int32_t>(measurement->multipath_indicator));
-    SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
 
-    return object.get();
+    env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
 }
 
-static jobject translate_gnss_measurement(JNIEnv* env,
-                                          GnssMeasurement* measurement) {
+Return<void> GnssCallback::gnssNmeaCb(
+    int64_t timestamp, const ::android::hardware::hidl_string& nmea) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    /*
+     * The Java code will call back to read these values.
+     * We do this to avoid creating unnecessary String objects.
+     */
+    sNmeaString = nmea.c_str();
+    sNmeaStringLength = nmea.size();
+
+    env->CallVoidMethod(mCallbacksObj, method_reportNmea, timestamp);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+Return<void> GnssCallback::gnssSetCapabilitesCb(uint32_t capabilities) {
+    ALOGD("%s: %du\n", __func__, capabilities);
+
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbacksObj, method_setEngineCapabilities, capabilities);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+Return<void> GnssCallback::gnssAcquireWakelockCb() {
+    acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
+    return Void();
+}
+
+Return<void> GnssCallback::gnssReleaseWakelockCb() {
+    release_wake_lock(WAKE_LOCK_NAME);
+    return Void();
+}
+
+Return<void> GnssCallback::gnssRequestTimeCb() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+Return<void> GnssCallback::gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) {
+    ALOGD("%s: yearOfHw=%d\n", __func__, info.yearOfHw);
+
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbacksObj, method_setGnssYearOfHardware,
+                        info.yearOfHw);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+class GnssXtraCallback : public IGnssXtraCallback {
+    Return<void> downloadRequestCb() override;
+};
+
+/*
+ * GnssXtraCallback class implements the callback methods for the IGnssXtra
+ * interface.
+ */
+Return<void> GnssXtraCallback::downloadRequestCb() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbacksObj, method_xtraDownloadRequest);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+/*
+ * GnssGeofenceCallback class implements the callback methods for the
+ * IGnssGeofence interface.
+ */
+struct GnssGeofenceCallback : public IGnssGeofenceCallback {
+    // Methods from ::android::hardware::gps::V1_0::IGnssGeofenceCallback follow.
+    Return<void> gnssGeofenceTransitionCb(
+            int32_t geofenceId,
+            const android::hardware::gnss::V1_0::GnssLocation& location,
+            GeofenceTransition transition,
+            hardware::gnss::V1_0::GnssUtcTime timestamp) override;
+    Return<void> gnssGeofenceStatusCb(
+            GeofenceAvailability status,
+            const android::hardware::gnss::V1_0::GnssLocation& location) override;
+    Return<void> gnssGeofenceAddCb(int32_t geofenceId,
+                                   GeofenceStatus status) override;
+    Return<void> gnssGeofenceRemoveCb(int32_t geofenceId,
+                                      GeofenceStatus status) override;
+    Return<void> gnssGeofencePauseCb(int32_t geofenceId,
+                                     GeofenceStatus status) override;
+    Return<void> gnssGeofenceResumeCb(int32_t geofenceId,
+                                      GeofenceStatus status) override;
+};
+
+Return<void> GnssGeofenceCallback::gnssGeofenceTransitionCb(
+        int32_t geofenceId,
+        const android::hardware::gnss::V1_0::GnssLocation& location,
+        GeofenceTransition transition,
+        hardware::gnss::V1_0::GnssUtcTime timestamp) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+    env->CallVoidMethod(mCallbacksObj,
+                        method_reportGeofenceTransition,
+                        geofenceId,
+                        location.gnssLocationFlags,
+                        static_cast<jdouble>(location.latitudeDegrees),
+                        static_cast<jdouble>(location.longitudeDegrees),
+                        static_cast<jdouble>(location.altitudeMeters),
+                        static_cast<jfloat>(location.speedMetersPerSec),
+                        static_cast<jfloat>(location.bearingDegrees),
+                        static_cast<jfloat>(location.accuracyMeters),
+                        static_cast<jlong>(location.timestamp),
+                        transition,
+                        timestamp);
+
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofenceStatusCb(
+        GeofenceAvailability status,
+        const android::hardware::gnss::V1_0::GnssLocation& location) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbacksObj,
+                        method_reportGeofenceStatus,
+                        status,
+                        location.gnssLocationFlags,
+                        static_cast<jdouble>(location.latitudeDegrees),
+                        static_cast<jdouble>(location.longitudeDegrees),
+                        static_cast<jdouble>(location.altitudeMeters),
+                        static_cast<jfloat>(location.speedMetersPerSec),
+                        static_cast<jfloat>(location.bearingDegrees),
+                        static_cast<jfloat>(location.accuracyMeters),
+                        static_cast<jlong>(location.timestamp));
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofenceAddCb(int32_t geofenceId,
+                                                    GeofenceStatus status) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
+        ALOGE("%s: Error in adding a Geofence: %d\n", __func__, status);
+    }
+
+    env->CallVoidMethod(mCallbacksObj,
+                        method_reportGeofenceAddStatus,
+                        geofenceId,
+                        status);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofenceRemoveCb(int32_t geofenceId,
+                                                       GeofenceStatus status) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
+        ALOGE("%s: Error in removing a Geofence: %d\n", __func__, status);
+    }
+
+    env->CallVoidMethod(mCallbacksObj,
+                        method_reportGeofenceRemoveStatus,
+                        geofenceId, status);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofencePauseCb(int32_t geofenceId,
+                                                      GeofenceStatus status) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
+        ALOGE("%s: Error in pausing Geofence: %d\n", __func__, status);
+    }
+
+    env->CallVoidMethod(mCallbacksObj,
+                        method_reportGeofencePauseStatus,
+                        geofenceId, status);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofenceResumeCb(int32_t geofenceId,
+                                                       GeofenceStatus status) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
+        ALOGE("%s: Error in resuming Geofence: %d\n", __func__, status);
+    }
+
+    env->CallVoidMethod(mCallbacksObj,
+                        method_reportGeofenceResumeStatus,
+                        geofenceId, status);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+/*
+ * GnssNavigationMessageCallback interface implements the callback methods
+ * required by the IGnssNavigationMessage interface.
+ */
+struct GnssNavigationMessageCallback : public IGnssNavigationMessageCallback {
+  /*
+   * Methods from ::android::hardware::gps::V1_0::IGnssNavigationMessageCallback
+   * follow.
+   */
+  Return<void> gnssNavigationMessageCb(
+          const IGnssNavigationMessageCallback::GnssNavigationMessage& message) override;
+};
+
+Return<void> GnssNavigationMessageCallback::gnssNavigationMessageCb(
+        const IGnssNavigationMessageCallback::GnssNavigationMessage& message) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+    size_t dataLength = message.data.size();
+
+    std::vector<uint8_t> navigationData = message.data;
+    uint8_t* data = &(navigationData[0]);
+    if (dataLength == 0 || data == NULL) {
+      ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data,
+            dataLength);
+      return Void();
+    }
+
+    JavaObject object(env, "android/location/GnssNavigationMessage");
+    SET(Type, static_cast<int32_t>(message.type));
+    SET(Svid, static_cast<int32_t>(message.svid));
+    SET(MessageId, static_cast<int32_t>(message.messageId));
+    SET(SubmessageId, static_cast<int32_t>(message.submessageId));
+    object.callSetter("setData", data, dataLength);
+    SET(Status, static_cast<int32_t>(message.status));
+
+    jobject navigationMessage = object.get();
+    env->CallVoidMethod(mCallbacksObj,
+                        method_reportNavigationMessages,
+                        navigationMessage);
+    env->DeleteLocalRef(navigationMessage);
+    return Void();
+}
+
+/*
+ * GnssMeasurementCallback implements the callback methods required for the
+ * GnssMeasurement interface.
+ */
+struct GnssMeasurementCallback : public IGnssMeasurementCallback {
+    Return<void> GnssMeasurementCb(const IGnssMeasurementCallback::GnssData& data);
+ private:
+    jobject translateGnssMeasurement(
+            JNIEnv* env, const IGnssMeasurementCallback::GnssMeasurement* measurement);
+    jobject translateGnssClock(
+            JNIEnv* env, const IGnssMeasurementCallback::GnssClock* clock);
+    jobjectArray translateGnssMeasurements(
+            JNIEnv* env,
+            const IGnssMeasurementCallback::GnssMeasurement* measurements,
+            size_t count);
+    void setMeasurementData(JNIEnv* env, jobject clock, jobjectArray measurementArray);
+};
+
+
+Return<void> GnssMeasurementCallback::GnssMeasurementCb(
+        const IGnssMeasurementCallback::GnssData& data) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+    jobject clock;
+    jobjectArray measurementArray;
+
+    clock = translateGnssClock(env, &data.clock);
+    measurementArray = translateGnssMeasurements(
+        env, data.measurements.data(), data.measurementCount);
+    setMeasurementData(env, clock, measurementArray);
+
+    env->DeleteLocalRef(clock);
+    env->DeleteLocalRef(measurementArray);
+    return Void();
+}
+
+jobject GnssMeasurementCallback::translateGnssMeasurement(
+        JNIEnv* env, const IGnssMeasurementCallback::GnssMeasurement* measurement) {
     JavaObject object(env, "android/location/GnssMeasurement");
 
-    GnssMeasurementFlags flags = measurement->flags;
+    uint32_t flags = static_cast<uint32_t>(measurement->flags);
 
     SET(Svid, static_cast<int32_t>(measurement->svid));
     SET(ConstellationType, static_cast<int32_t>(measurement->constellation));
-    SET(TimeOffsetNanos, measurement->time_offset_ns);
+    SET(TimeOffsetNanos, measurement->timeOffsetNs);
     SET(State, static_cast<int32_t>(measurement->state));
-    SET(ReceivedSvTimeNanos, measurement->received_sv_time_in_ns);
+    SET(ReceivedSvTimeNanos, measurement->receivedSvTimeInNs);
     SET(ReceivedSvTimeUncertaintyNanos,
-        measurement->received_sv_time_uncertainty_in_ns);
-    SET(Cn0DbHz, measurement->c_n0_dbhz);
-    SET(PseudorangeRateMetersPerSecond, measurement->pseudorange_rate_mps);
+        measurement->receivedSvTimeUncertaintyInNs);
+    SET(Cn0DbHz, measurement->cN0DbHz);
+    SET(PseudorangeRateMetersPerSecond, measurement->pseudorangeRateMps);
     SET(PseudorangeRateUncertaintyMetersPerSecond,
-        measurement->pseudorange_rate_uncertainty_mps);
+        measurement->pseudorangeRateUncertaintyMps);
     SET(AccumulatedDeltaRangeState,
-        static_cast<int32_t>(measurement->accumulated_delta_range_state));
-    SET(AccumulatedDeltaRangeMeters, measurement->accumulated_delta_range_m);
+        (static_cast<int32_t>(measurement->accumulatedDeltaRangeState)));
+    SET(AccumulatedDeltaRangeMeters, measurement->accumulatedDeltaRangeM);
     SET(AccumulatedDeltaRangeUncertaintyMeters,
-        measurement->accumulated_delta_range_uncertainty_m);
-    SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
-           CarrierFrequencyHz,
-           measurement->carrier_frequency_hz);
-    SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
-           CarrierCycles,
-           measurement->carrier_cycles);
-    SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE,
-           CarrierPhase,
-           measurement->carrier_phase);
-    SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
-           CarrierPhaseUncertainty,
-           measurement->carrier_phase_uncertainty);
-    SET(MultipathIndicator,
-        static_cast<int32_t>(measurement->multipath_indicator));
-    SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
+        measurement->accumulatedDeltaRangeUncertaintyM);
+
+    if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_CARRIER_FREQUENCY)) {
+        SET(CarrierFrequencyHz, measurement->carrierFrequencyHz);
+    }
+
+    if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_CARRIER_PHASE)) {
+        SET(CarrierPhase, measurement->carrierPhase);
+    }
+
+    if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_CARRIER_PHASE_UNCERTAINTY)) {
+        SET(CarrierPhaseUncertainty, measurement->carrierPhaseUncertainty);
+    }
+
+    SET(MultipathIndicator, static_cast<int32_t>(measurement->multipathIndicator));
+
+    if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_SNR)) {
+        SET(SnrInDb, measurement->snrDb);
+    }
 
     return object.get();
 }
 
-static jobjectArray translate_gps_measurements(JNIEnv* env,
-                                               GpsMeasurement* measurements,
-                                               size_t count) {
+jobject GnssMeasurementCallback::translateGnssClock(
+       JNIEnv* env, const IGnssMeasurementCallback::GnssClock* clock) {
+    JavaObject object(env, "android/location/GnssClock");
+
+    uint32_t flags = static_cast<uint32_t>(clock->gnssClockFlags);
+    if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_LEAP_SECOND)) {
+        SET(LeapSecond, static_cast<int32_t>(clock->leapSecond));
+    }
+
+    if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_TIME_UNCERTAINTY)) {
+        SET(TimeUncertaintyNanos, clock->timeUncertaintyNs);
+    }
+
+    if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_FULL_BIAS)) {
+        SET(FullBiasNanos, clock->fullBiasNs);
+    }
+
+    if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_BIAS)) {
+        SET(BiasNanos, clock->biasNs);
+    }
+
+    if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_BIAS_UNCERTAINTY)) {
+        SET(BiasUncertaintyNanos, clock->biasUncertaintyNs);
+    }
+
+    if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_DRIFT)) {
+        SET(DriftNanosPerSecond, clock->driftNsps);
+    }
+
+    if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_DRIFT_UNCERTAINTY)) {
+        SET(DriftUncertaintyNanosPerSecond, clock->driftUncertaintyNsps);
+    }
+
+    SET(TimeNanos, clock->timeNs);
+    SET(HardwareClockDiscontinuityCount, clock->hwClockDiscontinuityCount);
+
+    return object.get();
+}
+
+jobjectArray GnssMeasurementCallback::translateGnssMeasurements(JNIEnv* env,
+                                       const IGnssMeasurementCallback::GnssMeasurement*
+                                       measurements, size_t count) {
     if (count == 0) {
         return NULL;
     }
 
-    jclass gnssMeasurementClass = env->FindClass(
-            "android/location/GnssMeasurement");
+    jclass gnssMeasurementClass = env->FindClass("android/location/GnssMeasurement");
     jobjectArray gnssMeasurementArray = env->NewObjectArray(
             count,
             gnssMeasurementClass,
             NULL /* initialElement */);
 
     for (uint16_t i = 0; i < count; ++i) {
-        jobject gnssMeasurement = translate_gps_measurement(
+        jobject gnssMeasurement = translateGnssMeasurement(
             env,
             &measurements[i]);
         env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
@@ -1332,130 +673,789 @@
     return gnssMeasurementArray;
 }
 
-static jobjectArray translate_gnss_measurements(JNIEnv* env,
-                                                GnssMeasurement* measurements,
-                                                size_t count) {
-    if (count == 0) {
-        return NULL;
-    }
+void GnssMeasurementCallback::setMeasurementData(JNIEnv* env, jobject clock,
+                             jobjectArray measurementArray) {
+    jclass gnssMeasurementsEventClass =
+            env->FindClass("android/location/GnssMeasurementsEvent");
+    jmethodID gnssMeasurementsEventCtor =
+            env->GetMethodID(
+                    gnssMeasurementsEventClass,
+                    "<init>",
+                    "(Landroid/location/GnssClock;[Landroid/location/GnssMeasurement;)V");
 
-    jclass gnssMeasurementClass = env->FindClass(
-            "android/location/GnssMeasurement");
-    jobjectArray gnssMeasurementArray = env->NewObjectArray(
-            count,
-            gnssMeasurementClass,
-            NULL /* initialElement */);
+    jobject gnssMeasurementsEvent = env->NewObject(gnssMeasurementsEventClass,
+                                                   gnssMeasurementsEventCtor,
+                                                   clock,
+                                                   measurementArray);
 
-    for (uint16_t i = 0; i < count; ++i) {
-        jobject gnssMeasurement = translate_gnss_measurement(
-            env,
-            &measurements[i]);
-        env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
-        env->DeleteLocalRef(gnssMeasurement);
-    }
-
-    env->DeleteLocalRef(gnssMeasurementClass);
-    return gnssMeasurementArray;
-}
-
-static void set_measurement_data(JNIEnv *env,
-                                 jobject clock,
-                                 jobjectArray measurementArray) {
-    jclass gnssMeasurementsEventClass = env->FindClass(
-            "android/location/GnssMeasurementsEvent");
-    jmethodID gnssMeasurementsEventCtor = env->GetMethodID(
-        gnssMeasurementsEventClass,
-        "<init>",
-        "(Landroid/location/GnssClock;[Landroid/location/GnssMeasurement;)V");
-
-    jobject gnssMeasurementsEvent = env->NewObject(
-        gnssMeasurementsEventClass,
-        gnssMeasurementsEventCtor,
-        clock,
-        measurementArray);
-    env->CallVoidMethod(mCallbacksObj,
-                        method_reportMeasurementData,
-                        gnssMeasurementsEvent);
+    env->CallVoidMethod(mCallbacksObj, method_reportMeasurementData,
+                      gnssMeasurementsEvent);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
     env->DeleteLocalRef(gnssMeasurementsEventClass);
     env->DeleteLocalRef(gnssMeasurementsEvent);
 }
 
-static void measurement_callback(GpsData* data) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (data == NULL) {
-        ALOGE("Invalid data provided to gps_measurement_callback");
-        return;
-    }
-    if (data->size != sizeof(GpsData)) {
-        ALOGE("Invalid GpsData size found in gps_measurement_callback, "
-              "size=%zd",
-              data->size);
-        return;
-    }
-
-    jobject clock;
-    jobjectArray measurementArray;
-    clock = translate_gps_clock(env, &data->clock);
-    measurementArray = translate_gps_measurements(
-            env, data->measurements, data->measurement_count);
-    set_measurement_data(env, clock, measurementArray);
-
-    env->DeleteLocalRef(clock);
-    env->DeleteLocalRef(measurementArray);
-}
-
-static void gnss_measurement_callback(GnssData* data) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (data == NULL) {
-        ALOGE("Invalid data provided to gps_measurement_callback");
-        return;
-    }
-    if (data->size != sizeof(GnssData)) {
-        ALOGE("Invalid GnssData size found in gnss_measurement_callback, "
-              "size=%zd",
-              data->size);
-        return;
-    }
-
-    jobject clock;
-    jobjectArray measurementArray;
-    clock = translate_gnss_clock(env, &data->clock);
-    measurementArray = translate_gnss_measurements(
-            env, data->measurements, data->measurement_count);
-    set_measurement_data(env, clock, measurementArray);
-
-    env->DeleteLocalRef(clock);
-    env->DeleteLocalRef(measurementArray);
-}
-
-GpsMeasurementCallbacks sGpsMeasurementCallbacks = {
-    sizeof(GpsMeasurementCallbacks),
-    measurement_callback,
-    gnss_measurement_callback,
+/*
+ * GnssNiCallback implements callback methods required by the IGnssNi interface.
+ */
+struct GnssNiCallback : public IGnssNiCallback {
+    Return<void> niNotifyCb(const IGnssNiCallback::GnssNiNotification& notification)
+            override;
 };
 
+Return<void> GnssNiCallback::niNotifyCb(
+        const IGnssNiCallback::GnssNiNotification& notification) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jstring requestorId = env->NewStringUTF(notification.requestorId.c_str());
+    jstring text = env->NewStringUTF(notification.notificationMessage.c_str());
+
+    if (requestorId && text) {
+        env->CallVoidMethod(mCallbacksObj, method_reportNiNotification,
+                            notification.notificationId, notification.niType,
+                            notification.notifyFlags, notification.timeoutSec,
+                            notification.defaultResponse, requestorId, text,
+                            notification.requestorIdEncoding,
+                            notification.notificationIdEncoding);
+    } else {
+        ALOGE("%s: OOM Error\n", __func__);
+    }
+
+    if (requestorId) {
+        env->DeleteLocalRef(requestorId);
+    }
+
+    if (text) {
+        env->DeleteLocalRef(text);
+    }
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+/*
+ * AGnssCallback implements callback methods required by the IAGnss interface.
+ */
+struct AGnssCallback : public IAGnssCallback {
+    // Methods from ::android::hardware::gps::V1_0::IAGnssCallback follow.
+    Return<void> agnssStatusIpV6Cb(
+      const IAGnssCallback::AGnssStatusIpV6& agps_status) override;
+
+    Return<void> agnssStatusIpV4Cb(
+      const IAGnssCallback::AGnssStatusIpV4& agps_status) override;
+ private:
+    jbyteArray convertToIpV4(uint32_t ip);
+};
+
+Return<void> AGnssCallback::agnssStatusIpV6Cb(
+        const IAGnssCallback::AGnssStatusIpV6& agps_status) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jbyteArray byteArray = NULL;
+    bool isSupported = false;
+
+    byteArray = env->NewByteArray(16);
+    if (byteArray != NULL) {
+        env->SetByteArrayRegion(byteArray, 0, 16,
+                                (const jbyte*)(agps_status.ipV6Addr.data()));
+        isSupported = true;
+    } else {
+        ALOGE("Unable to allocate byte array for IPv6 address.");
+    }
+
+    IF_ALOGD() {
+        // log the IP for reference in case there is a bogus value pushed by HAL
+        char str[INET6_ADDRSTRLEN];
+        inet_ntop(AF_INET6, agps_status.ipV6Addr.data(), str, INET6_ADDRSTRLEN);
+        ALOGD("AGPS IP is v6: %s", str);
+    }
+
+    jsize byteArrayLength = byteArray != NULL ? env->GetArrayLength(byteArray) : 0;
+    ALOGV("Passing AGPS IP addr: size %d", byteArrayLength);
+    env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus,
+                        agps_status.type, agps_status.status, byteArray);
+
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+
+    if (byteArray) {
+        env->DeleteLocalRef(byteArray);
+    }
+
+    return Void();
+}
+
+Return<void> AGnssCallback::agnssStatusIpV4Cb(
+        const IAGnssCallback::AGnssStatusIpV4& agps_status) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jbyteArray byteArray = NULL;
+
+    uint32_t ipAddr = agps_status.ipV4Addr;
+    byteArray = convertToIpV4(ipAddr);
+
+    IF_ALOGD() {
+        /*
+         * log the IP for reference in case there is a bogus value pushed by
+         * HAL.
+         */
+        char str[INET_ADDRSTRLEN];
+        inet_ntop(AF_INET, &ipAddr, str, INET_ADDRSTRLEN);
+        ALOGD("AGPS IP is v4: %s", str);
+    }
+
+    jsize byteArrayLength =
+      byteArray != NULL ? env->GetArrayLength(byteArray) : 0;
+    ALOGV("Passing AGPS IP addr: size %d", byteArrayLength);
+    env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus,
+                      agps_status.type, agps_status.status, byteArray);
+
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+
+    if (byteArray) {
+        env->DeleteLocalRef(byteArray);
+    }
+    return Void();
+}
+
+jbyteArray AGnssCallback::convertToIpV4(uint32_t ip) {
+    if (INADDR_NONE == ip) {
+        return NULL;
+    }
+
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jbyteArray byteArray = env->NewByteArray(4);
+    if (byteArray == NULL) {
+        ALOGE("Unable to allocate byte array for IPv4 address");
+        return NULL;
+    }
+
+    jbyte ipv4[4];
+    ALOGV("Converting IPv4 address byte array (net_order) %x", ip);
+    memcpy(ipv4, &ip, sizeof(ipv4));
+    env->SetByteArrayRegion(byteArray, 0, 4, (const jbyte*)ipv4);
+    return byteArray;
+}
+
+/*
+ * AGnssRilCallback implements the callback methods required by the AGnssRil
+ * interface.
+ */
+struct AGnssRilCallback : IAGnssRilCallback {
+    Return<void> requestSetIdCb(IAGnssRilCallback::ID setIdFlag) override;
+    Return<void> requestRefLocCb() override;
+};
+
+Return<void> AGnssRilCallback::requestSetIdCb(IAGnssRilCallback::ID setIdFlag) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbacksObj, method_requestSetID, setIdFlag);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+Return<void> AGnssRilCallback::requestRefLocCb() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbacksObj, method_requestRefLocation);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
+    method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
+    method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
+    method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");
+    method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V");
+    method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");
+    method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V");
+    method_setGnssYearOfHardware = env->GetMethodID(clazz, "setGnssYearOfHardware", "(I)V");
+    method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
+    method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",
+            "(IIIIILjava/lang/String;Ljava/lang/String;II)V");
+    method_requestRefLocation = env->GetMethodID(clazz, "requestRefLocation", "()V");
+    method_requestSetID = env->GetMethodID(clazz, "requestSetID", "(I)V");
+    method_requestUtcTime = env->GetMethodID(clazz, "requestUtcTime", "()V");
+    method_reportGeofenceTransition = env->GetMethodID(clazz, "reportGeofenceTransition",
+            "(IIDDDFFFJIJ)V");
+    method_reportGeofenceStatus = env->GetMethodID(clazz, "reportGeofenceStatus",
+            "(IIDDDFFFJ)V");
+    method_reportGeofenceAddStatus = env->GetMethodID(clazz, "reportGeofenceAddStatus",
+            "(II)V");
+    method_reportGeofenceRemoveStatus = env->GetMethodID(clazz, "reportGeofenceRemoveStatus",
+            "(II)V");
+    method_reportGeofenceResumeStatus = env->GetMethodID(clazz, "reportGeofenceResumeStatus",
+            "(II)V");
+    method_reportGeofencePauseStatus = env->GetMethodID(clazz, "reportGeofencePauseStatus",
+            "(II)V");
+    method_reportMeasurementData = env->GetMethodID(
+            clazz,
+            "reportMeasurementData",
+            "(Landroid/location/GnssMeasurementsEvent;)V");
+    method_reportNavigationMessages = env->GetMethodID(
+            clazz,
+            "reportNavigationMessage",
+            "(Landroid/location/GnssNavigationMessage;)V");
+
+    // TODO(b/31632518)
+    gnssHal = IGnss::getService("gnss");
+    if (gnssHal != nullptr) {
+        auto result = gnssHal->getExtensionXtra([](const sp<IGnssXtra>& xtraIface) {
+            gnssXtraIface = xtraIface;
+        });
+
+        if (!result.getStatus().isOk()) {
+            ALOGD("Unable to get a handle to Xtra");
+        }
+
+        result = gnssHal->getExtensionAGnssRil([](const sp<IAGnssRil>& rilIface) {
+            agnssRilIface = rilIface;
+        });
+
+        if (!result.getStatus().isOk()) {
+            ALOGD("Unable to get a handle to AGnssRil");
+        }
+
+        result = gnssHal->getExtensionAGnss([](const sp<IAGnss>& assistedGnssIface) {
+            agnssIface = assistedGnssIface;
+        });
+
+        if (!result.getStatus().isOk()) {
+            ALOGD("Unable to get a handle to AGnss");
+        }
+
+        result = gnssHal->getExtensionGnssNavigationMessage(
+                [](const sp<IGnssNavigationMessage>& navigationMessageIface) {
+            gnssNavigationMessageIface = navigationMessageIface;
+        });
+
+        if (!result.getStatus().isOk()) {
+            ALOGD("Unable to get a handle to GnssNavigationMessage");
+        }
+
+        result = gnssHal->getExtensionGnssMeasurement([](
+                const sp<IGnssMeasurement>& measurementIface) {
+            gnssMeasurementIface = measurementIface;
+        });
+        if (!result.getStatus().isOk()) {
+            ALOGD("Unable to get a handle to GnssMeasurement");
+        }
+
+        result = gnssHal->getExtensionGnssDebug([](const sp<IGnssDebug>& debugIface) {
+            gnssDebugIface = debugIface;
+        });
+        if (!result.getStatus().isOk()) {
+            ALOGD("Unable to get a handle to GnssDebug");
+        }
+
+        result = gnssHal->getExtensionGnssNi([](const sp<IGnssNi>& niIface) {
+            gnssNiIface = niIface;
+        });
+        if (!result.getStatus().isOk()) {
+            ALOGD("Unable to get a handle to GnssNi");
+        }
+
+        result = gnssHal->getExtensionGnssConfiguration([](const sp<IGnssConfiguration>& configIface) {
+            gnssConfigurationIface = configIface;
+        });
+        if (!result.getStatus().isOk()) {
+            ALOGD("Unable to get a handle to GnssConfiguration");
+        }
+
+        result = gnssHal->getExtensionGnssGeofencing([](const sp<IGnssGeofencing>& geofenceIface) {
+            gnssGeofencingIface = geofenceIface;
+        });
+        if (!result.getStatus().isOk()) {
+            ALOGD("Unable to get a handle to GnssGeofencing");
+        }
+
+    } else {
+      ALOGE("Unable to get GPS service\n");
+    }
+    ProcessState::self()->setThreadPoolMaxThreadCount(0);
+    ProcessState::self()->startThreadPool();
+}
+
+static jboolean android_location_GnssLocationProvider_is_supported(
+        JNIEnv* /* env */, jclass /* clazz */) {
+    return (gnssHal != nullptr) ?  JNI_TRUE : JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_is_agps_ril_supported(
+        JNIEnv* /* env */, jclass /* clazz */) {
+    return (agnssRilIface != nullptr) ? JNI_TRUE : JNI_FALSE;
+}
+
+static jboolean android_location_gpsLocationProvider_is_gnss_configuration_supported(
+        JNIEnv* /* env */, jclass /* jclazz */) {
+    return (gnssConfigurationIface != nullptr) ? JNI_TRUE : JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject obj) {
+    /*
+     * This must be set before calling into the HAL library.
+     */
+    if (!mCallbacksObj)
+        mCallbacksObj = env->NewGlobalRef(obj);
+
+    sp<IGnssCallback> gnssCbIface = new GnssCallback();
+    /*
+     * Fail if the main interface fails to initialize
+     */
+    if (gnssHal == nullptr) {
+        ALOGE("Unable to Initialize GNSS HAL\n");
+        return JNI_FALSE;
+    }
+
+    auto result = gnssHal->setCallback(gnssCbIface);
+    if ((!result) || (!result.getStatus().isOk())) {
+        ALOGE("SetCallback for Gnss Interface fails\n");
+        return JNI_FALSE;
+    }
+
+    sp<IGnssXtraCallback> gnssXtraCbIface = new GnssXtraCallback();
+    if (gnssXtraIface == nullptr) {
+        ALOGE("Unable to initialize GNSS Xtra interface\n");
+    }
+
+    result = gnssXtraIface->setCallback(gnssXtraCbIface);
+    if ((!result) || (!result.getStatus().isOk())) {
+        gnssXtraIface = nullptr;
+        ALOGE("SetCallback for Gnss Xtra Interface fails\n");
+    }
+
+    sp<IAGnssCallback> aGnssCbIface = new AGnssCallback();
+    if (agnssIface != nullptr) {
+        agnssIface->setCallback(aGnssCbIface);
+    } else {
+        ALOGE("Unable to Initialize AGnss interface\n");
+    }
+
+    sp<IGnssGeofenceCallback> gnssGeofencingCbIface = new GnssGeofenceCallback();
+    if (gnssGeofencingIface != nullptr) {
+      gnssGeofencingIface->setCallback(gnssGeofencingCbIface);
+    } else {
+        ALOGE("Unable to initialize GNSS Geofencing interface\n");
+    }
+
+    sp<IGnssNiCallback> gnssNiCbIface = new GnssNiCallback();
+    if (gnssNiCbIface != nullptr) {
+        gnssNiIface->setCallback(gnssNiCbIface);
+    } else {
+        ALOGE("Unable to initialize GNSS NI interface\n");
+    }
+
+    return JNI_TRUE;
+}
+
+static void android_location_GnssLocationProvider_cleanup(JNIEnv* /* env */, jobject /* obj */) {
+    if (gnssHal != nullptr) {
+        gnssHal->cleanup();
+    }
+}
+
+static jboolean android_location_GnssLocationProvider_set_position_mode(JNIEnv* /* env */,
+        jobject /* obj */, jint mode, jint recurrence, jint min_interval, jint preferred_accuracy,
+        jint preferred_time) {
+    if (gnssHal != nullptr) {
+        auto result = gnssHal->setPositionMode(static_cast<IGnss::GnssPositionMode>(mode),
+                                     static_cast<IGnss::GnssPositionRecurrence>(recurrence),
+                                     min_interval,
+                                     preferred_accuracy,
+                                     preferred_time);
+        if (!result.getStatus().isOk()) {
+            ALOGE("%s: GNSS setPositionMode failed\n", __func__);
+            return JNI_FALSE;
+        } else {
+            return result;
+        }
+    } else {
+        return JNI_FALSE;
+    }
+}
+
+static jboolean android_location_GnssLocationProvider_start(JNIEnv* /* env */, jobject /* obj */) {
+    if (gnssHal != nullptr) {
+        auto result = gnssHal->start();
+        if (!result.getStatus().isOk()) {
+            return JNI_FALSE;
+        } else {
+            return result;
+        }
+    } else {
+        return JNI_FALSE;
+    }
+}
+
+static jboolean android_location_GnssLocationProvider_stop(JNIEnv* /* env */, jobject /* obj */) {
+    if (gnssHal != nullptr) {
+        auto result = gnssHal->stop();
+        if (!result.getStatus().isOk()) {
+            return JNI_FALSE;
+        } else {
+            return result;
+        }
+    } else {
+        return JNI_FALSE;
+    }
+}
+static void android_location_GnssLocationProvider_delete_aiding_data(JNIEnv* /* env */,
+                                                                    jobject /* obj */,
+                                                                    jint flags) {
+    if (gnssHal != nullptr) {
+        auto result = gnssHal->deleteAidingData(static_cast<IGnss::GnssAidingData>(flags));
+        if (!result.getStatus().isOk()) {
+            ALOGE("Error in deleting aiding data");
+        }
+    }
+}
+
+/*
+ * This enum is used by the read_sv_status method to combine the svid,
+ * constellation and svFlag fields.
+ */
+enum ShiftWidth: uint8_t {
+    SVID_SHIFT_WIDTH = 7,
+    CONSTELLATION_TYPE_SHIFT_WIDTH = 3
+};
+
+static jint android_location_GnssLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */,
+        jintArray svidWithFlagArray, jfloatArray cn0Array, jfloatArray elevArray,
+        jfloatArray azumArray) {
+    /*
+     * This method should only be called from within a call to reportSvStatus.
+     */
+    jint* svidWithFlags = env->GetIntArrayElements(svidWithFlagArray, 0);
+    jfloat* cn0s = env->GetFloatArrayElements(cn0Array, 0);
+    jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
+    jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
+
+    /*
+     * Read GNSS SV info.
+     */
+    for (size_t i = 0; i < GnssCallback::sGnssSvListSize; ++i) {
+        const IGnssCallback::GnssSvInfo& info = GnssCallback::sGnssSvList[i];
+        svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) |
+            (static_cast<uint32_t>(info.constellation) << CONSTELLATION_TYPE_SHIFT_WIDTH) |
+            static_cast<uint32_t>(info.svFlag);
+        cn0s[i] = info.cN0Dbhz;
+        elev[i] = info.elevationDegrees;
+        azim[i] = info.azimuthDegrees;
+    }
+
+    env->ReleaseIntArrayElements(svidWithFlagArray, svidWithFlags, 0);
+    env->ReleaseFloatArrayElements(cn0Array, cn0s, 0);
+    env->ReleaseFloatArrayElements(elevArray, elev, 0);
+    env->ReleaseFloatArrayElements(azumArray, azim, 0);
+    return static_cast<jint>(GnssCallback::sGnssSvListSize);
+}
+
+static void android_location_GnssLocationProvider_agps_set_reference_location_cellid(
+        JNIEnv* /* env */, jobject /* obj */, jint type, jint mcc, jint mnc, jint lac, jint cid) {
+    IAGnssRil::AGnssRefLocation location;
+
+    if (agnssRilIface == nullptr) {
+        ALOGE("No AGPS RIL interface in agps_set_reference_location_cellid");
+        return;
+    }
+
+    switch (static_cast<IAGnssRil::AGnssRefLocationType>(type)) {
+        case IAGnssRil::AGnssRefLocationType::GSM_CELLID:
+        case IAGnssRil::AGnssRefLocationType::UMTS_CELLID:
+          location.type = static_cast<IAGnssRil::AGnssRefLocationType>(type);
+          location.cellID.mcc = mcc;
+          location.cellID.mnc = mnc;
+          location.cellID.lac = lac;
+          location.cellID.cid = cid;
+          break;
+        default:
+            ALOGE("Neither a GSM nor a UMTS cellid (%s:%d).", __FUNCTION__, __LINE__);
+            return;
+            break;
+    }
+
+    agnssRilIface->setRefLocation(location);
+}
+
+static void android_location_GnssLocationProvider_agps_set_id(JNIEnv *env, jobject /* obj */,
+                                                             jint type, jstring  setid_string) {
+    if (agnssRilIface == nullptr) {
+        ALOGE("no AGPS RIL interface in agps_set_id");
+        return;
+    }
+
+    const char *setid = env->GetStringUTFChars(setid_string, NULL);
+    agnssRilIface->setSetId((IAGnssRil::SetIDType)type, setid);
+    env->ReleaseStringUTFChars(setid_string, setid);
+}
+
+static jint android_location_GnssLocationProvider_read_nmea(JNIEnv* env, jobject /* obj */,
+                                            jbyteArray nmeaArray, jint buffer_size) {
+    // this should only be called from within a call to reportNmea
+    jbyte* nmea = reinterpret_cast<jbyte *>(env->GetPrimitiveArrayCritical(nmeaArray, 0));
+    int length = GnssCallback::sNmeaStringLength;
+    if (length > buffer_size)
+        length = buffer_size;
+    memcpy(nmea, GnssCallback::sNmeaString, length);
+    env->ReleasePrimitiveArrayCritical(nmeaArray, nmea, JNI_ABORT);
+    return (jint) length;
+}
+
+static void android_location_GnssLocationProvider_inject_time(JNIEnv* /* env */, jobject /* obj */,
+        jlong time, jlong timeReference, jint uncertainty) {
+    if (gnssHal != nullptr) {
+        auto result = gnssHal->injectTime(time, timeReference, uncertainty);
+        if (!result || !result.getStatus().isOk()) {
+            ALOGE("%s: Gnss injectTime() failed", __func__);
+        }
+    }
+}
+
+static void android_location_GnssLocationProvider_inject_location(JNIEnv* /* env */,
+        jobject /* obj */, jdouble latitude, jdouble longitude, jfloat accuracy) {
+    if (gnssHal != nullptr) {
+        auto result = gnssHal->injectLocation(latitude, longitude, accuracy);
+        if (!result || !result.getStatus().isOk()) {
+            ALOGE("%s: Gnss injectLocation() failed", __func__);
+        }
+    }
+}
+
+static jboolean android_location_GnssLocationProvider_supports_xtra(
+        JNIEnv* /* env */, jobject /* obj */) {
+    return (gnssXtraIface != nullptr) ? JNI_TRUE : JNI_FALSE;
+}
+
+static void android_location_GnssLocationProvider_inject_xtra_data(JNIEnv* env, jobject /* obj */,
+        jbyteArray data, jint length) {
+    if (gnssXtraIface == nullptr) {
+        ALOGE("XTRA Interface not supported");
+        return;
+    }
+
+    jbyte* bytes = reinterpret_cast<jbyte *>(env->GetPrimitiveArrayCritical(data, 0));
+    gnssXtraIface->injectXtraData(std::string((const char*)bytes, length));
+    env->ReleasePrimitiveArrayCritical(data, bytes, JNI_ABORT);
+}
+
+static void android_location_GnssLocationProvider_agps_data_conn_open(
+        JNIEnv* env, jobject /* obj */, jstring apn, jint apnIpType) {
+    if (agnssIface == nullptr) {
+        ALOGE("no AGPS interface in agps_data_conn_open");
+        return;
+    }
+    if (apn == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return;
+    }
+
+    const char *apnStr = env->GetStringUTFChars(apn, NULL);
+
+    auto result = agnssIface->dataConnOpen(apnStr, static_cast<IAGnss::ApnIpType>(apnIpType));
+    if ((!result) || (!result.getStatus().isOk())) {
+        ALOGE("%s: Failed to set APN and its IP type", __func__);
+    }
+    env->ReleaseStringUTFChars(apn, apnStr);
+}
+
+static void android_location_GnssLocationProvider_agps_data_conn_closed(JNIEnv* /* env */,
+                                                                       jobject /* obj */) {
+    if (agnssIface == nullptr) {
+        ALOGE("%s: AGPS interface not supported", __func__);
+        return;
+    }
+
+    auto result = agnssIface->dataConnClosed();
+    if ((!result) || (!result.getStatus().isOk())) {
+        ALOGE("%s: Failed to close AGnss data connection", __func__);
+    }
+}
+
+static void android_location_GnssLocationProvider_agps_data_conn_failed(JNIEnv* /* env */,
+                                                                       jobject /* obj */) {
+    if (agnssIface == nullptr) {
+        ALOGE("%s: AGPS interface not supported", __func__);
+        return;
+    }
+
+    auto result = agnssIface->dataConnFailed();
+    if ((!result) || (!result.getStatus().isOk())) {
+        ALOGE("%s: Failed to notify unavailability of AGnss data connection", __func__);
+    }
+}
+
+static void android_location_GnssLocationProvider_set_agps_server(JNIEnv* env, jobject /* obj */,
+        jint type, jstring hostname, jint port) {
+    if (agnssIface == nullptr) {
+        ALOGE("no AGPS interface in set_agps_server");
+        return;
+    }
+
+    const char *c_hostname = env->GetStringUTFChars(hostname, NULL);
+    auto result = agnssIface->setServer(static_cast<IAGnssCallback::AGnssType>(type),
+                                       c_hostname,
+                                       port);
+    if ((!result) || (!result.getStatus().isOk())) {
+        ALOGE("%s: Failed to set AGnss host name and port", __func__);
+    }
+
+    env->ReleaseStringUTFChars(hostname, c_hostname);
+}
+
+static void android_location_GnssLocationProvider_send_ni_response(JNIEnv* /* env */,
+      jobject /* obj */, jint notifId, jint response) {
+    if (gnssNiIface == nullptr) {
+        ALOGE("no NI interface in send_ni_response");
+        return;
+    }
+
+    gnssNiIface->respond(notifId, static_cast<IGnssNiCallback::GnssUserResponseType>(response));
+}
+
+static jstring android_location_GnssLocationProvider_get_internal_state(JNIEnv* env,
+                                                                       jobject /* obj */) {
+    jstring result = NULL;
+    /*
+     * TODO(b/33089503) : Create a jobject to represent GnssDebug.
+     */
+    if (gnssDebugIface != nullptr) {
+        IGnssDebug::DebugData data;
+        gnssDebugIface->getDebugData([&data](const IGnssDebug::DebugData& debugData) {
+            data = debugData;
+        });
+
+        std::stringstream internalState;
+        if (data.position.valid) {
+            internalState << "Gnss Location Data:: LatitudeDegrees: " << data.position.latitudeDegrees
+                          << ", LongitudeDegrees: " << data.position.longitudeDegrees
+                          << ", altitudeMeters: " << data.position.altitudeMeters
+                          << ", accuracyMeters: " << data.position.accuracyMeters
+                          << ", ageSeconds: " << data.position.ageSeconds << std::endl;
+        }
+
+        if (data.time.valid) {
+            internalState << "Gnss Time Data:: timeEstimate: " << data.time.timeEstimate
+                          << ", timeUncertaintyNs: " << data.time.timeUncertaintyNs << std::endl;
+        }
+
+        if (data.satelliteDataArray.size() != 0) {
+            internalState << "Satellite Data:: ";
+        }
+
+        for (size_t i = 0; i < data.satelliteDataArray.size(); i++) {
+            internalState << "svid: " << data.satelliteDataArray[i].svid
+                          << ", constellation: "
+                          << static_cast<uint32_t>(data.satelliteDataArray[i].constellation)
+                          << ", ephemerisType: "
+                          << static_cast<uint32_t>(data.satelliteDataArray[i].ephemerisType)
+                          << ", ephemerisAgeSeconds: "
+                          << data.satelliteDataArray[i].ephemerisAgeSeconds << std::endl;
+        }
+        result = env->NewStringUTF(internalState.str().c_str());
+    }
+    return result;
+}
+
+static void android_location_GnssLocationProvider_update_network_state(JNIEnv* env,
+                                                                       jobject /* obj */,
+                                                                       jboolean connected,
+                                                                       jint type,
+                                                                       jboolean roaming,
+                                                                       jboolean available,
+                                                                       jstring extraInfo,
+                                                                       jstring apn) {
+    if (agnssRilIface != nullptr) {
+        auto result = agnssRilIface->updateNetworkState(connected,
+                                                       static_cast<IAGnssRil::NetworkType>(type),
+                                                       roaming);
+        if ((!result) || (!result.getStatus().isOk())) {
+            ALOGE("updateNetworkState failed");
+        }
+
+        const char *c_apn = env->GetStringUTFChars(apn, NULL);
+        result = agnssRilIface->updateNetworkAvailability(available, c_apn);
+        if ((!result) || (!result.getStatus().isOk())) {
+            ALOGE("updateNetworkAvailability failed");
+        }
+
+        env->ReleaseStringUTFChars(apn, c_apn);
+    } else {
+        ALOGE("AGnssRilInterface does not exist");
+    }
+}
+
+static jboolean android_location_GnssLocationProvider_is_geofence_supported(
+        JNIEnv* /* env */, jobject /* obj */) {
+    return (gnssGeofencingIface != nullptr) ? JNI_TRUE : JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_add_geofence(JNIEnv* /* env */,
+        jobject /* obj */, jint geofenceId, jdouble latitude, jdouble longitude, jdouble radius,
+        jint last_transition, jint monitor_transition, jint notification_responsiveness,
+        jint unknown_timer) {
+    if (gnssGeofencingIface != nullptr) {
+        auto result = gnssGeofencingIface->addGeofence(
+                geofenceId, latitude, longitude, radius,
+                static_cast<IGnssGeofenceCallback::GeofenceTransition>(last_transition),
+                monitor_transition, notification_responsiveness, unknown_timer);
+        return boolToJbool(result.getStatus().isOk());
+    } else {
+        ALOGE("Geofence Interface not available");
+    }
+    return JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_remove_geofence(JNIEnv* /* env */,
+        jobject /* obj */, jint geofenceId) {
+    if (gnssGeofencingIface != nullptr) {
+        auto result = gnssGeofencingIface->removeGeofence(geofenceId);
+        return boolToJbool(result.getStatus().isOk());
+    } else {
+        ALOGE("Geofence interface not available");
+    }
+    return JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_pause_geofence(JNIEnv* /* env */,
+        jobject /* obj */, jint geofenceId) {
+    if (gnssGeofencingIface != nullptr) {
+        auto result = gnssGeofencingIface->pauseGeofence(geofenceId);
+        return boolToJbool(result.getStatus().isOk());
+    } else {
+        ALOGE("Geofence interface not available");
+    }
+    return JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_resume_geofence(JNIEnv* /* env */,
+        jobject /* obj */, jint geofenceId, jint monitor_transition) {
+    if (gnssGeofencingIface != nullptr) {
+        auto result = gnssGeofencingIface->resumeGeofence(geofenceId, monitor_transition);
+        return boolToJbool(result.getStatus().isOk());
+    } else {
+        ALOGE("Geofence interface not available");
+    }
+    return JNI_FALSE;
+}
+
 static jboolean android_location_GnssLocationProvider_is_measurement_supported(
-        JNIEnv* env,
-        jclass clazz) {
-    if (sGpsMeasurementInterface != NULL) {
+    JNIEnv* env, jclass clazz) {
+    if (gnssMeasurementIface != nullptr) {
         return JNI_TRUE;
     }
+
     return JNI_FALSE;
 }
 
 static jboolean android_location_GnssLocationProvider_start_measurement_collection(
         JNIEnv* env,
         jobject obj) {
-    if (sGpsMeasurementInterface == NULL) {
-        ALOGE("Measurement interface is not available.");
+    if (gnssMeasurementIface == nullptr) {
+        ALOGE("GNSS Measurement interface is not available.");
         return JNI_FALSE;
     }
 
-    int result = sGpsMeasurementInterface->init(&sGpsMeasurementCallbacks);
-    if (result != GPS_GEOFENCE_OPERATION_SUCCESS) {
-        ALOGE("An error has been found on GpsMeasurementInterface::init, status=%d", result);
+    sp<GnssMeasurementCallback> cbIface = new GnssMeasurementCallback();
+    IGnssMeasurement::GnssMeasurementStatus result = gnssMeasurementIface->setCallback(cbIface);
+    if (result != IGnssMeasurement::GnssMeasurementStatus::SUCCESS) {
+        ALOGE("An error has been found on GnssMeasurementInterface::init, status=%d",
+              static_cast<int32_t>(result));
         return JNI_FALSE;
+    } else {
+      ALOGD("gnss measurement infc has been enabled");
     }
 
     return JNI_TRUE;
@@ -1464,104 +1464,19 @@
 static jboolean android_location_GnssLocationProvider_stop_measurement_collection(
         JNIEnv* env,
         jobject obj) {
-    if (sGpsMeasurementInterface == NULL) {
+    if (gnssMeasurementIface == nullptr) {
         ALOGE("Measurement interface not available");
         return JNI_FALSE;
     }
 
-    sGpsMeasurementInterface->close();
-    return JNI_TRUE;
+    auto result = gnssMeasurementIface->close();
+    return boolToJbool(result.getStatus().isOk());
 }
 
-static jobject translate_gps_navigation_message(JNIEnv* env, GpsNavigationMessage* message) {
-    size_t dataLength = message->data_length;
-    uint8_t* data = message->data;
-    if (dataLength == 0 || data == NULL) {
-        ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
-        return NULL;
-    }
-    JavaObject object(env, "android/location/GnssNavigationMessage");
-    SET(Svid, static_cast<int32_t>(message->prn));
-    if (message->prn >=1 && message->prn <= 32) {
-        SET(ConstellationType, static_cast<int32_t>(GNSS_CONSTELLATION_GPS));
-        // Legacy driver doesn't set the higher byte to constellation type
-        // correctly. Set the higher byte to 'GPS'.
-        SET(Type, static_cast<int32_t>(message->type | 0x0100));
-    } else {
-        ALOGD("Unknown constellation type with Svid = %d.", message->prn);
-        SET(ConstellationType,
-            static_cast<int32_t>(GNSS_CONSTELLATION_UNKNOWN));
-        SET(Type, static_cast<int32_t>(GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN));
-    }
-    SET(MessageId, static_cast<int32_t>(message->message_id));
-    SET(SubmessageId, static_cast<int32_t>(message->submessage_id));
-    object.callSetter("setData", data, dataLength);
-    SET(Status, static_cast<int32_t>(message->status));
-    return object.get();
-}
-
-static jobject translate_gnss_navigation_message(
-        JNIEnv* env, GnssNavigationMessage* message) {
-    size_t dataLength = message->data_length;
-    uint8_t* data = message->data;
-    if (dataLength == 0 || data == NULL) {
-        ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
-        return NULL;
-    }
-    JavaObject object(env, "android/location/GnssNavigationMessage");
-    SET(Type, static_cast<int32_t>(message->type));
-    SET(Svid, static_cast<int32_t>(message->svid));
-    SET(MessageId, static_cast<int32_t>(message->message_id));
-    SET(SubmessageId, static_cast<int32_t>(message->submessage_id));
-    object.callSetter("setData", data, dataLength);
-    SET(Status, static_cast<int32_t>(message->status));
-    return object.get();
-}
-
-static void navigation_message_callback(GpsNavigationMessage* message) {
-    if (message == NULL) {
-        ALOGE("Invalid Navigation Message provided to callback");
-        return;
-    }
-    if (message->size != sizeof(GpsNavigationMessage)) {
-        ALOGE("Invalid GpsNavigationMessage size found: %zd", message->size);
-        return;
-    }
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jobject navigationMessage = translate_gps_navigation_message(env, message);
-    env->CallVoidMethod(mCallbacksObj,
-                        method_reportNavigationMessages,
-                        navigationMessage);
-    env->DeleteLocalRef(navigationMessage);
-}
-
-static void gnss_navigation_message_callback(GnssNavigationMessage* message) {
-    if (message == NULL) {
-        ALOGE("Invalid Navigation Message provided to callback");
-        return;
-    }
-    if (message->size != sizeof(GnssNavigationMessage)) {
-        ALOGE("Invalid GnssNavigationMessage size found: %zd", message->size);
-        return;
-    }
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jobject navigationMessage = translate_gnss_navigation_message(env, message);
-    env->CallVoidMethod(mCallbacksObj,
-                        method_reportNavigationMessages,
-                        navigationMessage);
-    env->DeleteLocalRef(navigationMessage);
-}
-
-GpsNavigationMessageCallbacks sGpsNavigationMessageCallbacks = {
-    sizeof(GpsNavigationMessageCallbacks),
-    navigation_message_callback,
-    gnss_navigation_message_callback,
-};
-
 static jboolean android_location_GnssLocationProvider_is_navigation_message_supported(
         JNIEnv* env,
         jclass clazz) {
-    if(sGpsNavigationMessageInterface != NULL) {
+    if (gnssNavigationMessageIface != nullptr) {
         return JNI_TRUE;
     }
     return JNI_FALSE;
@@ -1570,14 +1485,18 @@
 static jboolean android_location_GnssLocationProvider_start_navigation_message_collection(
         JNIEnv* env,
         jobject obj) {
-    if (sGpsNavigationMessageInterface == NULL) {
+    if (gnssNavigationMessageIface == nullptr) {
         ALOGE("Navigation Message interface is not available.");
         return JNI_FALSE;
     }
 
-    int result = sGpsNavigationMessageInterface->init(&sGpsNavigationMessageCallbacks);
-    if (result != GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS) {
-        ALOGE("An error has been found in %s: %d", __FUNCTION__, result);
+    sp<IGnssNavigationMessageCallback> gnssNavigationMessageCbIface =
+            new GnssNavigationMessageCallback();
+    IGnssNavigationMessage::GnssNavigationMessageStatus result =
+            gnssNavigationMessageIface->setCallback(gnssNavigationMessageCbIface);
+
+    if (result != IGnssNavigationMessage::GnssNavigationMessageStatus::SUCCESS) {
+        ALOGE("An error has been found in %s: %d", __FUNCTION__, static_cast<int32_t>(result));
         return JNI_FALSE;
     }
 
@@ -1587,127 +1506,255 @@
 static jboolean android_location_GnssLocationProvider_stop_navigation_message_collection(
         JNIEnv* env,
         jobject obj) {
-    if (sGpsNavigationMessageInterface == NULL) {
+    if (gnssNavigationMessageIface == nullptr) {
         ALOGE("Navigation Message interface is not available.");
         return JNI_FALSE;
     }
 
-    sGpsNavigationMessageInterface->close();
-    return JNI_TRUE;
+    auto result = gnssNavigationMessageIface->close();
+    return boolToJbool(result.getStatus().isOk());
 }
 
-static void android_location_GnssLocationProvider_configuration_update(JNIEnv* env, jobject obj,
-        jstring config_content)
-{
-    if (!sGnssConfigurationInterface) {
-        ALOGE("no GPS configuration interface in configuraiton_update");
-        return;
+static jboolean android_location_GnssLocationProvider_set_emergency_supl_pdn(JNIEnv*,
+                                                                    jobject,
+                                                                    jint emergencySuplPdn) {
+    if (gnssConfigurationIface == nullptr) {
+        ALOGE("no GNSS configuration interface available");
+        return JNI_FALSE;
     }
-    const char *data = env->GetStringUTFChars(config_content, NULL);
-    ALOGD("GPS configuration:\n %s", data);
-    sGnssConfigurationInterface->configuration_update(
-            data, env->GetStringUTFLength(config_content));
-    env->ReleaseStringUTFChars(config_content, data);
+
+    auto result = gnssConfigurationIface->setEmergencySuplPdn(emergencySuplPdn);
+    if (result.getStatus().isOk()) {
+        return result;
+    } else {
+        return JNI_FALSE;
+    }
+}
+
+static jboolean android_location_GnssLocationProvider_set_supl_version(JNIEnv*,
+                                                                    jobject,
+                                                                    jint version) {
+    if (gnssConfigurationIface == nullptr) {
+        ALOGE("no GNSS configuration interface available");
+        return JNI_FALSE;
+    }
+    auto result = gnssConfigurationIface->setSuplVersion(version);
+    if (result.getStatus().isOk()) {
+        return result;
+    } else {
+        return JNI_FALSE;
+    }
+}
+
+static jboolean android_location_GnssLocationProvider_set_supl_es(JNIEnv*,
+                                                                    jobject,
+                                                                    jint suplEs) {
+    if (gnssConfigurationIface == nullptr) {
+        ALOGE("no GNSS configuration interface available");
+        return JNI_FALSE;
+    }
+
+    auto result = gnssConfigurationIface->setSuplEs(suplEs);
+    if (result.getStatus().isOk()) {
+        return result;
+    } else {
+        return JNI_FALSE;
+    }
+}
+
+static jboolean android_location_GnssLocationProvider_set_supl_mode(JNIEnv*,
+                                                                    jobject,
+                                                                    jint mode) {
+    if (gnssConfigurationIface == nullptr) {
+        ALOGE("no GNSS configuration interface available");
+        return JNI_FALSE;
+    }
+
+    auto result = gnssConfigurationIface->setSuplMode(mode);
+    if (result.getStatus().isOk()) {
+        return result;
+    } else {
+        return JNI_FALSE;
+    }
+}
+
+static jboolean android_location_GnssLocationProvider_set_gps_lock(JNIEnv*,
+                                                                   jobject,
+                                                                   jint gpsLock) {
+    if (gnssConfigurationIface == nullptr) {
+        ALOGE("no GNSS configuration interface available");
+        return JNI_FALSE;
+    }
+
+    auto result = gnssConfigurationIface->setGpsLock(gpsLock);
+    if (result.getStatus().isOk()) {
+        return result;
+    } else {
+        return JNI_FALSE;
+    }
+}
+
+static jboolean android_location_GnssLocationProvider_set_lpp_profile(JNIEnv*,
+                                                                   jobject,
+                                                                   jint lppProfile) {
+    if (gnssConfigurationIface == nullptr) {
+        ALOGE("no GNSS configuration interface available");
+        return JNI_FALSE;
+    }
+
+    auto result = gnssConfigurationIface->setLppProfile(lppProfile);
+
+    if (result.getStatus().isOk()) {
+        return result;
+    } else {
+        return JNI_FALSE;
+    }
+}
+
+static jboolean android_location_GnssLocationProvider_set_gnss_pos_protocol_select(JNIEnv*,
+                                                                   jobject,
+                                                                   jint gnssPosProtocol) {
+    if (gnssConfigurationIface == nullptr) {
+        ALOGE("no GNSS configuration interface available");
+        return JNI_FALSE;
+    }
+
+    auto result = gnssConfigurationIface->setGlonassPositioningProtocol(gnssPosProtocol);
+    if (result.getStatus().isOk()) {
+        return result;
+    } else {
+        return JNI_FALSE;
+    }
 }
 
 static const JNINativeMethod sMethods[] = {
      /* name, signature, funcPtr */
-    {"class_init_native", "()V", (void *)android_location_GnssLocationProvider_class_init_native},
-    {"native_is_supported", "()Z", (void*)android_location_GnssLocationProvider_is_supported},
+    {"class_init_native", "()V", reinterpret_cast<void *>(
+            android_location_GnssLocationProvider_class_init_native)},
+    {"native_is_supported", "()Z", reinterpret_cast<void *>(
+            android_location_GnssLocationProvider_is_supported)},
     {"native_is_agps_ril_supported", "()Z",
-            (void*)android_location_GnssLocationProvider_is_agps_ril_supported},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_is_agps_ril_supported)},
     {"native_is_gnss_configuration_supported", "()Z",
-            (void*)android_location_gpsLocationProvider_is_gnss_configuration_supported},
-    {"native_init", "()Z", (void*)android_location_GnssLocationProvider_init},
-    {"native_cleanup", "()V", (void*)android_location_GnssLocationProvider_cleanup},
+            reinterpret_cast<void *>(
+                    android_location_gpsLocationProvider_is_gnss_configuration_supported)},
+    {"native_init", "()Z", reinterpret_cast<void *>(android_location_GnssLocationProvider_init)},
+    {"native_cleanup", "()V", reinterpret_cast<void *>(
+            android_location_GnssLocationProvider_cleanup)},
     {"native_set_position_mode",
             "(IIIII)Z",
-            (void*)android_location_GnssLocationProvider_set_position_mode},
-    {"native_start", "()Z", (void*)android_location_GnssLocationProvider_start},
-    {"native_stop", "()Z", (void*)android_location_GnssLocationProvider_stop},
+            reinterpret_cast<void*>(android_location_GnssLocationProvider_set_position_mode)},
+    {"native_start", "()Z", reinterpret_cast<void*>(android_location_GnssLocationProvider_start)},
+    {"native_stop", "()Z", reinterpret_cast<void*>(android_location_GnssLocationProvider_stop)},
     {"native_delete_aiding_data",
             "(I)V",
-            (void*)android_location_GnssLocationProvider_delete_aiding_data},
+            reinterpret_cast<void*>(android_location_GnssLocationProvider_delete_aiding_data)},
     {"native_read_sv_status",
             "([I[F[F[F)I",
-            (void*)android_location_GnssLocationProvider_read_sv_status},
-    {"native_read_nmea", "([BI)I", (void*)android_location_GnssLocationProvider_read_nmea},
-    {"native_inject_time", "(JJI)V", (void*)android_location_GnssLocationProvider_inject_time},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_read_sv_status)},
+    {"native_read_nmea", "([BI)I", reinterpret_cast<void *>(
+            android_location_GnssLocationProvider_read_nmea)},
+    {"native_inject_time", "(JJI)V", reinterpret_cast<void *>(
+            android_location_GnssLocationProvider_inject_time)},
     {"native_inject_location",
             "(DDF)V",
-            (void*)android_location_GnssLocationProvider_inject_location},
-    {"native_supports_xtra", "()Z", (void*)android_location_GnssLocationProvider_supports_xtra},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_inject_location)},
+    {"native_supports_xtra", "()Z", reinterpret_cast<void *>(
+            android_location_GnssLocationProvider_supports_xtra)},
     {"native_inject_xtra_data",
             "([BI)V",
-            (void*)android_location_GnssLocationProvider_inject_xtra_data},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_inject_xtra_data)},
     {"native_agps_data_conn_open",
             "(Ljava/lang/String;I)V",
-            (void*)android_location_GnssLocationProvider_agps_data_conn_open},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_data_conn_open)},
     {"native_agps_data_conn_closed",
             "()V",
-            (void*)android_location_GnssLocationProvider_agps_data_conn_closed},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_data_conn_closed)},
     {"native_agps_data_conn_failed",
             "()V",
-            (void*)android_location_GnssLocationProvider_agps_data_conn_failed},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_data_conn_failed)},
     {"native_agps_set_id",
             "(ILjava/lang/String;)V",
-            (void*)android_location_GnssLocationProvider_agps_set_id},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_set_id)},
     {"native_agps_set_ref_location_cellid",
             "(IIIII)V",
-            (void*)android_location_GnssLocationProvider_agps_set_reference_location_cellid},
+            reinterpret_cast<void *>(
+                    android_location_GnssLocationProvider_agps_set_reference_location_cellid)},
     {"native_set_agps_server",
             "(ILjava/lang/String;I)V",
-            (void*)android_location_GnssLocationProvider_set_agps_server},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_set_agps_server)},
     {"native_send_ni_response",
             "(II)V",
-            (void*)android_location_GnssLocationProvider_send_ni_response},
-    {"native_agps_ni_message",
-            "([BI)V",
-            (void *)android_location_GnssLocationProvider_agps_send_ni_message},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_send_ni_response)},
     {"native_get_internal_state",
             "()Ljava/lang/String;",
-            (void*)android_location_GnssLocationProvider_get_internal_state},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_get_internal_state)},
     {"native_update_network_state",
             "(ZIZZLjava/lang/String;Ljava/lang/String;)V",
-            (void*)android_location_GnssLocationProvider_update_network_state },
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_update_network_state)},
     {"native_is_geofence_supported",
             "()Z",
-            (void*) android_location_GnssLocationProvider_is_geofence_supported},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_is_geofence_supported)},
     {"native_add_geofence",
             "(IDDDIIII)Z",
-            (void *)android_location_GnssLocationProvider_add_geofence},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_add_geofence)},
     {"native_remove_geofence",
             "(I)Z",
-            (void *)android_location_GnssLocationProvider_remove_geofence},
-    {"native_pause_geofence", "(I)Z", (void *)android_location_GnssLocationProvider_pause_geofence},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_remove_geofence)},
+    {"native_pause_geofence", "(I)Z", reinterpret_cast<void *>(
+            android_location_GnssLocationProvider_pause_geofence)},
     {"native_resume_geofence",
             "(II)Z",
-            (void *)android_location_GnssLocationProvider_resume_geofence},
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_resume_geofence)},
     {"native_is_measurement_supported",
             "()Z",
-            (void*) android_location_GnssLocationProvider_is_measurement_supported},
+            reinterpret_cast<void *>(
+                    android_location_GnssLocationProvider_is_measurement_supported)},
     {"native_start_measurement_collection",
             "()Z",
-            (void*) android_location_GnssLocationProvider_start_measurement_collection},
+            reinterpret_cast<void *>(
+                    android_location_GnssLocationProvider_start_measurement_collection)},
     {"native_stop_measurement_collection",
             "()Z",
-            (void*) android_location_GnssLocationProvider_stop_measurement_collection},
+            reinterpret_cast<void *>(
+                    android_location_GnssLocationProvider_stop_measurement_collection)},
     {"native_is_navigation_message_supported",
             "()Z",
-            (void*) android_location_GnssLocationProvider_is_navigation_message_supported},
+            reinterpret_cast<void *>(
+                    android_location_GnssLocationProvider_is_navigation_message_supported)},
     {"native_start_navigation_message_collection",
             "()Z",
-            (void*) android_location_GnssLocationProvider_start_navigation_message_collection},
+            reinterpret_cast<void *>(
+                    android_location_GnssLocationProvider_start_navigation_message_collection)},
     {"native_stop_navigation_message_collection",
             "()Z",
-            (void*) android_location_GnssLocationProvider_stop_navigation_message_collection},
-    {"native_configuration_update",
-            "(Ljava/lang/String;)V",
-            (void*)android_location_GnssLocationProvider_configuration_update},
+            reinterpret_cast<void *>(
+                    android_location_GnssLocationProvider_stop_navigation_message_collection)},
+    {"native_set_supl_es",
+            "(I)Z",
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_set_supl_es)},
+    {"native_set_supl_version",
+            "(I)Z",
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_set_supl_version)},
+    {"native_set_supl_mode",
+            "(I)Z",
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_set_supl_mode)},
+    {"native_set_lpp_profile",
+            "(I)Z",
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_set_lpp_profile)},
+    {"native_set_gnss_pos_protocol_select",
+            "(I)Z",
+            reinterpret_cast<void *>(
+                    android_location_GnssLocationProvider_set_gnss_pos_protocol_select)},
+    {"native_set_gps_lock",
+            "(I)Z",
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_set_gps_lock)},
+    {"native_set_emergency_supl_pdn",
+            "(I)Z",
+            reinterpret_cast<void *>(android_location_GnssLocationProvider_set_emergency_supl_pdn)},
 };
 
-int register_android_server_location_GnssLocationProvider(JNIEnv* env)
-{
+int register_android_server_location_GnssLocationProvider(JNIEnv* env) {
     return jniRegisterNativeMethods(
             env,
             "com/android/server/location/GnssLocationProvider",