Snap for 8562061 from a3344c8386fa80b7a2ffd53f6e7612b4ec20fb5e to mainline-media-release

Change-Id: I42c4cd3ab752c44171ff19bd14de2a9aeb49de6f
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..3c3e893
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,65 @@
+soong_namespace {
+}
+
+package {
+    default_applicable_licenses: ["hardware_qcom_sm7250_gps_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+    name: "hardware_qcom_sm7250_gps_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+        "SPDX-license-identifier-BSD",
+        "legacy_not_a_contribution",
+    ],
+    // large-scale-change unable to identify any license_text files
+}
+
+GNSS_CFLAGS = [
+    "-Werror",
+    "-Wno-error=unused-parameter",
+    "-Wno-error=macro-redefined",
+    "-Wno-error=reorder",
+    "-Wno-error=missing-braces",
+    "-Wno-error=self-assign",
+    "-Wno-error=enum-conversion",
+    "-Wno-error=logical-op-parentheses",
+    "-Wno-error=null-arithmetic",
+    "-Wno-error=null-conversion",
+    "-Wno-error=parentheses-equality",
+    "-Wno-error=undefined-bool-conversion",
+    "-Wno-error=tautological-compare",
+    "-Wno-error=switch",
+    "-Wno-error=date-time",
+]
+
+/* Activate the following for debug purposes only,
+   comment out for production */
+GNSS_SANITIZE_DIAG = {
+/*
+    diag: {
+        cfi: true,
+        misc_undefined: [
+            "bounds",
+            "null",
+            "unreachable",
+            "integer",
+        ],
+    },
+*/
+}
diff --git a/Android.mk b/Android.mk
index f1088a4..88bb0f4 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,5 +1,41 @@
 ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),)
-LOCAL_PATH := $(call my-dir)
-include $(LOCAL_PATH)/build/target_specific_features.mk
-include $(call all-makefiles-under,$(LOCAL_PATH))
+
+# Set required flags
+GNSS_CFLAGS := \
+    -Werror \
+    -Wno-error=unused-parameter \
+    -Wno-error=macro-redefined \
+    -Wno-error=reorder \
+    -Wno-error=missing-braces \
+    -Wno-error=self-assign \
+    -Wno-error=enum-conversion \
+    -Wno-error=logical-op-parentheses \
+    -Wno-error=null-arithmetic \
+    -Wno-error=null-conversion \
+    -Wno-error=parentheses-equality \
+    -Wno-error=undefined-bool-conversion \
+    -Wno-error=tautological-compare \
+    -Wno-error=switch \
+    -Wno-error=date-time
+
+GNSS_HIDL_VERSION = 2.1
+
+GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += msm8937
+GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += msm8953
+GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += msm8998
+GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += apq8098_latv
+GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += sdm710
+GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += qcs605
+GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += sdm845
+GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += sdm660
+
+ifneq (,$(filter $(GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST),$(TARGET_BOARD_PLATFORM)))
+GNSS_HIDL_LEGACY_MEASURMENTS = true
 endif
+
+LOCAL_PATH := $(call my-dir)
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
+GNSS_SANITIZE_DIAG := cfi bounds null unreachable integer address
+
+endif # ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),)
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..d97975c
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,3 @@
+third_party {
+  license_type: NOTICE
+}
diff --git a/android/1.0/AGnssRil.cpp b/android/1.0/AGnssRil.cpp
index 0437cf1..6879174 100644
--- a/android/1.0/AGnssRil.cpp
+++ b/android/1.0/AGnssRil.cpp
@@ -54,32 +54,33 @@
     const int NetworkType_BLUETOOTH = 7;
     const int NetworkType_ETHERNET = 9;
     const int NetworkType_PROXY = 16;
+    std::string apn("");
 
     // for XTRA
     if (nullptr != mGnss && ( nullptr != mGnss->getGnssInterface() )) {
-        int8_t typeout = loc_core::NetworkInfoDataItemBase::TYPE_UNKNOWN;
+        int8_t typeout = loc_core::TYPE_UNKNOWN;
         switch(type)
         {
             case IAGnssRil::NetworkType::MOBILE:
-                typeout = loc_core::NetworkInfoDataItemBase::TYPE_MOBILE;
+                typeout = loc_core::TYPE_MOBILE;
                 break;
             case IAGnssRil::NetworkType::WIFI:
-                typeout = loc_core::NetworkInfoDataItemBase::TYPE_WIFI;
+                typeout = loc_core::TYPE_WIFI;
                 break;
             case IAGnssRil::NetworkType::MMS:
-                typeout = loc_core::NetworkInfoDataItemBase::TYPE_MMS;
+                typeout = loc_core::TYPE_MMS;
                 break;
             case IAGnssRil::NetworkType::SUPL:
-                typeout = loc_core::NetworkInfoDataItemBase::TYPE_SUPL;
+                typeout = loc_core::TYPE_SUPL;
                 break;
             case IAGnssRil::NetworkType::DUN:
-                typeout = loc_core::NetworkInfoDataItemBase::TYPE_DUN;
+                typeout = loc_core::TYPE_DUN;
                 break;
             case IAGnssRil::NetworkType::HIPRI:
-                typeout = loc_core::NetworkInfoDataItemBase::TYPE_HIPRI;
+                typeout = loc_core::TYPE_HIPRI;
                 break;
             case IAGnssRil::NetworkType::WIMAX:
-                typeout = loc_core::NetworkInfoDataItemBase::TYPE_WIMAX;
+                typeout = loc_core::TYPE_WIMAX;
                 break;
             default:
                 {
@@ -88,21 +89,21 @@
                     switch(networkType)
                     {
                         case NetworkType_BLUETOOTH:
-                            typeout = loc_core::NetworkInfoDataItemBase::TYPE_BLUETOOTH;
+                            typeout = loc_core::TYPE_BLUETOOTH;
                             break;
                         case NetworkType_ETHERNET:
-                            typeout = loc_core::NetworkInfoDataItemBase::TYPE_ETHERNET;
+                            typeout = loc_core::TYPE_ETHERNET;
                             break;
                         case NetworkType_PROXY:
-                            typeout = loc_core::NetworkInfoDataItemBase::TYPE_PROXY;
+                            typeout = loc_core::TYPE_PROXY;
                             break;
                         default:
-                            typeout = loc_core::NetworkInfoDataItemBase::TYPE_UNKNOWN;
+                            typeout = loc_core::TYPE_UNKNOWN;
                     }
                 }
                 break;
         }
-        mGnss->getGnssInterface()->updateConnectionStatus(connected, false, typeout, 0);
+        mGnss->getGnssInterface()->updateConnectionStatus(connected, typeout, false, 0, apn);
     }
     return true;
 }
diff --git a/android/1.0/Android.mk b/android/1.0/Android.mk
index 797ecce..27c697b 100644
--- a/android/1.0/Android.mk
+++ b/android/1.0/Android.mk
@@ -2,7 +2,8 @@
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := android.hardware.gnss@1.0-impl-qti
-LOCAL_SANITIZE += $(GNSS_SANITIZE)
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-BSD legacy_not_a_contribution
+LOCAL_LICENSE_CONDITIONS := by_exception_only not_allowed notice
 # activate the following line for debug purposes only, comment out for production
 #LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
 LOCAL_VENDOR_MODULE := true
@@ -42,6 +43,7 @@
     android.hardware.gnss@1.0 \
     android.hardware.health@1.0 \
     android.hardware.health@2.0 \
+    android.hardware.health@2.1 \
     android.hardware.power@1.2 \
     libbase
 
@@ -58,7 +60,8 @@
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := android.hardware.gnss@1.0-service-qti
-LOCAL_SANITIZE += $(GNSS_SANITIZE)
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-BSD legacy_not_a_contribution
+LOCAL_LICENSE_CONDITIONS := by_exception_only not_allowed notice
 # activate the following line for debug purposes only, comment out for production
 #LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
 LOCAL_VINTF_FRAGMENTS := android.hardware.gnss@1.0-service-qti.xml
diff --git a/android/1.0/Gnss.cpp b/android/1.0/Gnss.cpp
index adb5232..308cc7c 100644
--- a/android/1.0/Gnss.cpp
+++ b/android/1.0/Gnss.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
  * Not a Contribution
  */
 /*
@@ -28,6 +28,7 @@
 #include "Gnss.h"
 #include <LocationUtil.h>
 #include "battery_listener.h"
+#include "loc_misc_utils.h"
 
 typedef const GnssInterface* (getLocationInterface)();
 
@@ -42,6 +43,7 @@
     LOC_LOGE("%s] service died. cookie: %llu, who: %p",
             __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
     if (mGnss != nullptr) {
+        mGnss->getGnssInterface()->resetNetworkInfo();
         mGnss->stop();
         mGnss->cleanup();
     }
@@ -69,7 +71,7 @@
 Gnss::~Gnss() {
     ENTRY_LOG_CALLFLOW();
     if (mApi != nullptr) {
-        delete mApi;
+        mApi->destroy();
         mApi = nullptr;
     }
     sGnss = nullptr;
@@ -102,22 +104,11 @@
 const GnssInterface* Gnss::getGnssInterface() {
     static bool getGnssInterfaceFailed = false;
     if (nullptr == mGnssInterface && !getGnssInterfaceFailed) {
-        LOC_LOGD("%s]: loading libgnss.so::getGnssInterface ...", __func__);
-        getLocationInterface* getter = NULL;
-        const char *error = NULL;
-        dlerror();
-        void *handle = dlopen("libgnss.so", RTLD_NOW);
-        if (NULL == handle || (error = dlerror()) != NULL)  {
-            LOC_LOGW("dlopen for libgnss.so failed, error = %s", error);
-        } else {
-            getter = (getLocationInterface*)dlsym(handle, "getGnssInterface");
-            if ((error = dlerror()) != NULL)  {
-                LOC_LOGW("dlsym for libgnss.so::getGnssInterface failed, error = %s", error);
-                getter = NULL;
-            }
-        }
+        void * libHandle = nullptr;
+        getLocationInterface* getter = (getLocationInterface*)
+                dlGetSymFromLib(libHandle, "libgnss.so", "getGnssInterface");
 
-        if (NULL == getter) {
+        if (nullptr == getter) {
             getGnssInterfaceFailed = true;
         } else {
             mGnssInterface = (const GnssInterface*)(*getter)();
@@ -185,7 +176,7 @@
         }
         if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
             mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
-            mPendingConfig.lppProfile = gnssConfig.lppProfile;
+            mPendingConfig.lppProfileMask = gnssConfig.lppProfileMask;
         }
         if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
             mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT;
diff --git a/android/1.0/GnssBatching.cpp b/android/1.0/GnssBatching.cpp
index 3e5a9f4..f92697f 100644
--- a/android/1.0/GnssBatching.cpp
+++ b/android/1.0/GnssBatching.cpp
@@ -46,7 +46,7 @@
 
 GnssBatching::~GnssBatching() {
     if (mApi != nullptr) {
-        delete mApi;
+        mApi->destroy();
         mApi = nullptr;
     }
 }
@@ -56,7 +56,7 @@
 Return<bool> GnssBatching::init(const sp<IGnssBatchingCallback>& callback) {
     if (mApi != nullptr) {
         LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__);
-        delete mApi;
+        mApi->destroy();
         mApi = nullptr;
     }
 
diff --git a/android/1.0/GnssConfiguration.cpp b/android/1.0/GnssConfiguration.cpp
index 73c9d5c..a7f64fa 100644
--- a/android/1.0/GnssConfiguration.cpp
+++ b/android/1.0/GnssConfiguration.cpp
@@ -80,7 +80,6 @@
         default:
             LOC_LOGE("%s]: invalid version: 0x%x.", __FUNCTION__, version);
             return false;
-            break;
     }
 
     return mGnss->updateConfiguration(config);
@@ -112,39 +111,33 @@
         default:
             LOC_LOGE("%s]: invalid mode: %d.", __FUNCTION__, mode);
             return false;
-            break;
     }
 
     return mGnss->updateConfiguration(config);
 }
 
-Return<bool> GnssConfiguration::setLppProfile(uint8_t lppProfile) {
+Return<bool> GnssConfiguration::setLppProfile(uint8_t lppProfileMask) {
     if (mGnss == nullptr) {
         LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
         return false;
     }
 
-    GnssConfig config;
-    memset(&config, 0, sizeof(GnssConfig));
+    GnssConfig config = {};
     config.size = sizeof(GnssConfig);
     config.flags = GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
-    switch (lppProfile) {
-        case 0:
-            config.lppProfile = GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE;
-            break;
-        case 1:
-            config.lppProfile = GNSS_CONFIG_LPP_PROFILE_USER_PLANE;
-            break;
-        case 2:
-            config.lppProfile = GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE;
-            break;
-        case 3:
-            config.lppProfile = GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE;
-            break;
-        default:
-            LOC_LOGE("%s]: invalid lppProfile: %d.", __FUNCTION__, lppProfile);
-            return false;
-            break;
+    config.lppProfileMask = GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE; //default
+
+    if (lppProfileMask & (1<<0)) {
+        config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_BIT;
+    }
+    if (lppProfileMask & (1<<1)) {
+        config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_BIT;
+    }
+    if (lppProfileMask & (1<<2)) {
+        config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_OVER_NR5G_SA_BIT;
+    }
+    if (lppProfileMask & (1<<3)) {
+        config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_OVER_NR5G_SA_BIT;
     }
 
     return mGnss->updateConfiguration(config);
@@ -203,7 +196,6 @@
         default:
             LOC_LOGE("%s]: invalid lock: %d.", __FUNCTION__, lock);
             return false;
-            break;
     }
 
     return mGnss->updateConfiguration(config);
diff --git a/android/1.0/GnssConfiguration.h b/android/1.0/GnssConfiguration.h
index 1629e06..d0e2ba8 100644
--- a/android/1.0/GnssConfiguration.h
+++ b/android/1.0/GnssConfiguration.h
@@ -53,7 +53,7 @@
     Return<bool> setSuplVersion(uint32_t version) override;
     Return<bool> setSuplMode(uint8_t mode) override;
     Return<bool> setSuplEs(bool enabled) override;
-    Return<bool> setLppProfile(uint8_t lppProfile) override;
+    Return<bool> setLppProfile(uint8_t lppProfileMask) override;
     Return<bool> setGlonassPositioningProtocol(uint8_t protocol) override;
     Return<bool> setEmergencySuplPdn(bool enable) override;
     Return<bool> setGpsLock(uint8_t lock) override;
diff --git a/android/1.0/GnssGeofencing.cpp b/android/1.0/GnssGeofencing.cpp
index 2a8ff88..4be6d8a 100644
--- a/android/1.0/GnssGeofencing.cpp
+++ b/android/1.0/GnssGeofencing.cpp
@@ -45,7 +45,7 @@
 
 GnssGeofencing::~GnssGeofencing() {
     if (mApi != nullptr) {
-        delete mApi;
+        mApi->destroy();
         mApi = nullptr;
     }
 }
diff --git a/android/1.0/GnssMeasurement.cpp b/android/1.0/GnssMeasurement.cpp
index 1c65bd6..7af9e27 100644
--- a/android/1.0/GnssMeasurement.cpp
+++ b/android/1.0/GnssMeasurement.cpp
@@ -46,7 +46,7 @@
 
 GnssMeasurement::~GnssMeasurement() {
     if (mApi) {
-        delete mApi;
+        mApi->destroy();
         mApi = nullptr;
     }
 }
diff --git a/android/1.0/location_api/BatchingAPIClient.cpp b/android/1.0/location_api/BatchingAPIClient.cpp
index 264ab83..94a234d 100644
--- a/android/1.0/location_api/BatchingAPIClient.cpp
+++ b/android/1.0/location_api/BatchingAPIClient.cpp
@@ -30,6 +30,7 @@
 #define LOG_NDEBUG 0
 #define LOG_TAG "LocSvc_BatchingAPIClient"
 
+#include <inttypes.h>
 #include <log_util.h>
 #include <loc_cfg.h>
 
@@ -153,7 +154,7 @@
 
 void BatchingAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)
 {
-    LOC_LOGD("%s]: (%02x)", __FUNCTION__, capabilitiesMask);
+    LOC_LOGD("%s]: (%" PRIu64 ")", __FUNCTION__, capabilitiesMask);
     mLocationCapabilitiesMask = capabilitiesMask;
 }
 
diff --git a/android/1.0/location_api/BatchingAPIClient.h b/android/1.0/location_api/BatchingAPIClient.h
index 5d64df3..c3b0a7b 100644
--- a/android/1.0/location_api/BatchingAPIClient.h
+++ b/android/1.0/location_api/BatchingAPIClient.h
@@ -46,7 +46,6 @@
 {
 public:
     BatchingAPIClient(const sp<V1_0::IGnssBatchingCallback>& callback);
-    ~BatchingAPIClient();
     int getBatchSize();
     int startSession(const V1_0::IGnssBatching::Options& options);
     int updateSessionOptions(const V1_0::IGnssBatching::Options& options);
@@ -61,6 +60,8 @@
     void onBatchingCb(size_t count, Location* location, BatchingOptions batchOptions) final;
 
 private:
+    ~BatchingAPIClient();
+
     sp<V1_0::IGnssBatchingCallback> mGnssBatchingCbIface;
     uint32_t mDefaultId;
     LocationCapabilitiesMask mLocationCapabilitiesMask;
diff --git a/android/1.0/location_api/GeofenceAPIClient.cpp b/android/1.0/location_api/GeofenceAPIClient.cpp
index 774a049..6feb841 100644
--- a/android/1.0/location_api/GeofenceAPIClient.cpp
+++ b/android/1.0/location_api/GeofenceAPIClient.cpp
@@ -141,7 +141,7 @@
 // callbacks
 void GeofenceAPIClient::onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification)
 {
-    LOC_LOGD("%s]: (%zu)", __FUNCTION__, geofenceBreachNotification.count);
+    LOC_LOGD("%s]: (%d)", __FUNCTION__, geofenceBreachNotification.count);
     if (mGnssGeofencingCbIface != nullptr) {
         for (size_t i = 0; i < geofenceBreachNotification.count; i++) {
             GnssLocation gnssLocation;
diff --git a/android/1.0/location_api/GeofenceAPIClient.h b/android/1.0/location_api/GeofenceAPIClient.h
index dc99ddd..b6a009b 100644
--- a/android/1.0/location_api/GeofenceAPIClient.h
+++ b/android/1.0/location_api/GeofenceAPIClient.h
@@ -46,7 +46,6 @@
 {
 public:
     GeofenceAPIClient(const sp<V1_0::IGnssGeofenceCallback>& callback);
-    virtual ~GeofenceAPIClient() = default;
 
     void geofenceAdd(uint32_t geofence_id, double latitude, double longitude,
             double radius_meters, int32_t last_transition, int32_t monitor_transitions,
@@ -65,6 +64,8 @@
     void onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final;
 
 private:
+    virtual ~GeofenceAPIClient() = default;
+
     sp<V1_0::IGnssGeofenceCallback> mGnssGeofencingCbIface;
 };
 
diff --git a/android/1.0/location_api/GnssAPIClient.cpp b/android/1.0/location_api/GnssAPIClient.cpp
index eb78591..9cef2ba 100644
--- a/android/1.0/location_api/GnssAPIClient.cpp
+++ b/android/1.0/location_api/GnssAPIClient.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -31,6 +31,7 @@
 #define LOG_TAG "LocSvc_GnssAPIClient"
 #define SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC (590 * 60 * 60 * 1000) // 590 hours
 
+#include <inttypes.h>
 #include <log_util.h>
 #include <loc_cfg.h>
 
@@ -110,9 +111,7 @@
 
     locationCallbacks.gnssNiCb = nullptr;
     loc_core::ContextBase* context =
-            loc_core::LocContext::getLocContext(
-                    NULL, NULL,
-                    loc_core::LocContext::mLocationHalName, false);
+            loc_core::LocContext::getLocContext(loc_core::LocContext::mLocationHalName);
     if (mGnssNiCbIface != nullptr && !context->hasAgpsExtendedCapabilities()) {
         LOC_LOGD("Registering NI CB");
         locationCallbacks.gnssNiCb = [this](uint32_t id, GnssNiNotification gnssNiNotification) {
@@ -301,7 +300,7 @@
 // callbacks
 void GnssAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)
 {
-    LOC_LOGD("%s]: (%02x)", __FUNCTION__, capabilitiesMask);
+    LOC_LOGD("%s]: (%" PRIu64 ")", __FUNCTION__, capabilitiesMask);
     mLocationCapabilitiesMask = capabilitiesMask;
     mLocationCapabilitiesCached = true;
 
@@ -331,16 +330,17 @@
         }
     }
     if (gnssCbIface != nullptr) {
-        IGnssCallback::GnssSystemInfo gnssInfo;
-        if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT ||
-            capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT) {
-            gnssInfo.yearOfHw = 2018;
-        } else if (capabilitiesMask & LOCATION_CAPABILITIES_DEBUG_NMEA_BIT) {
-            gnssInfo.yearOfHw = 2017;
-        } else if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) {
-            gnssInfo.yearOfHw = 2016;
-        } else {
-            gnssInfo.yearOfHw = 2015;
+        IGnssCallback::GnssSystemInfo gnssInfo = { .yearOfHw = 2015 };
+
+        if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) {
+            gnssInfo.yearOfHw++; // 2016
+            if (capabilitiesMask & LOCATION_CAPABILITIES_DEBUG_NMEA_BIT) {
+                gnssInfo.yearOfHw++; // 2017
+                if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT ||
+                    capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT) {
+                    gnssInfo.yearOfHw++; // 2018
+                }
+            }
         }
         LOC_LOGV("%s:%d] set_system_info_cb (%d)", __FUNCTION__, __LINE__, gnssInfo.yearOfHw);
         auto r = gnssCbIface->gnssSetSystemInfoCb(gnssInfo);
@@ -446,7 +446,7 @@
 
 void GnssAPIClient::onGnssSvCb(GnssSvNotification gnssSvNotification)
 {
-    LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, gnssSvNotification.count);
+    LOC_LOGD("%s]: (count: %u)", __FUNCTION__, gnssSvNotification.count);
     mMutex.lock();
     auto gnssCbIface(mGnssCbIface);
     mMutex.unlock();
@@ -479,7 +479,7 @@
             auto r = gnssCbIface->gnssNmeaCb(
                     static_cast<V1_0::GnssUtcTime>(gnssNmeaNotification.timestamp), nmeaString);
             if (!r.isOk()) {
-                LOC_LOGE("%s] Error from gnssNmeaCb nmea=%s length=%zu description=%s", __func__,
+                LOC_LOGE("%s] Error from gnssNmeaCb nmea=%s length=%u description=%s", __func__,
                             gnssNmeaNotification.nmea, gnssNmeaNotification.length,
                             r.description().c_str());
             }
@@ -540,7 +540,7 @@
     }
     for (size_t i = 0; i < out.numSvs; i++) {
         IGnssCallback::GnssSvInfo& info = out.gnssSvList[i];
-        info.svid = in.gnssSvs[i].svId;
+        convertGnssSvid(in.gnssSvs[i], info.svid);
         convertGnssConstellationType(in.gnssSvs[i].type, info.constellation);
         info.cN0Dbhz = in.gnssSvs[i].cN0Dbhz;
         info.elevationDegrees = in.gnssSvs[i].elevation;
diff --git a/android/1.0/location_api/GnssAPIClient.h b/android/1.0/location_api/GnssAPIClient.h
index 4e4b4a9..427b0db 100644
--- a/android/1.0/location_api/GnssAPIClient.h
+++ b/android/1.0/location_api/GnssAPIClient.h
@@ -50,7 +50,6 @@
 public:
     GnssAPIClient(const sp<V1_0::IGnssCallback>& gpsCb,
             const sp<V1_0::IGnssNiCallback>& niCb);
-    virtual ~GnssAPIClient();
     GnssAPIClient(const GnssAPIClient&) = delete;
     GnssAPIClient& operator=(const GnssAPIClient&) = delete;
 
@@ -92,6 +91,8 @@
     void onStopTrackingCb(LocationError error) final;
 
 private:
+    virtual ~GnssAPIClient();
+
     sp<V1_0::IGnssCallback> mGnssCbIface;
     sp<V1_0::IGnssNiCallback> mGnssNiCbIface;
     std::mutex mMutex;
diff --git a/android/1.0/location_api/LocationUtil.cpp b/android/1.0/location_api/LocationUtil.cpp
index 102593b..a37d8de 100644
--- a/android/1.0/location_api/LocationUtil.cpp
+++ b/android/1.0/location_api/LocationUtil.cpp
@@ -28,6 +28,7 @@
  */
 
 #include <LocationUtil.h>
+#include <gps_extended_c.h>
 
 namespace android {
 namespace hardware {
@@ -147,6 +148,74 @@
     }
 }
 
+void convertGnssSvid(GnssSv& in, int16_t& out)
+{
+    switch(in.type){
+        case GNSS_SV_TYPE_GPS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_SBAS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_GLONASS:
+            if (!isGloSlotUnknown(in.svId)) { // OSN is known
+                out = in.svId - GLO_SV_PRN_MIN + 1;
+            } else { // OSN is not known, report FCN
+                out = in.gloFrequency + 92;
+            }
+            break;
+        case GNSS_SV_TYPE_QZSS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_BEIDOU:
+            out = in.svId - BDS_SV_PRN_MIN + 1;
+            break;
+        case GNSS_SV_TYPE_GALILEO:
+            out = in.svId - GAL_SV_PRN_MIN + 1;
+            break;
+        case GNSS_SV_TYPE_NAVIC:
+            out = in.svId - NAVIC_SV_PRN_MIN + 1;
+            break;
+        default:
+            out = in.svId;
+            break;
+    }
+}
+
+void convertGnssSvid(GnssMeasurementsData& in, int16_t& out)
+{
+    switch (in.svType) {
+        case GNSS_SV_TYPE_GPS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_SBAS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_GLONASS:
+            if (!isGloSlotUnknown(in.svId)) { // OSN is known
+                out = in.svId - GLO_SV_PRN_MIN + 1;
+            } else { // OSN is not known, report FCN
+                out = in.gloFrequency + 92;
+            }
+            break;
+        case GNSS_SV_TYPE_QZSS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_BEIDOU:
+            out = in.svId - BDS_SV_PRN_MIN + 1;
+            break;
+        case GNSS_SV_TYPE_GALILEO:
+            out = in.svId - GAL_SV_PRN_MIN + 1;
+            break;
+        case GNSS_SV_TYPE_NAVIC:
+            out = in.svId - NAVIC_SV_PRN_MIN + 1;
+            break;
+        default:
+            out = in.svId;
+            break;
+    }
+}
+
 void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out)
 {
     switch(in) {
diff --git a/android/1.0/location_api/LocationUtil.h b/android/1.0/location_api/LocationUtil.h
index 9e0cd36..f6760e5 100644
--- a/android/1.0/location_api/LocationUtil.h
+++ b/android/1.0/location_api/LocationUtil.h
@@ -43,6 +43,8 @@
 void convertGnssLocation(Location& in, V1_0::GnssLocation& out);
 void convertGnssLocation(const V1_0::GnssLocation& in, Location& out);
 void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out);
+void convertGnssSvid(GnssSv& in, int16_t& out);
+void convertGnssSvid(GnssMeasurementsData& in, int16_t& out);
 void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out);
 void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out);
 void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out);
diff --git a/android/1.0/location_api/MeasurementAPIClient.cpp b/android/1.0/location_api/MeasurementAPIClient.cpp
index 73709e3..8dd039b 100644
--- a/android/1.0/location_api/MeasurementAPIClient.cpp
+++ b/android/1.0/location_api/MeasurementAPIClient.cpp
@@ -125,7 +125,7 @@
 void MeasurementAPIClient::onGnssMeasurementsCb(
         GnssMeasurementsNotification gnssMeasurementsNotification)
 {
-    LOC_LOGD("%s]: (count: %zu active: %d)",
+    LOC_LOGD("%s]: (count: %u active: %d)",
             __FUNCTION__, gnssMeasurementsNotification.count, mTracking);
     if (mTracking) {
         mMutex.lock();
@@ -163,7 +163,7 @@
         out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE_UNCERTAINTY;
     if (in.flags & GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT)
         out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_AUTOMATIC_GAIN_CONTROL;
-    out.svid = in.svId;
+    convertGnssSvid(in, out.svid);
     convertGnssConstellationType(in.svType, out.constellation);
     out.timeOffsetNs = in.timeOffsetNs;
     if (in.stateMask & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT)
diff --git a/android/1.0/location_api/MeasurementAPIClient.h b/android/1.0/location_api/MeasurementAPIClient.h
index c357313..225deac 100644
--- a/android/1.0/location_api/MeasurementAPIClient.h
+++ b/android/1.0/location_api/MeasurementAPIClient.h
@@ -49,7 +49,6 @@
 {
 public:
     MeasurementAPIClient();
-    virtual ~MeasurementAPIClient();
     MeasurementAPIClient(const MeasurementAPIClient&) = delete;
     MeasurementAPIClient& operator=(const MeasurementAPIClient&) = delete;
 
@@ -63,6 +62,8 @@
     void onGnssMeasurementsCb(GnssMeasurementsNotification gnssMeasurementsNotification) final;
 
 private:
+    virtual ~MeasurementAPIClient();
+
     std::mutex mMutex;
     sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface;
 
diff --git a/android/1.1/AGnssRil.cpp b/android/1.1/AGnssRil.cpp
index 1e774f1..af519a7 100644
--- a/android/1.1/AGnssRil.cpp
+++ b/android/1.1/AGnssRil.cpp
@@ -54,32 +54,33 @@
     const int NetworkType_BLUETOOTH = 7;
     const int NetworkType_ETHERNET = 9;
     const int NetworkType_PROXY = 16;
+    std::string apn("");
 
     // for XTRA
     if (nullptr != mGnss && ( nullptr != mGnss->getGnssInterface() )) {
-        int8_t typeout = loc_core::NetworkInfoDataItemBase::TYPE_UNKNOWN;
+        int8_t typeout = loc_core::TYPE_UNKNOWN;
         switch(type)
         {
             case IAGnssRil::NetworkType::MOBILE:
-                typeout = loc_core::NetworkInfoDataItemBase::TYPE_MOBILE;
+                typeout = loc_core::TYPE_MOBILE;
                 break;
             case IAGnssRil::NetworkType::WIFI:
-                typeout = loc_core::NetworkInfoDataItemBase::TYPE_WIFI;
+                typeout = loc_core::TYPE_WIFI;
                 break;
             case IAGnssRil::NetworkType::MMS:
-                typeout = loc_core::NetworkInfoDataItemBase::TYPE_MMS;
+                typeout = loc_core::TYPE_MMS;
                 break;
             case IAGnssRil::NetworkType::SUPL:
-                typeout = loc_core::NetworkInfoDataItemBase::TYPE_SUPL;
+                typeout = loc_core::TYPE_SUPL;
                 break;
             case IAGnssRil::NetworkType::DUN:
-                typeout = loc_core::NetworkInfoDataItemBase::TYPE_DUN;
+                typeout = loc_core::TYPE_DUN;
                 break;
             case IAGnssRil::NetworkType::HIPRI:
-                typeout = loc_core::NetworkInfoDataItemBase::TYPE_HIPRI;
+                typeout = loc_core::TYPE_HIPRI;
                 break;
             case IAGnssRil::NetworkType::WIMAX:
-                typeout = loc_core::NetworkInfoDataItemBase::TYPE_WIMAX;
+                typeout = loc_core::TYPE_WIMAX;
                 break;
             default:
                 {
@@ -88,21 +89,21 @@
                     switch(networkType)
                     {
                         case NetworkType_BLUETOOTH:
-                            typeout = loc_core::NetworkInfoDataItemBase::TYPE_BLUETOOTH;
+                            typeout = loc_core::TYPE_BLUETOOTH;
                             break;
                         case NetworkType_ETHERNET:
-                            typeout = loc_core::NetworkInfoDataItemBase::TYPE_ETHERNET;
+                            typeout = loc_core::TYPE_ETHERNET;
                             break;
                         case NetworkType_PROXY:
-                            typeout = loc_core::NetworkInfoDataItemBase::TYPE_PROXY;
+                            typeout = loc_core::TYPE_PROXY;
                             break;
                         default:
-                            typeout = loc_core::NetworkInfoDataItemBase::TYPE_UNKNOWN;
+                            typeout = loc_core::TYPE_UNKNOWN;
                     }
                 }
                 break;
         }
-        mGnss->getGnssInterface()->updateConnectionStatus(connected, false, typeout, 0);
+        mGnss->getGnssInterface()->updateConnectionStatus(connected, typeout, false, 0, apn);
     }
     return true;
 }
diff --git a/android/1.1/Android.mk b/android/1.1/Android.mk
index 66abd06..0a8f1d3 100644
--- a/android/1.1/Android.mk
+++ b/android/1.1/Android.mk
@@ -2,7 +2,8 @@
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := android.hardware.gnss@1.1-impl-qti
-LOCAL_SANITIZE += $(GNSS_SANITIZE)
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-BSD legacy_not_a_contribution
+LOCAL_LICENSE_CONDITIONS := by_exception_only not_allowed notice
 # activate the following line for debug purposes only, comment out for production
 #LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
 LOCAL_VENDOR_MODULE := true
@@ -43,6 +44,7 @@
     android.hardware.gnss@1.1 \
     android.hardware.health@1.0 \
     android.hardware.health@2.0 \
+    android.hardware.health@2.1 \
     android.hardware.power@1.2 \
     libbase
 
@@ -59,7 +61,8 @@
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := android.hardware.gnss@1.1-service-qti
-LOCAL_SANITIZE += $(GNSS_SANITIZE)
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-BSD legacy_not_a_contribution
+LOCAL_LICENSE_CONDITIONS := by_exception_only not_allowed notice
 # activate the following line for debug purposes only, comment out for production
 #LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
 LOCAL_VINTF_FRAGMENTS := android.hardware.gnss@1.1-service-qti.xml
diff --git a/android/1.1/Gnss.cpp b/android/1.1/Gnss.cpp
index 260f999..537f6a6 100644
--- a/android/1.1/Gnss.cpp
+++ b/android/1.1/Gnss.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
  * Not a Contribution
  */
 /*
@@ -29,6 +29,7 @@
 #include <LocationUtil.h>
 
 #include "battery_listener.h"
+#include "loc_misc_utils.h"
 
 typedef const GnssInterface* (getLocationInterface)();
 
@@ -83,6 +84,7 @@
     LOC_LOGE("%s] service died. cookie: %llu, who: %p",
             __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
     if (mGnss != nullptr) {
+        mGnss->getGnssInterface()->resetNetworkInfo();
         mGnss->stop();
         mGnss->cleanup();
     }
@@ -110,7 +112,7 @@
 Gnss::~Gnss() {
     ENTRY_LOG_CALLFLOW();
     if (mApi != nullptr) {
-        delete mApi;
+        mApi->destroy();
         mApi = nullptr;
     }
     sGnss = nullptr;
@@ -143,22 +145,11 @@
 const GnssInterface* Gnss::getGnssInterface() {
     static bool getGnssInterfaceFailed = false;
     if (nullptr == mGnssInterface && !getGnssInterfaceFailed) {
-        LOC_LOGD("%s]: loading libgnss.so::getGnssInterface ...", __func__);
-        getLocationInterface* getter = NULL;
-        const char *error = NULL;
-        dlerror();
-        void *handle = dlopen("libgnss.so", RTLD_NOW);
-        if (NULL == handle || (error = dlerror()) != NULL)  {
-            LOC_LOGW("dlopen for libgnss.so failed, error = %s", error);
-        } else {
-            getter = (getLocationInterface*)dlsym(handle, "getGnssInterface");
-            if ((error = dlerror()) != NULL)  {
-                LOC_LOGW("dlsym for libgnss.so::getGnssInterface failed, error = %s", error);
-                getter = NULL;
-            }
-        }
+        void * libHandle = nullptr;
+        getLocationInterface* getter = (getLocationInterface*)
+                dlGetSymFromLib(libHandle, "libgnss.so", "getGnssInterface");
 
-        if (NULL == getter) {
+        if (nullptr == getter) {
             getGnssInterfaceFailed = true;
         } else {
             mGnssInterface = (const GnssInterface*)(*getter)();
@@ -226,7 +217,7 @@
         }
         if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
             mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
-            mPendingConfig.lppProfile = gnssConfig.lppProfile;
+            mPendingConfig.lppProfileMask = gnssConfig.lppProfileMask;
         }
         if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
             mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT;
@@ -389,7 +380,7 @@
         OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) {
             odcpiRequestCb(odcpiRequest);
         };
-        gnssInterface->odcpiInit(cb);
+        gnssInterface->odcpiInit(cb, OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW);
     }
     return setCallback(callback);
 }
@@ -439,6 +430,9 @@
 
 void Gnss::odcpiRequestCb(const OdcpiRequestInfo& request) {
     ENTRY_LOG_CALLFLOW();
+    if (ODCPI_REQUEST_TYPE_STOP == request.type) {
+        return;
+    }
     if (mGnssCbIface_1_1 != nullptr) {
         // For emergency mode, request DBH (Device based hybrid) location
         // Mark Independent from GNSS flag to false.
diff --git a/android/1.1/GnssBatching.cpp b/android/1.1/GnssBatching.cpp
index 9701aff..8ab264d 100644
--- a/android/1.1/GnssBatching.cpp
+++ b/android/1.1/GnssBatching.cpp
@@ -46,7 +46,7 @@
 
 GnssBatching::~GnssBatching() {
     if (mApi != nullptr) {
-        delete mApi;
+        mApi->destroy();
         mApi = nullptr;
     }
 }
@@ -56,7 +56,7 @@
 Return<bool> GnssBatching::init(const sp<IGnssBatchingCallback>& callback) {
     if (mApi != nullptr) {
         LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__);
-        delete mApi;
+        mApi->destroy();
         mApi = nullptr;
     }
 
diff --git a/android/1.1/GnssConfiguration.cpp b/android/1.1/GnssConfiguration.cpp
index 708e2c1..c50ed9b 100644
--- a/android/1.1/GnssConfiguration.cpp
+++ b/android/1.1/GnssConfiguration.cpp
@@ -80,7 +80,6 @@
         default:
             LOC_LOGE("%s]: invalid version: 0x%x.", __FUNCTION__, version);
             return false;
-            break;
     }
 
     return mGnss->updateConfiguration(config);
@@ -112,39 +111,33 @@
         default:
             LOC_LOGE("%s]: invalid mode: %d.", __FUNCTION__, mode);
             return false;
-            break;
     }
 
     return mGnss->updateConfiguration(config);
 }
 
-Return<bool> GnssConfiguration::setLppProfile(uint8_t lppProfile) {
+Return<bool> GnssConfiguration::setLppProfile(uint8_t lppProfileMask) {
     if (mGnss == nullptr) {
         LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
         return false;
     }
 
-    GnssConfig config;
-    memset(&config, 0, sizeof(GnssConfig));
+    GnssConfig config = {};
     config.size = sizeof(GnssConfig);
     config.flags = GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
-    switch (lppProfile) {
-        case 0:
-            config.lppProfile = GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE;
-            break;
-        case 1:
-            config.lppProfile = GNSS_CONFIG_LPP_PROFILE_USER_PLANE;
-            break;
-        case 2:
-            config.lppProfile = GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE;
-            break;
-        case 3:
-            config.lppProfile = GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE;
-            break;
-        default:
-            LOC_LOGE("%s]: invalid lppProfile: %d.", __FUNCTION__, lppProfile);
-            return false;
-            break;
+    config.lppProfileMask = GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE; //default
+
+    if (lppProfileMask & (1<<0)) {
+        config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_BIT;
+    }
+    if (lppProfileMask & (1<<1)) {
+        config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_BIT;
+    }
+    if (lppProfileMask & (1<<2)) {
+        config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_OVER_NR5G_SA_BIT;
+    }
+    if (lppProfileMask & (1<<3)) {
+        config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_OVER_NR5G_SA_BIT;
     }
 
     return mGnss->updateConfiguration(config);
@@ -203,7 +196,6 @@
         default:
             LOC_LOGE("%s]: invalid lock: %d.", __FUNCTION__, lock);
             return false;
-            break;
     }
 
     return mGnss->updateConfiguration(config);
@@ -297,7 +289,7 @@
         break;
     default:
         copyToSource.constellation = GNSS_SV_TYPE_UNKNOWN;
-        LOC_LOGe("Invalid constellation %d", copyFromSource.constellation);
+        LOC_LOGe("Invalid constellation %hhu", copyFromSource.constellation);
         retVal = false;
         break;
     }
diff --git a/android/1.1/GnssConfiguration.h b/android/1.1/GnssConfiguration.h
index 96681b6..daea159 100644
--- a/android/1.1/GnssConfiguration.h
+++ b/android/1.1/GnssConfiguration.h
@@ -53,7 +53,7 @@
     Return<bool> setSuplVersion(uint32_t version) override;
     Return<bool> setSuplMode(uint8_t mode) override;
     Return<bool> setSuplEs(bool enabled) override;
-    Return<bool> setLppProfile(uint8_t lppProfile) override;
+    Return<bool> setLppProfile(uint8_t lppProfileMask) override;
     Return<bool> setGlonassPositioningProtocol(uint8_t protocol) override;
     Return<bool> setEmergencySuplPdn(bool enable) override;
     Return<bool> setGpsLock(uint8_t lock) override;
diff --git a/android/1.1/GnssGeofencing.cpp b/android/1.1/GnssGeofencing.cpp
index d57a666..a4aaf88 100644
--- a/android/1.1/GnssGeofencing.cpp
+++ b/android/1.1/GnssGeofencing.cpp
@@ -45,7 +45,7 @@
 
 GnssGeofencing::~GnssGeofencing() {
     if (mApi != nullptr) {
-        delete mApi;
+        mApi->destroy();
         mApi = nullptr;
     }
 }
diff --git a/android/1.1/GnssMeasurement.cpp b/android/1.1/GnssMeasurement.cpp
index ffe5c52..6f8c14d 100644
--- a/android/1.1/GnssMeasurement.cpp
+++ b/android/1.1/GnssMeasurement.cpp
@@ -46,7 +46,7 @@
 
 GnssMeasurement::~GnssMeasurement() {
     if (mApi) {
-        delete mApi;
+        mApi->destroy();
         mApi = nullptr;
     }
 }
diff --git a/android/1.1/location_api/BatchingAPIClient.cpp b/android/1.1/location_api/BatchingAPIClient.cpp
index 82a803f..6ec27a9 100644
--- a/android/1.1/location_api/BatchingAPIClient.cpp
+++ b/android/1.1/location_api/BatchingAPIClient.cpp
@@ -30,6 +30,7 @@
 #define LOG_NDEBUG 0
 #define LOG_TAG "LocSvc_BatchingAPIClient"
 
+#include <inttypes.h>
 #include <log_util.h>
 #include <loc_cfg.h>
 
@@ -153,7 +154,7 @@
 
 void BatchingAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)
 {
-    LOC_LOGD("%s]: (%02x)", __FUNCTION__, capabilitiesMask);
+    LOC_LOGD("%s]: (%" PRIu64 ")", __FUNCTION__, capabilitiesMask);
     mLocationCapabilitiesMask = capabilitiesMask;
 }
 
diff --git a/android/1.1/location_api/BatchingAPIClient.h b/android/1.1/location_api/BatchingAPIClient.h
index 64d47a0..4c90626 100644
--- a/android/1.1/location_api/BatchingAPIClient.h
+++ b/android/1.1/location_api/BatchingAPIClient.h
@@ -46,7 +46,6 @@
 {
 public:
     BatchingAPIClient(const sp<V1_0::IGnssBatchingCallback>& callback);
-    ~BatchingAPIClient();
     int getBatchSize();
     int startSession(const V1_0::IGnssBatching::Options& options);
     int updateSessionOptions(const V1_0::IGnssBatching::Options& options);
@@ -61,6 +60,8 @@
     void onBatchingCb(size_t count, Location* location, BatchingOptions batchOptions) final;
 
 private:
+    ~BatchingAPIClient();
+
     sp<V1_0::IGnssBatchingCallback> mGnssBatchingCbIface;
     uint32_t mDefaultId;
     LocationCapabilitiesMask mLocationCapabilitiesMask;
diff --git a/android/1.1/location_api/GeofenceAPIClient.cpp b/android/1.1/location_api/GeofenceAPIClient.cpp
index 93d175e..f6d1dc3 100644
--- a/android/1.1/location_api/GeofenceAPIClient.cpp
+++ b/android/1.1/location_api/GeofenceAPIClient.cpp
@@ -141,7 +141,7 @@
 // callbacks
 void GeofenceAPIClient::onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification)
 {
-    LOC_LOGD("%s]: (%zu)", __FUNCTION__, geofenceBreachNotification.count);
+    LOC_LOGD("%s]: (%d)", __FUNCTION__, geofenceBreachNotification.count);
     if (mGnssGeofencingCbIface != nullptr) {
         for (size_t i = 0; i < geofenceBreachNotification.count; i++) {
             GnssLocation gnssLocation;
diff --git a/android/1.1/location_api/GeofenceAPIClient.h b/android/1.1/location_api/GeofenceAPIClient.h
index c74a59a..0ffff91 100644
--- a/android/1.1/location_api/GeofenceAPIClient.h
+++ b/android/1.1/location_api/GeofenceAPIClient.h
@@ -46,7 +46,6 @@
 {
 public:
     GeofenceAPIClient(const sp<V1_0::IGnssGeofenceCallback>& callback);
-    virtual ~GeofenceAPIClient() = default;
 
     void geofenceAdd(uint32_t geofence_id, double latitude, double longitude,
             double radius_meters, int32_t last_transition, int32_t monitor_transitions,
@@ -65,6 +64,8 @@
     void onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final;
 
 private:
+    virtual ~GeofenceAPIClient() = default;
+
     sp<V1_0::IGnssGeofenceCallback> mGnssGeofencingCbIface;
 };
 
diff --git a/android/1.1/location_api/GnssAPIClient.cpp b/android/1.1/location_api/GnssAPIClient.cpp
index be4d659..dbb5fe4 100644
--- a/android/1.1/location_api/GnssAPIClient.cpp
+++ b/android/1.1/location_api/GnssAPIClient.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -31,6 +31,7 @@
 #define LOG_TAG "LocSvc_GnssAPIClient"
 #define SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC (590 * 60 * 60 * 1000) // 590 hours
 
+#include <inttypes.h>
 #include <log_util.h>
 #include <loc_cfg.h>
 
@@ -110,9 +111,7 @@
 
     locationCallbacks.gnssNiCb = nullptr;
     loc_core::ContextBase* context =
-            loc_core::LocContext::getLocContext(
-                    NULL, NULL,
-                    loc_core::LocContext::mLocationHalName, false);
+            loc_core::LocContext::getLocContext(loc_core::LocContext::mLocationHalName);
     if (mGnssNiCbIface != nullptr && !context->hasAgpsExtendedCapabilities()) {
         LOC_LOGD("Registering NI CB");
         locationCallbacks.gnssNiCb = [this](uint32_t id, GnssNiNotification gnssNiNotification) {
@@ -301,7 +300,7 @@
 // callbacks
 void GnssAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)
 {
-    LOC_LOGD("%s]: (%02x)", __FUNCTION__, capabilitiesMask);
+    LOC_LOGD("%s]: (%" PRIu64 ")", __FUNCTION__, capabilitiesMask);
     mLocationCapabilitiesMask = capabilitiesMask;
     mLocationCapabilitiesCached = true;
 
@@ -331,16 +330,17 @@
         }
     }
     if (gnssCbIface != nullptr) {
-        IGnssCallback::GnssSystemInfo gnssInfo;
-        if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT ||
-            capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT) {
-            gnssInfo.yearOfHw = 2018;
-        } else if (capabilitiesMask & LOCATION_CAPABILITIES_DEBUG_NMEA_BIT) {
-            gnssInfo.yearOfHw = 2017;
-        } else if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) {
-            gnssInfo.yearOfHw = 2016;
-        } else {
-            gnssInfo.yearOfHw = 2015;
+        IGnssCallback::GnssSystemInfo gnssInfo = { .yearOfHw = 2015 };
+
+        if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) {
+            gnssInfo.yearOfHw++; // 2016
+            if (capabilitiesMask & LOCATION_CAPABILITIES_DEBUG_NMEA_BIT) {
+                gnssInfo.yearOfHw++; // 2017
+                if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT ||
+                    capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT) {
+                    gnssInfo.yearOfHw++; // 2018
+                }
+            }
         }
         LOC_LOGV("%s:%d] set_system_info_cb (%d)", __FUNCTION__, __LINE__, gnssInfo.yearOfHw);
         auto r = gnssCbIface->gnssSetSystemInfoCb(gnssInfo);
@@ -446,7 +446,7 @@
 
 void GnssAPIClient::onGnssSvCb(GnssSvNotification gnssSvNotification)
 {
-    LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, gnssSvNotification.count);
+    LOC_LOGD("%s]: (count: %u)", __FUNCTION__, gnssSvNotification.count);
     mMutex.lock();
     auto gnssCbIface(mGnssCbIface);
     mMutex.unlock();
@@ -479,7 +479,7 @@
             auto r = gnssCbIface->gnssNmeaCb(
                     static_cast<V1_0::GnssUtcTime>(gnssNmeaNotification.timestamp), nmeaString);
             if (!r.isOk()) {
-                LOC_LOGE("%s] Error from gnssNmeaCb nmea=%s length=%zu description=%s", __func__,
+                LOC_LOGE("%s] Error from gnssNmeaCb nmea=%s length=%u description=%s", __func__,
                             gnssNmeaNotification.nmea, gnssNmeaNotification.length,
                             r.description().c_str());
             }
@@ -540,7 +540,7 @@
     }
     for (size_t i = 0; i < out.numSvs; i++) {
         IGnssCallback::GnssSvInfo& info = out.gnssSvList[i];
-        info.svid = in.gnssSvs[i].svId;
+        convertGnssSvid(in.gnssSvs[i], info.svid);
         convertGnssConstellationType(in.gnssSvs[i].type, info.constellation);
         info.cN0Dbhz = in.gnssSvs[i].cN0Dbhz;
         info.elevationDegrees = in.gnssSvs[i].elevation;
diff --git a/android/1.1/location_api/GnssAPIClient.h b/android/1.1/location_api/GnssAPIClient.h
index 82f8fbf..3829265 100644
--- a/android/1.1/location_api/GnssAPIClient.h
+++ b/android/1.1/location_api/GnssAPIClient.h
@@ -50,7 +50,6 @@
 public:
     GnssAPIClient(const sp<V1_0::IGnssCallback>& gpsCb,
             const sp<V1_0::IGnssNiCallback>& niCb);
-    virtual ~GnssAPIClient();
     GnssAPIClient(const GnssAPIClient&) = delete;
     GnssAPIClient& operator=(const GnssAPIClient&) = delete;
 
@@ -92,6 +91,8 @@
     void onStopTrackingCb(LocationError error) final;
 
 private:
+    virtual ~GnssAPIClient();
+
     sp<V1_0::IGnssCallback> mGnssCbIface;
     sp<V1_0::IGnssNiCallback> mGnssNiCbIface;
     std::mutex mMutex;
diff --git a/android/1.1/location_api/LocationUtil.cpp b/android/1.1/location_api/LocationUtil.cpp
index f1d051c..aacec07 100644
--- a/android/1.1/location_api/LocationUtil.cpp
+++ b/android/1.1/location_api/LocationUtil.cpp
@@ -28,6 +28,7 @@
  */
 
 #include <LocationUtil.h>
+#include <gps_extended_c.h>
 
 namespace android {
 namespace hardware {
@@ -147,6 +148,74 @@
     }
 }
 
+void convertGnssSvid(GnssSv& in, int16_t& out)
+{
+    switch(in.type){
+        case GNSS_SV_TYPE_GPS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_SBAS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_GLONASS:
+            if (!isGloSlotUnknown(in.svId)) { // OSN is known
+                out = in.svId - GLO_SV_PRN_MIN + 1;
+            } else { //OSN is not known, report FCN
+                out = in.gloFrequency + 92;
+            }
+            break;
+        case GNSS_SV_TYPE_QZSS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_BEIDOU:
+            out = in.svId - BDS_SV_PRN_MIN + 1;
+            break;
+        case GNSS_SV_TYPE_GALILEO:
+            out = in.svId - GAL_SV_PRN_MIN + 1;
+            break;
+        case GNSS_SV_TYPE_NAVIC:
+            out = in.svId - NAVIC_SV_PRN_MIN + 1;
+            break;
+        default:
+            out = in.svId;
+            break;
+    }
+}
+
+void convertGnssSvid(GnssMeasurementsData& in, int16_t& out)
+{
+    switch (in.svType) {
+        case GNSS_SV_TYPE_GPS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_SBAS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_GLONASS:
+            if (!isGloSlotUnknown(in.svId)) { // OSN is known
+                out = in.svId - GLO_SV_PRN_MIN + 1;
+            } else { // OSN is not known, report FCN
+                out = in.gloFrequency + 92;
+            }
+            break;
+        case GNSS_SV_TYPE_QZSS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_BEIDOU:
+            out = in.svId - BDS_SV_PRN_MIN + 1;
+            break;
+        case GNSS_SV_TYPE_GALILEO:
+            out = in.svId - GAL_SV_PRN_MIN + 1;
+            break;
+        case GNSS_SV_TYPE_NAVIC:
+            out = in.svId - NAVIC_SV_PRN_MIN + 1;
+            break;
+        default:
+            out = in.svId;
+            break;
+    }
+}
+
 void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out)
 {
     switch(in) {
diff --git a/android/1.1/location_api/LocationUtil.h b/android/1.1/location_api/LocationUtil.h
index 63f4f6f..af3c93f 100644
--- a/android/1.1/location_api/LocationUtil.h
+++ b/android/1.1/location_api/LocationUtil.h
@@ -43,6 +43,8 @@
 void convertGnssLocation(Location& in, V1_0::GnssLocation& out);
 void convertGnssLocation(const V1_0::GnssLocation& in, Location& out);
 void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out);
+void convertGnssSvid(GnssSv& in, int16_t& out);
+void convertGnssSvid(GnssMeasurementsData& in, int16_t& out);
 void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out);
 void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out);
 void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out);
diff --git a/android/1.1/location_api/MeasurementAPIClient.cpp b/android/1.1/location_api/MeasurementAPIClient.cpp
index 6f25067..af8095c 100644
--- a/android/1.1/location_api/MeasurementAPIClient.cpp
+++ b/android/1.1/location_api/MeasurementAPIClient.cpp
@@ -148,7 +148,7 @@
 void MeasurementAPIClient::onGnssMeasurementsCb(
         GnssMeasurementsNotification gnssMeasurementsNotification)
 {
-    LOC_LOGD("%s]: (count: %zu active: %d)",
+    LOC_LOGD("%s]: (count: %u active: %d)",
             __FUNCTION__, gnssMeasurementsNotification.count, mTracking);
     if (mTracking) {
         mMutex.lock();
@@ -197,7 +197,7 @@
         out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE_UNCERTAINTY;
     if (in.flags & GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT)
         out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_AUTOMATIC_GAIN_CONTROL;
-    out.svid = in.svId;
+    convertGnssSvid(in, out.svid);
     convertGnssConstellationType(in.svType, out.constellation);
     out.timeOffsetNs = in.timeOffsetNs;
     if (in.stateMask & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT)
diff --git a/android/1.1/location_api/MeasurementAPIClient.h b/android/1.1/location_api/MeasurementAPIClient.h
index 38811c5..5fb307c 100644
--- a/android/1.1/location_api/MeasurementAPIClient.h
+++ b/android/1.1/location_api/MeasurementAPIClient.h
@@ -49,7 +49,6 @@
 {
 public:
     MeasurementAPIClient();
-    virtual ~MeasurementAPIClient();
     MeasurementAPIClient(const MeasurementAPIClient&) = delete;
     MeasurementAPIClient& operator=(const MeasurementAPIClient&) = delete;
 
@@ -69,6 +68,8 @@
     void onGnssMeasurementsCb(GnssMeasurementsNotification gnssMeasurementsNotification) final;
 
 private:
+    virtual ~MeasurementAPIClient();
+
     std::mutex mMutex;
     sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface;
     sp<IGnssMeasurementCallback> mGnssMeasurementCbIface_1_1;
diff --git a/android/2.0/AGnssRil.cpp b/android/2.0/AGnssRil.cpp
index a477fc2..d8005e4 100644
--- a/android/2.0/AGnssRil.cpp
+++ b/android/2.0/AGnssRil.cpp
@@ -54,6 +54,7 @@
     const int NetworkType_BLUETOOTH = 7;
     const int NetworkType_ETHERNET = 9;
     const int NetworkType_PROXY = 16;
+    std::string apn("");
 
     // for XTRA
     if (nullptr != mGnss && ( nullptr != mGnss->getGnssInterface() )) {
@@ -102,13 +103,13 @@
                 }
                 break;
         }
-        mGnss->getGnssInterface()->updateConnectionStatus(connected, false, typeout, 0);
+        mGnss->getGnssInterface()->updateConnectionStatus(connected, typeout, false, 0, apn);
     }
     return true;
 }
 Return<bool> AGnssRil::updateNetworkState_2_0(const V2_0::IAGnssRil::NetworkAttributes& attributes) {
     ENTRY_LOG_CALLFLOW();
-
+    std::string apn = attributes.apn;
     if (nullptr != mGnss && (nullptr != mGnss->getGnssInterface())) {
         int8_t typeout = loc_core::TYPE_UNKNOWN;
         bool roaming = false;
@@ -120,8 +121,9 @@
         if (attributes.capabilities & IAGnssRil::NetworkCapability::NOT_ROAMING) {
             roaming = false;
         }
+        LOC_LOGd("apn string received is: %s", apn.c_str());
         mGnss->getGnssInterface()->updateConnectionStatus(attributes.isConnected,
-                typeout, roaming, (NetworkHandle) attributes.networkHandle);
+                typeout, roaming, (NetworkHandle) attributes.networkHandle, apn);
     }
     return true;
 }
diff --git a/android/2.0/Android.mk b/android/2.0/Android.mk
index b6790c5..a0af746 100644
--- a/android/2.0/Android.mk
+++ b/android/2.0/Android.mk
@@ -2,7 +2,8 @@
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := android.hardware.gnss@2.0-impl-qti
-LOCAL_SANITIZE += $(GNSS_SANITIZE)
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-BSD legacy_not_a_contribution
+LOCAL_LICENSE_CONDITIONS := by_exception_only not_allowed notice
 # activate the following line for debug purposes only, comment out for production
 #LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
 LOCAL_VENDOR_MODULE := true
@@ -17,8 +18,8 @@
     GnssGeofencing.cpp \
     GnssNi.cpp \
     GnssDebug.cpp \
-    ../measurement_corrections/1.0/MeasurementCorrections.cpp \
-    ../visibility_control/1.0/GnssVisibilityControl.cpp
+    MeasurementCorrections.cpp \
+    GnssVisibilityControl.cpp
 
 LOCAL_SRC_FILES += \
     location_api/GnssAPIClient.cpp \
@@ -33,9 +34,8 @@
 endif
 
 LOCAL_C_INCLUDES:= \
-    $(LOCAL_PATH)/location_api \
-    $(LOCAL_PATH)/../measurement_corrections/1.0 \
-    $(LOCAL_PATH)/../visibility_control/1.0
+    $(LOCAL_PATH)/location_api
+
 LOCAL_HEADER_LIBRARIES := \
     libgps.utils_headers \
     libloc_core_headers \
@@ -55,6 +55,7 @@
     android.hardware.gnss.visibility_control@1.0 \
     android.hardware.health@1.0 \
     android.hardware.health@2.0 \
+    android.hardware.health@2.1 \
     android.hardware.power@1.2 \
     libbase
 
@@ -71,7 +72,8 @@
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := android.hardware.gnss@2.0-service-qti
-LOCAL_SANITIZE += $(GNSS_SANITIZE)
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-BSD legacy_not_a_contribution
+LOCAL_LICENSE_CONDITIONS := by_exception_only not_allowed notice
 # activate the following line for debug purposes only, comment out for production
 #LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
 LOCAL_VINTF_FRAGMENTS := android.hardware.gnss@2.0-service-qti.xml
diff --git a/android/2.0/Gnss.cpp b/android/2.0/Gnss.cpp
index 1b3ea1d..823ef6e 100644
--- a/android/2.0/Gnss.cpp
+++ b/android/2.0/Gnss.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
  * Not a Contribution
  */
 /*
@@ -28,6 +28,7 @@
 #include "Gnss.h"
 #include "LocationUtil.h"
 #include "battery_listener.h"
+#include "loc_misc_utils.h"
 
 typedef const GnssInterface* (getLocationInterface)();
 
@@ -83,6 +84,7 @@
     LOC_LOGE("%s] service died. cookie: %llu, who: %p",
             __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
     if (mGnss != nullptr) {
+        mGnss->getGnssInterface()->resetNetworkInfo();
         mGnss->cleanup();
     }
 }
@@ -108,7 +110,7 @@
 Gnss::~Gnss() {
     ENTRY_LOG_CALLFLOW();
     if (mApi != nullptr) {
-        delete mApi;
+        mApi->destroy();
         mApi = nullptr;
     }
     sGnss = nullptr;
@@ -145,26 +147,16 @@
 
 const GnssInterface* Gnss::getGnssInterface() {
     static bool getGnssInterfaceFailed = false;
-    if (nullptr == mGnssInterface && !getGnssInterfaceFailed) {
-        LOC_LOGD("%s]: loading libgnss.so::getGnssInterface ...", __func__);
-        getLocationInterface* getter = NULL;
-        const char *error = NULL;
-        dlerror();
-        void *handle = dlopen("libgnss.so", RTLD_NOW);
-        if (NULL == handle || (error = dlerror()) != NULL)  {
-            LOC_LOGW("dlopen for libgnss.so failed, error = %s", error);
-        } else {
-            getter = (getLocationInterface*)dlsym(handle, "getGnssInterface");
-            if ((error = dlerror()) != NULL)  {
-                LOC_LOGW("dlsym for libgnss.so::getGnssInterface failed, error = %s", error);
-                getter = NULL;
-            }
-        }
 
-        if (NULL == getter) {
+    if (nullptr == mGnssInterface && !getGnssInterfaceFailed) {
+        void * libHandle = nullptr;
+        getLocationInterface* getter = (getLocationInterface*)
+                dlGetSymFromLib(libHandle, "libgnss.so", "getGnssInterface");
+
+        if (nullptr == getter) {
             getGnssInterfaceFailed = true;
         } else {
-            mGnssInterface = (const GnssInterface*)(*getter)();
+            mGnssInterface = (GnssInterface*)(*getter)();
         }
     }
     return mGnssInterface;
@@ -246,7 +238,7 @@
         }
         if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
             mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
-            mPendingConfig.lppProfile = gnssConfig.lppProfile;
+            mPendingConfig.lppProfileMask = gnssConfig.lppProfileMask;
         }
         if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
             mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT;
@@ -454,7 +446,7 @@
         OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) {
             odcpiRequestCb(odcpiRequest);
         };
-        gnssInterface->odcpiInit(cb);
+        gnssInterface->odcpiInit(cb, OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW);
     }
 
     GnssAPIClient* api = getApi();
@@ -517,6 +509,9 @@
 void Gnss::odcpiRequestCb(const OdcpiRequestInfo& request) {
     ENTRY_LOG_CALLFLOW();
 
+    if (ODCPI_REQUEST_TYPE_STOP == request.type) {
+        return;
+    }
     if (mGnssCbIface_2_0 != nullptr) {
         // For emergency mode, request DBH (Device based hybrid) location
         // Mark Independent from GNSS flag to false.
@@ -584,7 +579,7 @@
         OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) {
             odcpiRequestCb(odcpiRequest);
         };
-        gnssInterface->odcpiInit(cb);
+        gnssInterface->odcpiInit(cb, OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW);
     }
 
     GnssAPIClient* api = getApi();
@@ -662,11 +657,7 @@
 }
 
 Return<sp<V2_0::IGnssBatching>> Gnss::getExtensionGnssBatching_2_0() {
-    ENTRY_LOG_CALLFLOW();
-    if (mGnssBatching == nullptr) {
-        mGnssBatching = new GnssBatching();
-    }
-    return mGnssBatching;
+    return nullptr;
 }
 
 V1_0::IGnss* HIDL_FETCH_IGnss(const char* hal) {
diff --git a/android/2.0/GnssBatching.cpp b/android/2.0/GnssBatching.cpp
index 7a937fc..6a2a09e 100644
--- a/android/2.0/GnssBatching.cpp
+++ b/android/2.0/GnssBatching.cpp
@@ -46,7 +46,7 @@
 
 GnssBatching::~GnssBatching() {
     if (mApi != nullptr) {
-        delete mApi;
+        mApi->destroy();
         mApi = nullptr;
     }
 }
@@ -56,7 +56,7 @@
 Return<bool> GnssBatching::init(const sp<V1_0::IGnssBatchingCallback>& callback) {
     if (mApi != nullptr) {
         LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__);
-        delete mApi;
+        mApi->destroy();
         mApi = nullptr;
     }
 
@@ -135,7 +135,7 @@
 Return<bool> GnssBatching::init_2_0(const sp<V2_0::IGnssBatchingCallback>& callback) {
     if (mApi != nullptr) {
         LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__);
-        delete mApi;
+        mApi->destroy();
         mApi = nullptr;
     }
 
diff --git a/android/2.0/GnssConfiguration.cpp b/android/2.0/GnssConfiguration.cpp
index 069c036..55a70dc 100644
--- a/android/2.0/GnssConfiguration.cpp
+++ b/android/2.0/GnssConfiguration.cpp
@@ -70,7 +70,6 @@
         default:
             LOC_LOGE("%s]: invalid version: 0x%x.", __FUNCTION__, version);
             return false;
-            break;
     }
 
     return mGnss->updateConfiguration(config);
@@ -102,13 +101,12 @@
         default:
             LOC_LOGE("%s]: invalid mode: %d.", __FUNCTION__, mode);
             return false;
-            break;
     }
 
     return mGnss->updateConfiguration(config);
 }
 
-Return<bool> GnssConfiguration::setLppProfile(uint8_t lppProfile) {
+Return<bool> GnssConfiguration::setLppProfile(uint8_t lppProfileMask) {
     if (mGnss == nullptr) {
         LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
         return false;
@@ -117,23 +115,19 @@
     GnssConfig config = {};
     config.size = sizeof(GnssConfig);
     config.flags = GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
-    switch (lppProfile) {
-        case 0:
-            config.lppProfile = GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE;
-            break;
-        case 1:
-            config.lppProfile = GNSS_CONFIG_LPP_PROFILE_USER_PLANE;
-            break;
-        case 2:
-            config.lppProfile = GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE;
-            break;
-        case 3:
-            config.lppProfile = GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE;
-            break;
-        default:
-            LOC_LOGE("%s]: invalid lppProfile: %d.", __FUNCTION__, lppProfile);
-            return false;
-            break;
+    config.lppProfileMask = GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE; //default
+
+    if (lppProfileMask & (1<<0)) {
+        config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_BIT;
+    }
+    if (lppProfileMask & (1<<1)) {
+        config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_BIT;
+    }
+    if (lppProfileMask & (1<<2)) {
+        config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_OVER_NR5G_SA_BIT;
+    }
+    if (lppProfileMask & (1<<3)) {
+        config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_OVER_NR5G_SA_BIT;
     }
 
     return mGnss->updateConfiguration(config);
@@ -192,7 +186,6 @@
     default:
         LOC_LOGE("%s]: invalid lock: %d.", __FUNCTION__, lock);
         return false;
-        break;
     }
 
     mGnss->updateConfiguration(config);
diff --git a/android/2.0/GnssConfiguration.h b/android/2.0/GnssConfiguration.h
index 202a9fd..c3de2c9 100644
--- a/android/2.0/GnssConfiguration.h
+++ b/android/2.0/GnssConfiguration.h
@@ -52,7 +52,7 @@
     Return<bool> setSuplVersion(uint32_t version) override;
     Return<bool> setSuplMode(uint8_t mode) override;
     Return<bool> setSuplEs(bool enabled) override;
-    Return<bool> setLppProfile(uint8_t lppProfile) override;
+    Return<bool> setLppProfile(uint8_t lppProfileMask) override;
     Return<bool> setGlonassPositioningProtocol(uint8_t protocol) override;
     Return<bool> setEmergencySuplPdn(bool enable) override;
     Return<bool> setGpsLock(uint8_t lock) override;
diff --git a/android/2.0/GnssGeofencing.cpp b/android/2.0/GnssGeofencing.cpp
index b72d835..b6fc94b 100644
--- a/android/2.0/GnssGeofencing.cpp
+++ b/android/2.0/GnssGeofencing.cpp
@@ -45,7 +45,7 @@
 
 GnssGeofencing::~GnssGeofencing() {
     if (mApi != nullptr) {
-        delete mApi;
+        mApi->destroy();
         mApi = nullptr;
     }
 }
diff --git a/android/2.0/GnssMeasurement.cpp b/android/2.0/GnssMeasurement.cpp
index 721a48c..6cb55ca 100644
--- a/android/2.0/GnssMeasurement.cpp
+++ b/android/2.0/GnssMeasurement.cpp
@@ -46,7 +46,7 @@
 
 GnssMeasurement::~GnssMeasurement() {
     if (mApi) {
-        delete mApi;
+        mApi->destroy();
         mApi = nullptr;
     }
 }
@@ -71,18 +71,15 @@
         return ret;
     }
 
+    clearInterfaces();
+
     mGnssMeasurementCbIface = callback;
     mGnssMeasurementCbIface->linkToDeath(mGnssMeasurementDeathRecipient, 0);
 
     return mApi->measurementSetCallback(callback);
 }
 
-Return<void> GnssMeasurement::close()  {
-    if (mApi == nullptr) {
-        LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
-        return Void();
-    }
-
+void GnssMeasurement::clearInterfaces() {
     if (mGnssMeasurementCbIface != nullptr) {
         mGnssMeasurementCbIface->unlinkToDeath(mGnssMeasurementDeathRecipient);
         mGnssMeasurementCbIface = nullptr;
@@ -95,6 +92,15 @@
         mGnssMeasurementCbIface_2_0->unlinkToDeath(mGnssMeasurementDeathRecipient);
         mGnssMeasurementCbIface_2_0 = nullptr;
     }
+}
+
+Return<void> GnssMeasurement::close()  {
+    if (mApi == nullptr) {
+        LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+        return Void();
+    }
+
+    clearInterfaces();
     mApi->measurementClose();
 
     return Void();
@@ -120,6 +126,8 @@
         return ret;
     }
 
+    clearInterfaces();
+
     mGnssMeasurementCbIface_1_1 = callback;
     mGnssMeasurementCbIface_1_1->linkToDeath(mGnssMeasurementDeathRecipient, 0);
 
@@ -149,6 +157,8 @@
         return ret;
     }
 
+    clearInterfaces();
+
     mGnssMeasurementCbIface_2_0 = callback;
     mGnssMeasurementCbIface_2_0->linkToDeath(mGnssMeasurementDeathRecipient, 0);
 
diff --git a/android/2.0/GnssMeasurement.h b/android/2.0/GnssMeasurement.h
index 000b00f..7fa66b4 100644
--- a/android/2.0/GnssMeasurement.h
+++ b/android/2.0/GnssMeasurement.h
@@ -75,6 +75,7 @@
     sp<V1_1::IGnssMeasurementCallback> mGnssMeasurementCbIface_1_1 = nullptr;
     sp<V2_0::IGnssMeasurementCallback> mGnssMeasurementCbIface_2_0 = nullptr;
     MeasurementAPIClient* mApi;
+    void clearInterfaces();
 };
 
 }  // namespace implementation
diff --git a/android/visibility_control/1.0/GnssVisibilityControl.cpp b/android/2.0/GnssVisibilityControl.cpp
similarity index 100%
rename from android/visibility_control/1.0/GnssVisibilityControl.cpp
rename to android/2.0/GnssVisibilityControl.cpp
diff --git a/android/visibility_control/1.0/GnssVisibilityControl.h b/android/2.0/GnssVisibilityControl.h
similarity index 100%
rename from android/visibility_control/1.0/GnssVisibilityControl.h
rename to android/2.0/GnssVisibilityControl.h
diff --git a/android/measurement_corrections/1.0/MeasurementCorrections.cpp b/android/2.0/MeasurementCorrections.cpp
similarity index 90%
rename from android/measurement_corrections/1.0/MeasurementCorrections.cpp
rename to android/2.0/MeasurementCorrections.cpp
index 2c93cb3..bb75073 100644
--- a/android/measurement_corrections/1.0/MeasurementCorrections.cpp
+++ b/android/2.0/MeasurementCorrections.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -54,7 +54,9 @@
 MeasurementCorrections::~MeasurementCorrections() {
 }
 
-Return<bool> MeasurementCorrections::setCorrections(const ::android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections& /*corrections*/) {
+Return<bool> MeasurementCorrections::setCorrections(
+        const ::android::hardware::gnss::measurement_corrections::
+                V1_0::MeasurementCorrections& /*corrections*/) {
     return true;
 }
 
diff --git a/android/measurement_corrections/1.0/MeasurementCorrections.h b/android/2.0/MeasurementCorrections.h
similarity index 92%
rename from android/measurement_corrections/1.0/MeasurementCorrections.h
rename to android/2.0/MeasurementCorrections.h
index ad534dc..96b1120 100644
--- a/android/measurement_corrections/1.0/MeasurementCorrections.h
+++ b/android/2.0/MeasurementCorrections.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -59,10 +59,11 @@
     ~MeasurementCorrections();
 
 // Methods from ::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections follow.
-Return<bool> setCorrections(const ::android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections& corrections) override;
+Return<bool> setCorrections(
+        const ::android::hardware::gnss::measurement_corrections::
+                V1_0::MeasurementCorrections& corrections) override;
 
 Return<bool> setCallback(const sp<IMeasurementCorrectionsCallback>& callback) override;
-
 };
 
 
diff --git a/android/2.0/location_api/BatchingAPIClient.cpp b/android/2.0/location_api/BatchingAPIClient.cpp
index 49cd18a..766c37a 100644
--- a/android/2.0/location_api/BatchingAPIClient.cpp
+++ b/android/2.0/location_api/BatchingAPIClient.cpp
@@ -30,6 +30,7 @@
 #define LOG_NDEBUG 0
 #define LOG_TAG "LocSvc_BatchingAPIClient"
 
+#include <inttypes.h>
 #include <log_util.h>
 #include <loc_cfg.h>
 
@@ -191,7 +192,7 @@
 
 void BatchingAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)
 {
-    LOC_LOGD("%s]: (%02x)", __FUNCTION__, capabilitiesMask);
+    LOC_LOGD("%s]: (%" PRIu64 ")", __FUNCTION__, capabilitiesMask);
     mLocationCapabilitiesMask = capabilitiesMask;
 }
 
diff --git a/android/2.0/location_api/BatchingAPIClient.h b/android/2.0/location_api/BatchingAPIClient.h
index 7198341..d2d9b4a 100644
--- a/android/2.0/location_api/BatchingAPIClient.h
+++ b/android/2.0/location_api/BatchingAPIClient.h
@@ -50,7 +50,6 @@
     BatchingAPIClient(const sp<V2_0::IGnssBatchingCallback>& callback);
     void gnssUpdateCallbacks(const sp<V1_0::IGnssBatchingCallback>& callback);
     void gnssUpdateCallbacks_2_0(const sp<V2_0::IGnssBatchingCallback>& callback);
-    ~BatchingAPIClient();
     int getBatchSize();
     int startSession(const V1_0::IGnssBatching::Options& options);
     int updateSessionOptions(const V1_0::IGnssBatching::Options& options);
@@ -66,6 +65,8 @@
 
 private:
     void setCallbacks();
+    ~BatchingAPIClient();
+
     std::mutex mMutex;
     sp<V1_0::IGnssBatchingCallback> mGnssBatchingCbIface;
     uint32_t mDefaultId;
diff --git a/android/2.0/location_api/GeofenceAPIClient.h b/android/2.0/location_api/GeofenceAPIClient.h
index 71049de..5bce476 100644
--- a/android/2.0/location_api/GeofenceAPIClient.h
+++ b/android/2.0/location_api/GeofenceAPIClient.h
@@ -46,7 +46,6 @@
 {
 public:
     GeofenceAPIClient(const sp<V1_0::IGnssGeofenceCallback>& callback);
-    virtual ~GeofenceAPIClient() = default;
 
     void geofenceAdd(uint32_t geofence_id, double latitude, double longitude,
             double radius_meters, int32_t last_transition, int32_t monitor_transitions,
@@ -65,6 +64,8 @@
     void onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final;
 
 private:
+    virtual ~GeofenceAPIClient() = default;
+
     sp<V1_0::IGnssGeofenceCallback> mGnssGeofencingCbIface;
 };
 
diff --git a/android/2.0/location_api/GnssAPIClient.cpp b/android/2.0/location_api/GnssAPIClient.cpp
index d505241..44007d9 100644
--- a/android/2.0/location_api/GnssAPIClient.cpp
+++ b/android/2.0/location_api/GnssAPIClient.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -31,6 +31,7 @@
 #define LOG_TAG "LocSvc_GnssAPIClient"
 #define SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC (590 * 60 * 60 * 1000) // 590 hours
 
+#include <inttypes.h>
 #include <log_util.h>
 #include <loc_cfg.h>
 
@@ -123,9 +124,7 @@
     locationCallbacks.gnssNiCb = nullptr;
     if (mGnssNiCbIface != nullptr) {
         loc_core::ContextBase* context =
-                loc_core::LocContext::getLocContext(
-                        NULL, NULL,
-                        loc_core::LocContext::mLocationHalName, false);
+                loc_core::LocContext::getLocContext(loc_core::LocContext::mLocationHalName);
         if (!context->hasAgpsExtendedCapabilities()) {
             LOC_LOGD("Registering NI CB");
             locationCallbacks.gnssNiCb = [this](uint32_t id, GnssNiNotification gnssNiNotify) {
@@ -351,7 +350,7 @@
 // callbacks
 void GnssAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)
 {
-    LOC_LOGD("%s]: (%02x)", __FUNCTION__, capabilitiesMask);
+    LOC_LOGD("%s]: (%" PRIu64 ")", __FUNCTION__, capabilitiesMask);
     mLocationCapabilitiesMask = capabilitiesMask;
     mLocationCapabilitiesCached = true;
 
@@ -380,18 +379,20 @@
         if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT)
             data |= IGnssCallback::Capabilities::SATELLITE_BLACKLIST;
 
-        IGnssCallback::GnssSystemInfo gnssInfo;
-        if (capabilitiesMask & LOCATION_CAPABILITIES_PRIVACY_BIT) {
-            gnssInfo.yearOfHw = 2019;
-        } else if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT ||
-            capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT) {
-            gnssInfo.yearOfHw = 2018;
-        } else if (capabilitiesMask & LOCATION_CAPABILITIES_DEBUG_NMEA_BIT) {
-            gnssInfo.yearOfHw = 2017;
-        } else if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) {
-            gnssInfo.yearOfHw = 2016;
-        } else {
-            gnssInfo.yearOfHw = 2015;
+        IGnssCallback::GnssSystemInfo gnssInfo = { .yearOfHw = 2015 };
+
+        if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) {
+            gnssInfo.yearOfHw++; // 2016
+            if (capabilitiesMask & LOCATION_CAPABILITIES_DEBUG_NMEA_BIT) {
+                gnssInfo.yearOfHw++; // 2017
+                if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT ||
+                    capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT) {
+                    gnssInfo.yearOfHw++; // 2018
+                    if (capabilitiesMask & LOCATION_CAPABILITIES_PRIVACY_BIT) {
+                        gnssInfo.yearOfHw++; // 2019
+                    }
+                }
+            }
         }
         LOC_LOGV("%s:%d] set_system_info_cb (%d)", __FUNCTION__, __LINE__, gnssInfo.yearOfHw);
 
@@ -678,7 +679,7 @@
         out.numSvs = static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT);
     }
     for (size_t i = 0; i < out.numSvs; i++) {
-        out.gnssSvList[i].svid = in.gnssSvs[i].svId;
+        convertGnssSvid(in.gnssSvs[i], out.gnssSvList[i].svid);
         convertGnssConstellationType(in.gnssSvs[i].type, out.gnssSvList[i].constellation);
         out.gnssSvList[i].cN0Dbhz = in.gnssSvs[i].cN0Dbhz;
         out.gnssSvList[i].elevationDegrees = in.gnssSvs[i].elevation;
@@ -701,7 +702,7 @@
 {
     out.resize(in.count);
     for (size_t i = 0; i < in.count; i++) {
-        out[i].v1_0.svid = in.gnssSvs[i].svId;
+        convertGnssSvid(in.gnssSvs[i], out[i].v1_0.svid);
         out[i].v1_0.cN0Dbhz = in.gnssSvs[i].cN0Dbhz;
         out[i].v1_0.elevationDegrees = in.gnssSvs[i].elevation;
         out[i].v1_0.azimuthDegrees = in.gnssSvs[i].azimuth;
diff --git a/android/2.0/location_api/GnssAPIClient.h b/android/2.0/location_api/GnssAPIClient.h
index 63b4561..cfa78c7 100644
--- a/android/2.0/location_api/GnssAPIClient.h
+++ b/android/2.0/location_api/GnssAPIClient.h
@@ -50,7 +50,6 @@
     GnssAPIClient(const sp<V1_0::IGnssCallback>& gpsCb,
             const sp<V1_0::IGnssNiCallback>& niCb);
     GnssAPIClient(const sp<V2_0::IGnssCallback>& gpsCb);
-    virtual ~GnssAPIClient();
     GnssAPIClient(const GnssAPIClient&) = delete;
     GnssAPIClient& operator=(const GnssAPIClient&) = delete;
 
@@ -93,6 +92,8 @@
     void onStopTrackingCb(LocationError error) final;
 
 private:
+    virtual ~GnssAPIClient();
+
     void setCallbacks();
     void initLocationOptions();
     sp<V1_0::IGnssCallback> mGnssCbIface;
diff --git a/android/2.0/location_api/LocationUtil.cpp b/android/2.0/location_api/LocationUtil.cpp
index 7e6810c..961b7b1 100644
--- a/android/2.0/location_api/LocationUtil.cpp
+++ b/android/2.0/location_api/LocationUtil.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -30,6 +30,8 @@
 #include <LocationUtil.h>
 #include <log_util.h>
 #include <inttypes.h>
+#include <gps_extended_c.h>
+#include <loc_misc_utils.h>
 
 namespace android {
 namespace hardware {
@@ -38,6 +40,7 @@
 namespace implementation {
 
 using ::android::hardware::gnss::V2_0::GnssLocation;
+using ::android::hardware::gnss::V2_0::ElapsedRealtimeFlags;
 using ::android::hardware::gnss::V2_0::GnssConstellationType;
 using ::android::hardware::gnss::V1_0::GnssLocationFlags;
 
@@ -81,73 +84,21 @@
     out.timestamp = static_cast<V1_0::GnssUtcTime>(in.timestamp);
 }
 
-bool getCurrentTime(struct timespec& currentTime, int64_t& sinceBootTimeNanos)
-{
-    struct timespec sinceBootTime;
-    struct timespec sinceBootTimeTest;
-    bool clockGetTimeSuccess = false;
-    const uint32_t MAX_TIME_DELTA_VALUE_NANOS = 10000;
-    const uint32_t MAX_GET_TIME_COUNT = 20;
-    /* Attempt to get CLOCK_REALTIME and CLOCK_BOOTIME in succession without an interruption
-    or context switch (for up to MAX_GET_TIME_COUNT times) to avoid errors in the calculation */
-    for (uint32_t i = 0; i < MAX_GET_TIME_COUNT; i++) {
-        if (clock_gettime(CLOCK_BOOTTIME, &sinceBootTime) != 0) {
-            break;
-        };
-        if (clock_gettime(CLOCK_REALTIME, &currentTime) != 0) {
-            break;
-        }
-        if (clock_gettime(CLOCK_BOOTTIME, &sinceBootTimeTest) != 0) {
-            break;
-        };
-        sinceBootTimeNanos = sinceBootTime.tv_sec * 1000000000 + sinceBootTime.tv_nsec;
-        int64_t sinceBootTimeTestNanos =
-            sinceBootTimeTest.tv_sec * 1000000000 + sinceBootTimeTest.tv_nsec;
-        int64_t sinceBootTimeDeltaNanos = sinceBootTimeTestNanos - sinceBootTimeNanos;
-
-        /* sinceBootTime and sinceBootTimeTest should have a close value if there was no
-        interruption or context switch between clock_gettime for CLOCK_BOOTIME and
-        clock_gettime for CLOCK_REALTIME */
-        if (sinceBootTimeDeltaNanos < MAX_TIME_DELTA_VALUE_NANOS) {
-            clockGetTimeSuccess = true;
-            break;
-        } else {
-            LOC_LOGd("Delta:%" PRIi64 "ns time too large, retry number #%u...",
-                     sinceBootTimeDeltaNanos, i + 1);
-        }
-    }
-    return clockGetTimeSuccess;
-}
-
 void convertGnssLocation(Location& in, V2_0::GnssLocation& out)
 {
     memset(&out, 0, sizeof(V2_0::GnssLocation));
     convertGnssLocation(in, out.v1_0);
 
-    struct timespec currentTime;
-    int64_t sinceBootTimeNanos;
-
-    if (getCurrentTime(currentTime, sinceBootTimeNanos)) {
-        int64_t currentTimeNanos = currentTime.tv_sec*1000000000 + currentTime.tv_nsec;
-        int64_t locationTimeNanos = in.timestamp*1000000;
-        LOC_LOGD("%s]: sinceBootTimeNanos:%" PRIi64 " currentTimeNanos:%" PRIi64 ""
-                " locationTimeNanos:%" PRIi64 "",
-                __FUNCTION__, sinceBootTimeNanos, currentTimeNanos, locationTimeNanos);
-        if (currentTimeNanos >= locationTimeNanos) {
-            int64_t ageTimeNanos = currentTimeNanos - locationTimeNanos;
-            LOC_LOGD("%s]: ageTimeNanos:%" PRIi64 ")", __FUNCTION__, ageTimeNanos);
-            if (ageTimeNanos >= 0 && ageTimeNanos <= sinceBootTimeNanos) {
-                out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS;
-                out.elapsedRealtime.timestampNs = sinceBootTimeNanos - ageTimeNanos;
-                out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS;
-                // time uncertainty is 1 ms since it is calculated from utc time that is in ms
-                out.elapsedRealtime.timeUncertaintyNs = 1000000;
-                LOC_LOGD("%s]: timestampNs:%" PRIi64 ")",
-                        __FUNCTION__, out.elapsedRealtime.timestampNs);
-            }
-        }
-    } else {
-        LOC_LOGe("Failed to calculate elapsedRealtimeNanos timestamp");
+    if (in.flags & LOCATION_HAS_ELAPSED_REAL_TIME) {
+        out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS;
+        out.elapsedRealtime.timestampNs = in.elapsedRealTime;
+        out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS;
+        out.elapsedRealtime.timeUncertaintyNs = in.elapsedRealTimeUnc;
+        LOC_LOGd("out.elapsedRealtime.timestampNs=%" PRIi64 ""
+                 " out.elapsedRealtime.timeUncertaintyNs=%" PRIi64 ""
+                 " out.elapsedRealtime.flags=0x%X",
+                 out.elapsedRealtime.timestampNs,
+                 out.elapsedRealtime.timeUncertaintyNs, out.elapsedRealtime.flags);
     }
 }
 
@@ -256,6 +207,74 @@
     }
 }
 
+void convertGnssSvid(GnssSv& in, int16_t& out)
+{
+    switch (in.type) {
+        case GNSS_SV_TYPE_GPS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_SBAS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_GLONASS:
+            if (!isGloSlotUnknown(in.svId)) { // OSN is known
+                out = in.svId - GLO_SV_PRN_MIN + 1;
+            } else { // OSN is not known, report FCN
+                out = in.gloFrequency + 92;
+            }
+            break;
+        case GNSS_SV_TYPE_QZSS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_BEIDOU:
+            out = in.svId - BDS_SV_PRN_MIN + 1;
+            break;
+        case GNSS_SV_TYPE_GALILEO:
+            out = in.svId - GAL_SV_PRN_MIN + 1;
+            break;
+        case GNSS_SV_TYPE_NAVIC:
+            out = in.svId - NAVIC_SV_PRN_MIN + 1;
+            break;
+        default:
+            out = in.svId;
+            break;
+    }
+}
+
+void convertGnssSvid(GnssMeasurementsData& in, int16_t& out)
+{
+    switch (in.svType) {
+        case GNSS_SV_TYPE_GPS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_SBAS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_GLONASS:
+            if (!isGloSlotUnknown(in.svId)) { // OSN is known
+                out = in.svId - GLO_SV_PRN_MIN + 1;
+            } else { // OSN is not known, report FCN
+                out = in.gloFrequency + 92;
+            }
+            break;
+        case GNSS_SV_TYPE_QZSS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_BEIDOU:
+            out = in.svId - BDS_SV_PRN_MIN + 1;
+            break;
+        case GNSS_SV_TYPE_GALILEO:
+            out = in.svId - GAL_SV_PRN_MIN + 1;
+            break;
+        case GNSS_SV_TYPE_NAVIC:
+            out = in.svId - NAVIC_SV_PRN_MIN + 1;
+            break;
+        default:
+            out = in.svId;
+            break;
+    }
+}
+
 void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out)
 {
     switch(in) {
diff --git a/android/2.0/location_api/LocationUtil.h b/android/2.0/location_api/LocationUtil.h
index d3dce23..70729e4 100644
--- a/android/2.0/location_api/LocationUtil.h
+++ b/android/2.0/location_api/LocationUtil.h
@@ -46,10 +46,11 @@
 void convertGnssLocation(const V2_0::GnssLocation& in, Location& out);
 void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out);
 void convertGnssConstellationType(GnssSvType& in, V2_0::GnssConstellationType& out);
+void convertGnssSvid(GnssSv& in, int16_t& out);
+void convertGnssSvid(GnssMeasurementsData& in, int16_t& out);
 void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out);
 void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out);
 void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out);
-bool getCurrentTime(struct timespec& currentTime, int64_t& sinceBootTimeNanos);
 
 }  // namespace implementation
 }  // namespace V2_0
diff --git a/android/2.0/location_api/MeasurementAPIClient.cpp b/android/2.0/location_api/MeasurementAPIClient.cpp
index b87e508..425415f 100644
--- a/android/2.0/location_api/MeasurementAPIClient.cpp
+++ b/android/2.0/location_api/MeasurementAPIClient.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -36,6 +36,7 @@
 
 #include "LocationUtil.h"
 #include "MeasurementAPIClient.h"
+#include <loc_misc_utils.h>
 
 namespace android {
 namespace hardware {
@@ -57,6 +58,8 @@
 static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out);
 static void convertGnssMeasurementsCodeType(GnssMeasurementsCodeType& in,
         ::android::hardware::hidl_string& out);
+static void convertElapsedRealtimeNanos(GnssMeasurementsNotification& in,
+        ::android::hardware::gnss::V2_0::ElapsedRealtime& elapsedRealtimeNanos);
 
 MeasurementAPIClient::MeasurementAPIClient() :
     mGnssMeasurementCbIface(nullptr),
@@ -72,6 +75,13 @@
     LOC_LOGD("%s]: ()", __FUNCTION__);
 }
 
+void MeasurementAPIClient::clearInterfaces()
+{
+    mGnssMeasurementCbIface = nullptr;
+    mGnssMeasurementCbIface_1_1 = nullptr;
+    mGnssMeasurementCbIface_2_0 = nullptr;
+}
+
 // for GpsInterface
 Return<IGnssMeasurement::GnssMeasurementStatus>
 MeasurementAPIClient::measurementSetCallback(const sp<V1_0::IGnssMeasurementCallback>& callback)
@@ -79,6 +89,7 @@
     LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
 
     mMutex.lock();
+    clearInterfaces();
     mGnssMeasurementCbIface = callback;
     mMutex.unlock();
 
@@ -94,6 +105,7 @@
             __FUNCTION__, &callback, (int)powerMode, timeBetweenMeasurement);
 
     mMutex.lock();
+    clearInterfaces();
     mGnssMeasurementCbIface_1_1 = callback;
     mMutex.unlock();
 
@@ -109,6 +121,7 @@
         __FUNCTION__, &callback, (int)powerMode, timeBetweenMeasurement);
 
     mMutex.lock();
+    clearInterfaces();
     mGnssMeasurementCbIface_2_0 = callback;
     mMutex.unlock();
 
@@ -231,7 +244,7 @@
         out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE_UNCERTAINTY;
     if (in.flags & GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT)
         out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_AUTOMATIC_GAIN_CONTROL;
-    out.svid = in.svId;
+    convertGnssSvid(in, out.svid);
     convertGnssConstellationType(in.svType, out.constellation);
     out.timeOffsetNs = in.timeOffsetNs;
     if (in.stateMask & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT)
@@ -296,7 +309,7 @@
 
 static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out)
 {
-    memset(&out, 0, sizeof(IGnssMeasurementCallback::GnssClock));
+    memset(&out, 0, sizeof(out));
     if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT)
         out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_LEAP_SECOND;
     if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_TIME_UNCERTAINTY_BIT)
@@ -325,6 +338,7 @@
 static void convertGnssData(GnssMeasurementsNotification& in,
         V1_0::IGnssMeasurementCallback::GnssData& out)
 {
+    memset(&out, 0, sizeof(out));
     out.measurementCount = in.count;
     if (out.measurementCount > static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT)) {
         LOC_LOGW("%s]: Too many measurement %u. Clamps to %d.",
@@ -340,6 +354,7 @@
 static void convertGnssData_1_1(GnssMeasurementsNotification& in,
         V1_1::IGnssMeasurementCallback::GnssData& out)
 {
+    memset(&out, 0, sizeof(out));
     out.measurements.resize(in.count);
     for (size_t i = 0; i < in.count; i++) {
         convertGnssMeasurement(in.measurements[i], out.measurements[i].v1_0);
@@ -362,6 +377,7 @@
 static void convertGnssData_2_0(GnssMeasurementsNotification& in,
         V2_0::IGnssMeasurementCallback::GnssData& out)
 {
+    memset(&out, 0, sizeof(out));
     out.measurements.resize(in.count);
     for (size_t i = 0; i < in.count; i++) {
         convertGnssMeasurement(in.measurements[i], out.measurements[i].v1_1.v1_0);
@@ -415,40 +431,21 @@
             out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_2ND_CODE_LOCK;
     }
     convertGnssClock(in.clock, out.clock);
+    convertElapsedRealtimeNanos(in, out.elapsedRealtime);
+}
 
-    const uint32_t UTC_TO_GPS_SECONDS = 315964800;
-    struct timespec currentTime;
-    int64_t sinceBootTimeNanos;
-
-    if (getCurrentTime(currentTime, sinceBootTimeNanos) &&
-        in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT &&
-        in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_FULL_BIAS_BIT &&
-        in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_BIT &&
-        in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_UNCERTAINTY_BIT) {
-        int64_t currentTimeNanos = currentTime.tv_sec * 1000000000 + currentTime.tv_nsec;
-        int64_t measTimeNanos = (int64_t)in.clock.timeNs - (int64_t)in.clock.fullBiasNs
-                - (int64_t)in.clock.biasNs - (int64_t)in.clock.leapSecond * 1000000000
-                + (int64_t)UTC_TO_GPS_SECONDS * 1000000000;
-
-        LOC_LOGd("sinceBootTimeNanos:%" PRIi64 " currentTimeNanos:%" PRIi64 ""
-                 " measTimeNanos:%" PRIi64 "",
-                 sinceBootTimeNanos, currentTimeNanos, measTimeNanos);
-        if (currentTimeNanos >= measTimeNanos) {
-            int64_t ageTimeNanos = currentTimeNanos - measTimeNanos;
-            LOC_LOGD("%s]: ageTimeNanos:%" PRIi64 ")", __FUNCTION__, ageTimeNanos);
-            if (ageTimeNanos >= 0 && ageTimeNanos <= sinceBootTimeNanos) {
-                out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS;
-                out.elapsedRealtime.timestampNs = sinceBootTimeNanos - ageTimeNanos;
-                out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS;
-                // time uncertainty is 1 ms since it is calculated from utc time that is in ms
-                out.elapsedRealtime.timeUncertaintyNs = 1000000;
-                LOC_LOGd("timestampNs:%" PRIi64 ") timeUncertaintyNs:%" PRIi64 ")",
-                         out.elapsedRealtime.timestampNs,
-                         out.elapsedRealtime.timeUncertaintyNs);
-            }
-        }
-    } else {
-        LOC_LOGe("Failed to calculate elapsedRealtimeNanos timestamp");
+static void convertElapsedRealtimeNanos(GnssMeasurementsNotification& in,
+        ::android::hardware::gnss::V2_0::ElapsedRealtime& elapsedRealtime)
+{
+    if (in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_ELAPSED_REAL_TIME_BIT) {
+        elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS;
+        elapsedRealtime.timestampNs = in.clock.elapsedRealTime;
+        elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS;
+        elapsedRealtime.timeUncertaintyNs = in.clock.elapsedRealTimeUnc;
+        LOC_LOGd("elapsedRealtime.timestampNs=%" PRIi64 ""
+                 " elapsedRealtime.timeUncertaintyNs=%" PRIi64 " elapsedRealtime.flags=0x%X",
+                 elapsedRealtime.timestampNs,
+                 elapsedRealtime.timeUncertaintyNs, elapsedRealtime.flags);
     }
 }
 
diff --git a/android/2.0/location_api/MeasurementAPIClient.h b/android/2.0/location_api/MeasurementAPIClient.h
index 4146a13..6c2d38d 100644
--- a/android/2.0/location_api/MeasurementAPIClient.h
+++ b/android/2.0/location_api/MeasurementAPIClient.h
@@ -49,7 +49,6 @@
 {
 public:
     MeasurementAPIClient();
-    virtual ~MeasurementAPIClient();
     MeasurementAPIClient(const MeasurementAPIClient&) = delete;
     MeasurementAPIClient& operator=(const MeasurementAPIClient&) = delete;
 
@@ -73,12 +72,14 @@
     void onGnssMeasurementsCb(GnssMeasurementsNotification gnssMeasurementsNotification) final;
 
 private:
+    virtual ~MeasurementAPIClient();
+
     std::mutex mMutex;
     sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface;
     sp<V1_1::IGnssMeasurementCallback> mGnssMeasurementCbIface_1_1;
     sp<V2_0::IGnssMeasurementCallback> mGnssMeasurementCbIface_2_0;
-
     bool mTracking;
+    void clearInterfaces();
 };
 
 }  // namespace implementation
diff --git a/android/2.0/service.cpp b/android/2.0/service.cpp
index 664c661..fd957de 100644
--- a/android/2.0/service.cpp
+++ b/android/2.0/service.cpp
@@ -60,20 +60,18 @@
 
     status = registerPassthroughServiceImplementation<IGnss>();
     if (status == OK) {
-        if (vendorEnhanced) {
     #ifdef LOC_HIDL_VERSION
-            #define VENDOR_ENHANCED_LIB "vendor.qti.gnss@" LOC_HIDL_VERSION "-service.so"
+        #define VENDOR_ENHANCED_LIB "vendor.qti.gnss@" LOC_HIDL_VERSION "-service.so"
 
-            void* libHandle = NULL;
-            vendorEnhancedServiceMain* vendorEnhancedMainMethod = (vendorEnhancedServiceMain*)
-                    dlGetSymFromLib(libHandle, VENDOR_ENHANCED_LIB, "main");
-            if (NULL != vendorEnhancedMainMethod) {
-                (*vendorEnhancedMainMethod)(0, NULL);
-            }
-    #else
-            ALOGE("LOC_HIDL_VERSION not defined.");
-    #endif
+        void* libHandle = NULL;
+        vendorEnhancedServiceMain* vendorEnhancedMainMethod = (vendorEnhancedServiceMain*)
+                dlGetSymFromLib(libHandle, VENDOR_ENHANCED_LIB, "main");
+        if (NULL != vendorEnhancedMainMethod) {
+            (*vendorEnhancedMainMethod)(0, NULL);
         }
+    #else
+        ALOGI("LOC_HIDL_VERSION not defined.");
+    #endif
 
         joinRpcThreadpool();
 
diff --git a/android/2.1/AGnss.cpp b/android/2.1/AGnss.cpp
new file mode 100644
index 0000000..ce7b3aa
--- /dev/null
+++ b/android/2.1/AGnss.cpp
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_AGnssInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "AGnss.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+static AGnss* spAGnss = nullptr;
+
+AGnss::AGnss(Gnss* gnss) : mGnss(gnss), mType(LOC_AGPS_TYPE_INVALID) {
+    spAGnss = this;
+}
+
+AGnss::~AGnss() {
+    spAGnss = nullptr;
+}
+
+void AGnss::agnssStatusIpV4Cb(AGnssExtStatusIpV4 status) {
+    if (nullptr != spAGnss) {
+        spAGnss->statusCb(status.type, status.status);
+    }
+}
+
+void AGnss::statusCb(AGpsExtType type, LocAGpsStatusValue status) {
+
+    V2_0::IAGnssCallback::AGnssType  aType;
+    IAGnssCallback::AGnssStatusValue aStatus;
+
+    // cache the AGps Type
+    mType = type;
+
+    switch (type) {
+    case LOC_AGPS_TYPE_SUPL:
+        aType = IAGnssCallback::AGnssType::SUPL;
+        break;
+    case LOC_AGPS_TYPE_SUPL_ES:
+        aType = IAGnssCallback::AGnssType::SUPL_EIMS;
+        break;
+    default:
+        LOC_LOGE("invalid type: %d", type);
+        return;
+    }
+
+    switch (status) {
+    case LOC_GPS_REQUEST_AGPS_DATA_CONN:
+        aStatus = IAGnssCallback::AGnssStatusValue::REQUEST_AGNSS_DATA_CONN;
+        break;
+    case LOC_GPS_RELEASE_AGPS_DATA_CONN:
+        aStatus = IAGnssCallback::AGnssStatusValue::RELEASE_AGNSS_DATA_CONN;
+        break;
+    case LOC_GPS_AGPS_DATA_CONNECTED:
+        aStatus = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONNECTED;
+        break;
+    case LOC_GPS_AGPS_DATA_CONN_DONE:
+        aStatus = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_DONE;
+        break;
+    case LOC_GPS_AGPS_DATA_CONN_FAILED:
+        aStatus = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_FAILED;
+        break;
+    default:
+        LOC_LOGE("invalid status: %d", status);
+        return;
+    }
+
+    if (mAGnssCbIface != nullptr) {
+        auto r = mAGnssCbIface->agnssStatusCb(aType, aStatus);
+        if (!r.isOk()) {
+            LOC_LOGw("Error invoking AGNSS status cb %s", r.description().c_str());
+        }
+    }
+    else {
+        LOC_LOGw("setCallback has not been called yet");
+    }
+}
+
+Return<void> AGnss::setCallback(const sp<V2_0::IAGnssCallback>& callback) {
+
+    if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+        LOC_LOGE("Null GNSS interface");
+        return Void();
+    }
+
+    // Save the interface
+    mAGnssCbIface = callback;
+
+    AgpsCbInfo cbInfo = {};
+    cbInfo.statusV4Cb = (void*)agnssStatusIpV4Cb;
+    cbInfo.atlType = AGPS_ATL_TYPE_SUPL | AGPS_ATL_TYPE_SUPL_ES;
+
+    mGnss->getGnssInterface()->agpsInit(cbInfo);
+    return Void();
+}
+
+Return<bool> AGnss::dataConnClosed() {
+
+    if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+        LOC_LOGE("Null GNSS interface");
+        return false;
+    }
+
+    mGnss->getGnssInterface()->agpsDataConnClosed(LOC_AGPS_TYPE_SUPL);
+    return true;
+}
+
+Return<bool> AGnss::dataConnFailed() {
+
+    if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+        LOC_LOGE("Null GNSS interface");
+        return false;
+    }
+
+    mGnss->getGnssInterface()->agpsDataConnFailed(LOC_AGPS_TYPE_SUPL);
+    return true;
+}
+
+Return<bool> AGnss::dataConnOpen(uint64_t /*networkHandle*/, const hidl_string& apn,
+        V2_0::IAGnss::ApnIpType apnIpType) {
+
+    if (mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+        LOC_LOGE("Null GNSS interface");
+        return false;
+    }
+
+    std::string apnString(apn.c_str());
+    // During Emergency SUPL, an apn name of "sos" means that no
+    // apn was found, like in the simless case, so apn is cleared
+    if (LOC_AGPS_TYPE_SUPL_ES == mType && "sos" == apnString) {
+        LOC_LOGD("dataConnOpen APN name = [sos] cleared");
+        apnString.clear();
+    }
+
+    LOC_LOGD("dataConnOpen APN name = [%s]", apnString.c_str());
+
+    AGpsBearerType bearerType;
+    switch (apnIpType) {
+    case IAGnss::ApnIpType::IPV4:
+        bearerType = AGPS_APN_BEARER_IPV4;
+        break;
+    case IAGnss::ApnIpType::IPV6:
+        bearerType = AGPS_APN_BEARER_IPV6;
+        break;
+    case IAGnss::ApnIpType::IPV4V6:
+        bearerType = AGPS_APN_BEARER_IPV4V6;
+        break;
+    default:
+        bearerType = AGPS_APN_BEARER_IPV4;
+        break;
+    }
+
+    mGnss->getGnssInterface()->agpsDataConnOpen(
+        LOC_AGPS_TYPE_SUPL, apnString.c_str(), apnString.size(), (int)bearerType);
+    return true;
+}
+
+Return<bool> AGnss::setServer(V2_0::IAGnssCallback::AGnssType type,
+                              const hidl_string& hostname,
+                              int32_t port) {
+    if (mGnss == nullptr) {
+        LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+        return false;
+    }
+
+    GnssConfig config;
+    memset(&config, 0, sizeof(GnssConfig));
+    config.size = sizeof(GnssConfig);
+    config.flags = GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT;
+    config.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer);
+    if (type == IAGnssCallback::AGnssType::SUPL) {
+        config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL;
+    } else if (type == IAGnssCallback::AGnssType::C2K) {
+        config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_C2K;
+    } else if (type == IAGnssCallback::AGnssType::SUPL_EIMS) {
+        config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL_EIMS;
+    } else if (type == IAGnssCallback::AGnssType::SUPL_IMS) {
+        config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL_IMS;
+    } else {
+        LOC_LOGE("%s]: invalid AGnssType: %d", __FUNCTION__, static_cast<uint8_t>(type));
+        return false;
+    }
+    config.assistanceServer.hostName = strdup(hostname.c_str());
+    config.assistanceServer.port = port;
+    return mGnss->updateConfiguration(config);
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/android/2.1/AGnss.h b/android/2.1/AGnss.h
new file mode 100644
index 0000000..cf9c8a7
--- /dev/null
+++ b/android/2.1/AGnss.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_AGNSS_H
+#define ANDROID_HARDWARE_GNSS_V2_0_AGNSS_H
+
+#include <android/hardware/gnss/2.0/IAGnss.h>
+#include <hidl/Status.h>
+#include <gps_extended_c.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+using ::android::hardware::gnss::V2_0::IAGnssCallback;
+
+struct Gnss;
+struct AGnss : public V2_0::IAGnss {
+
+    AGnss(Gnss* gnss);
+    ~AGnss();
+    /*
+     * Methods from ::android::hardware::gnss::V2_0::IAGnss interface follow.
+     * These declarations were generated from IAGnss.hal.
+     */
+    Return<void> setCallback(const sp<V2_0::IAGnssCallback>& callback) override;
+
+    Return<bool> dataConnClosed() override;
+
+    Return<bool> dataConnFailed() override;
+
+    Return<bool> dataConnOpen(uint64_t networkHandle, const hidl_string& apn,
+            V2_0::IAGnss::ApnIpType apnIpType) override;
+
+    Return<bool> setServer(V2_0::IAGnssCallback::AGnssType type,
+                         const hidl_string& hostname, int32_t port) override;
+
+    void statusCb(AGpsExtType type, LocAGpsStatusValue status);
+
+    /* Data call setup callback passed down to GNSS HAL implementation */
+    static void agnssStatusIpV4Cb(AGnssExtStatusIpV4 status);
+
+ private:
+    Gnss* mGnss = nullptr;
+    sp<V2_0::IAGnssCallback> mAGnssCbIface = nullptr;
+
+    AGpsExtType mType;
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GNSS_V2_0_AGNSS_H
diff --git a/android/2.1/AGnssRil.cpp b/android/2.1/AGnssRil.cpp
new file mode 100644
index 0000000..f413e93
--- /dev/null
+++ b/android/2.1/AGnssRil.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc__AGnssRilInterface"
+
+#include <log_util.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sstream>
+#include <string>
+#include "Gnss.h"
+#include "AGnssRil.h"
+#include <DataItemConcreteTypesBase.h>
+
+typedef void* (getLocationInterface)();
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+
+AGnssRil::AGnssRil(Gnss* gnss) : mGnss(gnss) {
+    ENTRY_LOG_CALLFLOW();
+}
+
+AGnssRil::~AGnssRil() {
+    ENTRY_LOG_CALLFLOW();
+}
+
+Return<bool> AGnssRil::updateNetworkState(bool connected, NetworkType type, bool /*roaming*/) {
+    ENTRY_LOG_CALLFLOW();
+    // Extra NetworkTypes not available in IAgnssRil enums
+    const int NetworkType_BLUETOOTH = 7;
+    const int NetworkType_ETHERNET = 9;
+    const int NetworkType_PROXY = 16;
+    std::string apn("");
+
+    // for XTRA
+    if (nullptr != mGnss && ( nullptr != mGnss->getGnssInterface() )) {
+        int8_t typeout = loc_core::TYPE_UNKNOWN;
+        switch(type)
+        {
+            case IAGnssRil::NetworkType::MOBILE:
+                typeout = loc_core::TYPE_MOBILE;
+                break;
+            case IAGnssRil::NetworkType::WIFI:
+                typeout = loc_core::TYPE_WIFI;
+                break;
+            case IAGnssRil::NetworkType::MMS:
+                typeout = loc_core::TYPE_MMS;
+                break;
+            case IAGnssRil::NetworkType::SUPL:
+                typeout = loc_core::TYPE_SUPL;
+                break;
+            case IAGnssRil::NetworkType::DUN:
+                typeout = loc_core::TYPE_DUN;
+                break;
+            case IAGnssRil::NetworkType::HIPRI:
+                typeout = loc_core::TYPE_HIPRI;
+                break;
+            case IAGnssRil::NetworkType::WIMAX:
+                typeout = loc_core::TYPE_WIMAX;
+                break;
+            default:
+                {
+                    int networkType = (int) type;
+                    // Handling network types not available in IAgnssRil
+                    switch(networkType)
+                    {
+                        case NetworkType_BLUETOOTH:
+                            typeout = loc_core::TYPE_BLUETOOTH;
+                            break;
+                        case NetworkType_ETHERNET:
+                            typeout = loc_core::TYPE_ETHERNET;
+                            break;
+                        case NetworkType_PROXY:
+                            typeout = loc_core::TYPE_PROXY;
+                            break;
+                        default:
+                            typeout = loc_core::TYPE_UNKNOWN;
+                    }
+                }
+                break;
+        }
+        mGnss->getGnssInterface()->updateConnectionStatus(connected, typeout, false, 0, apn);
+    }
+    return true;
+}
+Return<bool> AGnssRil::updateNetworkState_2_0(const V2_0::IAGnssRil::NetworkAttributes& attributes) {
+    ENTRY_LOG_CALLFLOW();
+    std::string apn = attributes.apn;
+    if (nullptr != mGnss && (nullptr != mGnss->getGnssInterface())) {
+        int8_t typeout = loc_core::TYPE_UNKNOWN;
+        bool roaming = false;
+        if (attributes.capabilities & IAGnssRil::NetworkCapability::NOT_METERED) {
+            typeout = loc_core::TYPE_WIFI;
+        } else {
+            typeout = loc_core::TYPE_MOBILE;
+        }
+        if (attributes.capabilities & IAGnssRil::NetworkCapability::NOT_ROAMING) {
+            roaming = false;
+        }
+        LOC_LOGd("apn string received is: %s", apn.c_str());
+        mGnss->getGnssInterface()->updateConnectionStatus(attributes.isConnected,
+                typeout, roaming, (NetworkHandle) attributes.networkHandle, apn);
+    }
+    return true;
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/android/2.1/AGnssRil.h b/android/2.1/AGnssRil.h
new file mode 100644
index 0000000..2bf6156
--- /dev/null
+++ b/android/2.1/AGnssRil.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_AGNSSRIL_H_
+#define ANDROID_HARDWARE_GNSS_V2_0_AGNSSRIL_H_
+
+#include <android/hardware/gnss/2.0/IAGnssRil.h>
+#include <hidl/Status.h>
+#include <location_interface.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+/*
+ * Extended interface for AGNSS RIL support. An Assisted GNSS Radio Interface Layer interface
+ * allows the GNSS chipset to request radio interface layer information from Android platform.
+ * Examples of such information are reference location, unique subscriber ID, phone number string
+ * and network availability changes. Also contains wrapper methods to allow methods from
+ * IAGnssiRilCallback interface to be passed into the conventional implementation of the GNSS HAL.
+ */
+struct AGnssRil : public V2_0::IAGnssRil {
+    AGnssRil(Gnss* gnss);
+    ~AGnssRil();
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IAGnssRil follow.
+     * These declarations were generated from IAGnssRil.hal.
+     */
+    Return<void> setCallback(const sp<V1_0::IAGnssRilCallback>& /*callback*/) override {
+        return Void();
+    }
+    Return<void> setRefLocation(const V1_0::IAGnssRil::AGnssRefLocation& /*agnssReflocation*/) override {
+        return Void();
+    }
+    Return<bool> setSetId(V1_0::IAGnssRil::SetIDType /*type*/, const hidl_string& /*setid*/) override {
+        return false;
+    }
+    Return<bool> updateNetworkAvailability(bool /*available*/,
+                                    const hidl_string& /*apn*/) override {
+        return false;
+    }
+    Return<bool> updateNetworkState(bool connected, V1_0::IAGnssRil::NetworkType type, bool roaming) override;
+
+    // Methods from ::android::hardware::gnss::V2_0::IAGnssRil follow
+    Return<bool> updateNetworkState_2_0(const V2_0::IAGnssRil::NetworkAttributes& attributes) override;
+
+ private:
+    Gnss* mGnss = nullptr;
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GNSS_V2_0_AGNSSRIL_H_
diff --git a/android/2.1/Android.mk b/android/2.1/Android.mk
new file mode 100644
index 0000000..6bd2be1
--- /dev/null
+++ b/android/2.1/Android.mk
@@ -0,0 +1,118 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gnss@2.1-impl-qti
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-BSD legacy_not_a_contribution
+LOCAL_LICENSE_CONDITIONS := by_exception_only not_allowed notice
+# activate the following line for debug purposes only, comment out for production
+#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    AGnss.cpp \
+    Gnss.cpp \
+    AGnssRil.cpp \
+    GnssMeasurement.cpp \
+    GnssConfiguration.cpp \
+    GnssBatching.cpp \
+    GnssGeofencing.cpp \
+    GnssNi.cpp \
+    GnssDebug.cpp \
+    GnssAntennaInfo.cpp \
+    MeasurementCorrections.cpp \
+    GnssVisibilityControl.cpp
+
+LOCAL_SRC_FILES += \
+    location_api/GnssAPIClient.cpp \
+    location_api/MeasurementAPIClient.cpp \
+    location_api/GeofenceAPIClient.cpp \
+    location_api/BatchingAPIClient.cpp \
+    location_api/LocationUtil.cpp \
+
+ifeq ($(GNSS_HIDL_LEGACY_MEASURMENTS),true)
+LOCAL_CFLAGS += \
+     -DGNSS_HIDL_LEGACY_MEASURMENTS
+endif
+
+LOCAL_C_INCLUDES:= \
+    $(LOCAL_PATH)/location_api
+
+LOCAL_HEADER_LIBRARIES := \
+    libgps.utils_headers \
+    libloc_core_headers \
+    libloc_pla_headers \
+    liblocation_api_headers \
+    liblocbatterylistener_headers
+
+LOCAL_SHARED_LIBRARIES := \
+    liblog \
+    libhidlbase \
+    libcutils \
+    libutils \
+    android.hardware.gnss@1.0 \
+    android.hardware.gnss@1.1 \
+    android.hardware.gnss@2.0 \
+    android.hardware.gnss@2.1 \
+    android.hardware.gnss.measurement_corrections@1.0 \
+    android.hardware.gnss.measurement_corrections@1.1 \
+    android.hardware.gnss.visibility_control@1.0 \
+    android.hardware.health@1.0 \
+    android.hardware.health@2.0 \
+    android.hardware.health@2.1 \
+    android.hardware.power@1.2 \
+    libbase
+
+LOCAL_SHARED_LIBRARIES += \
+    libloc_core \
+    libgps.utils \
+    libdl \
+    liblocation_api \
+
+LOCAL_CFLAGS += $(GNSS_CFLAGS)
+LOCAL_STATIC_LIBRARIES := liblocbatterylistener
+LOCAL_STATIC_LIBRARIES += libhealthhalutils
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gnss@2.1-service-qti
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-BSD legacy_not_a_contribution
+LOCAL_LICENSE_CONDITIONS := by_exception_only not_allowed notice
+# activate the following line for debug purposes only, comment out for production
+#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
+LOCAL_VINTF_FRAGMENTS := android.hardware.gnss@2.1-service-qti.xml
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_INIT_RC := android.hardware.gnss@2.1-service-qti.rc
+LOCAL_SRC_FILES := \
+    service.cpp \
+
+LOCAL_HEADER_LIBRARIES := \
+    libgps.utils_headers \
+    libloc_core_headers \
+    libloc_pla_headers \
+    liblocation_api_headers
+
+
+LOCAL_SHARED_LIBRARIES := \
+    liblog \
+    libcutils \
+    libdl \
+    libbase \
+    libutils \
+    libgps.utils \
+    libqti_vndfwk_detect \
+
+LOCAL_SHARED_LIBRARIES += \
+    libhidlbase \
+    android.hardware.gnss@1.0 \
+    android.hardware.gnss@1.1 \
+    android.hardware.gnss@2.0 \
+    android.hardware.gnss@2.1 \
+
+LOCAL_CFLAGS += $(GNSS_CFLAGS)
+
+ifneq ($(LOC_HIDL_VERSION),)
+LOCAL_CFLAGS += -DLOC_HIDL_VERSION='"$(LOC_HIDL_VERSION)"'
+endif
+
+include $(BUILD_EXECUTABLE)
diff --git a/android/2.1/Gnss.cpp b/android/2.1/Gnss.cpp
new file mode 100644
index 0000000..37e1cc5
--- /dev/null
+++ b/android/2.1/Gnss.cpp
@@ -0,0 +1,800 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2_0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2_0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssInterface"
+#define LOG_NDEBUG 0
+
+#include <fstream>
+#include <log_util.h>
+#include <dlfcn.h>
+#include <cutils/properties.h>
+#include "Gnss.h"
+#include "LocationUtil.h"
+#include "battery_listener.h"
+#include "loc_misc_utils.h"
+
+typedef const GnssInterface* (getLocationInterface)();
+
+#define IMAGES_INFO_FILE "/sys/devices/soc0/images"
+#define DELIMITER ";"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::visibility_control::V1_0::implementation::GnssVisibilityControl;
+using ::android::hardware::gnss::measurement_corrections::V1_1::
+        implementation::MeasurementCorrections;
+static sp<Gnss> sGnss;
+static std::string getVersionString() {
+    static std::string version;
+    if (!version.empty())
+        return version;
+
+    char value[PROPERTY_VALUE_MAX] = {0};
+    property_get("ro.hardware", value, "unknown");
+    version.append(value).append(DELIMITER);
+
+    std::ifstream in(IMAGES_INFO_FILE);
+    std::string s;
+    while(getline(in, s)) {
+        std::size_t found = s.find("CRM:");
+        if (std::string::npos == found) {
+            continue;
+        }
+
+        // skip over space characters after "CRM:"
+        const char* substr = s.c_str();
+        found += 4;
+        while (0 != substr[found] && isspace(substr[found])) {
+            found++;
+        }
+        if (s.find("11:") != found) {
+            continue;
+        }
+        s.erase(0, found + 3);
+
+        found = s.find_first_of("\r\n");
+        if (std::string::npos != found) {
+            s.erase(s.begin() + found, s.end());
+        }
+        version.append(s).append(DELIMITER);
+    }
+    return version;
+}
+
+void Gnss::GnssDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) {
+    LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+            __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+    if (mGnss != nullptr) {
+        mGnss->getGnssInterface()->resetNetworkInfo();
+        mGnss->cleanup();
+    }
+}
+
+void location_on_battery_status_changed(bool charging) {
+    LOC_LOGd("battery status changed to %s charging", charging ? "" : "not");
+    if (sGnss != nullptr) {
+        sGnss->getGnssInterface()->updateBatteryStatus(charging);
+    }
+}
+Gnss::Gnss() {
+    ENTRY_LOG_CALLFLOW();
+    sGnss = this;
+    // initilize gnss interface at first in case needing notify battery status
+    sGnss->getGnssInterface()->initialize();
+    // register health client to listen on battery change
+    loc_extn_battery_properties_listener_init(location_on_battery_status_changed);
+    // clear pending GnssConfig
+    memset(&mPendingConfig, 0, sizeof(GnssConfig));
+    mGnssDeathRecipient = new GnssDeathRecipient(this);
+}
+
+Gnss::~Gnss() {
+    ENTRY_LOG_CALLFLOW();
+    if (mApi != nullptr) {
+        mApi->destroy();
+        mApi = nullptr;
+    }
+    sGnss = nullptr;
+}
+
+GnssAPIClient* Gnss::getApi() {
+    if (mApi != nullptr) {
+        return mApi;
+    }
+
+    if (mGnssCbIface_2_1 != nullptr) {
+        mApi = new GnssAPIClient(mGnssCbIface_2_1);
+    } else if (mGnssCbIface_2_0 != nullptr) {
+        mApi = new GnssAPIClient(mGnssCbIface_2_0);
+    } else if (mGnssCbIface_1_1 != nullptr) {
+        mApi = new GnssAPIClient(mGnssCbIface_1_1, mGnssNiCbIface);
+    } else if (mGnssCbIface != nullptr) {
+        mApi = new GnssAPIClient(mGnssCbIface, mGnssNiCbIface);
+    } else {
+        LOC_LOGW("%s] GnssAPIClient is not ready", __FUNCTION__);
+        return mApi;
+    }
+
+    if (mPendingConfig.size == sizeof(GnssConfig)) {
+        // we have pending GnssConfig
+        mApi->gnssConfigurationUpdate(mPendingConfig);
+        // clear size to invalid mPendingConfig
+        mPendingConfig.size = 0;
+        if (mPendingConfig.assistanceServer.hostName != nullptr) {
+            free((void*)mPendingConfig.assistanceServer.hostName);
+        }
+    }
+
+    return mApi;
+}
+
+const GnssInterface* Gnss::getGnssInterface() {
+    static bool getGnssInterfaceFailed = false;
+    if (mGnssInterface == nullptr && !getGnssInterfaceFailed) {
+        void * libHandle = nullptr;
+        getLocationInterface* getter = (getLocationInterface*)
+                dlGetSymFromLib(libHandle, "libgnss.so", "getGnssInterface");
+        if (NULL == getter) {
+            getGnssInterfaceFailed = true;
+        } else {
+            mGnssInterface = (GnssInterface*)(*getter)();
+        }
+    }
+    return mGnssInterface;
+}
+
+Return<bool> Gnss::setCallback(const sp<V1_0::IGnssCallback>& callback)  {
+    ENTRY_LOG_CALLFLOW();
+
+    // In case where previous call to setCallback_1_1/setCallback_2_0/setCallback_2_1, then
+    // we need to cleanup these interfaces/callbacks here since we no longer
+    // do so in cleanup() function to keep callbacks around after cleanup()
+    if (mApi != nullptr) {
+        mApi->gnssUpdateCallbacks_2_0(nullptr);
+        mApi->gnssUpdateCallbacks_2_1(nullptr);
+    }
+    if (mGnssCbIface_1_1 != nullptr) {
+        mGnssCbIface_1_1->unlinkToDeath(mGnssDeathRecipient);
+        mGnssCbIface_1_1 = nullptr;
+    }
+    if (mGnssCbIface_2_0 != nullptr) {
+        mGnssCbIface_2_0->unlinkToDeath(mGnssDeathRecipient);
+        mGnssCbIface_2_0 = nullptr;
+    }
+    if (mGnssCbIface_2_1 != nullptr) {
+        mGnssCbIface_2_1->unlinkToDeath(mGnssDeathRecipient);
+        mGnssCbIface_2_1 = nullptr;
+    }
+
+
+    if (mGnssCbIface != nullptr) {
+        mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
+    }
+    mGnssCbIface = callback;
+    if (mGnssCbIface != nullptr) {
+        mGnssCbIface->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
+    }
+
+    GnssAPIClient* api = getApi();
+    if (api != nullptr) {
+        api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
+        api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
+        api->requestCapabilities();
+    }
+    return true;
+}
+
+Return<bool> Gnss::setGnssNiCb(const sp<IGnssNiCallback>& callback) {
+    ENTRY_LOG_CALLFLOW();
+    mGnssNiCbIface = callback;
+    GnssAPIClient* api = getApi();
+    if (api != nullptr) {
+        api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
+    }
+    return true;
+}
+
+Return<bool> Gnss::updateConfiguration(GnssConfig& gnssConfig) {
+    ENTRY_LOG_CALLFLOW();
+    GnssAPIClient* api = getApi();
+    if (api) {
+        api->gnssConfigurationUpdate(gnssConfig);
+    } else if (gnssConfig.flags != 0) {
+        // api is not ready yet, update mPendingConfig with gnssConfig
+        mPendingConfig.size = sizeof(GnssConfig);
+
+        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
+            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT;
+            mPendingConfig.gpsLock = gnssConfig.gpsLock;
+        }
+        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
+            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT;
+            mPendingConfig.suplVersion = gnssConfig.suplVersion;
+        }
+        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
+            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT;
+            mPendingConfig.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer);
+            mPendingConfig.assistanceServer.type = gnssConfig.assistanceServer.type;
+            if (mPendingConfig.assistanceServer.hostName != nullptr) {
+                free((void*)mPendingConfig.assistanceServer.hostName);
+                mPendingConfig.assistanceServer.hostName =
+                    strdup(gnssConfig.assistanceServer.hostName);
+            }
+            mPendingConfig.assistanceServer.port = gnssConfig.assistanceServer.port;
+        }
+        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
+            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
+            mPendingConfig.lppProfileMask = gnssConfig.lppProfileMask;
+        }
+        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
+            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT;
+            mPendingConfig.lppeControlPlaneMask = gnssConfig.lppeControlPlaneMask;
+        }
+        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
+            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT;
+            mPendingConfig.lppeUserPlaneMask = gnssConfig.lppeUserPlaneMask;
+        }
+        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
+            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT;
+            mPendingConfig.aGlonassPositionProtocolMask = gnssConfig.aGlonassPositionProtocolMask;
+        }
+        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
+            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT;
+            mPendingConfig.emergencyPdnForEmergencySupl = gnssConfig.emergencyPdnForEmergencySupl;
+        }
+        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
+            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT;
+            mPendingConfig.suplEmergencyServices = gnssConfig.suplEmergencyServices;
+        }
+        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
+            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_MODE_BIT;
+            mPendingConfig.suplModeMask = gnssConfig.suplModeMask;
+        }
+        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
+            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
+            mPendingConfig.blacklistedSvIds = gnssConfig.blacklistedSvIds;
+        }
+        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
+            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT;
+            mPendingConfig.emergencyExtensionSeconds = gnssConfig.emergencyExtensionSeconds;
+        }
+    }
+    return true;
+}
+
+Return<bool> Gnss::start()  {
+    ENTRY_LOG_CALLFLOW();
+    bool retVal = false;
+    GnssAPIClient* api = getApi();
+    if (api) {
+        retVal = api->gnssStart();
+    }
+    return retVal;
+}
+
+Return<bool> Gnss::stop()  {
+    ENTRY_LOG_CALLFLOW();
+    bool retVal = false;
+    GnssAPIClient* api = getApi();
+    if (api) {
+        retVal = api->gnssStop();
+    }
+    return retVal;
+}
+
+Return<void> Gnss::cleanup()  {
+    ENTRY_LOG_CALLFLOW();
+
+    if (mApi != nullptr) {
+        mApi->gnssStop();
+        mApi->gnssDisable();
+    }
+
+    return Void();
+}
+
+Return<bool> Gnss::injectLocation(double latitudeDegrees,
+                                  double longitudeDegrees,
+                                  float accuracyMeters)  {
+    ENTRY_LOG_CALLFLOW();
+    const GnssInterface* gnssInterface = getGnssInterface();
+    if (nullptr != gnssInterface) {
+        gnssInterface->injectLocation(latitudeDegrees, longitudeDegrees, accuracyMeters);
+        return true;
+    } else {
+        return false;
+    }
+}
+
+Return<bool> Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs,
+                              int32_t uncertaintyMs) {
+    return true;
+}
+
+Return<void> Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags)  {
+    ENTRY_LOG_CALLFLOW();
+    GnssAPIClient* api = getApi();
+    if (api) {
+        api->gnssDeleteAidingData(aidingDataFlags);
+    }
+    return Void();
+}
+
+Return<bool> Gnss::setPositionMode(V1_0::IGnss::GnssPositionMode mode,
+                                   V1_0::IGnss::GnssPositionRecurrence recurrence,
+                                   uint32_t minIntervalMs,
+                                   uint32_t preferredAccuracyMeters,
+                                   uint32_t preferredTimeMs)  {
+    ENTRY_LOG_CALLFLOW();
+    bool retVal = false;
+    GnssAPIClient* api = getApi();
+    if (api) {
+        retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs,
+                preferredAccuracyMeters, preferredTimeMs);
+    }
+    return retVal;
+}
+
+Return<sp<V1_0::IAGnss>> Gnss::getExtensionAGnss()  {
+    ENTRY_LOG_CALLFLOW();
+    // deprecated function. Must return nullptr to pass VTS
+    return nullptr;
+}
+
+Return<sp<V1_0::IGnssNi>> Gnss::getExtensionGnssNi()  {
+    ENTRY_LOG_CALLFLOW();
+    // deprecated function. Must return nullptr to pass VTS
+    return nullptr;
+}
+
+Return<sp<V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
+    ENTRY_LOG_CALLFLOW();
+    if (mGnssMeasurement == nullptr) {
+        mGnssMeasurement = new GnssMeasurement();
+    }
+    return mGnssMeasurement;
+}
+
+Return<sp<V1_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration()  {
+    ENTRY_LOG_CALLFLOW();
+    if (mGnssConfig == nullptr) {
+        mGnssConfig = new GnssConfiguration(this);
+    }
+    return mGnssConfig;
+}
+
+Return<sp<V1_0::IGnssGeofencing>> Gnss::getExtensionGnssGeofencing()  {
+    ENTRY_LOG_CALLFLOW();
+    if (mGnssGeofencingIface == nullptr) {
+        mGnssGeofencingIface = new GnssGeofencing();
+    }
+    return mGnssGeofencingIface;
+}
+
+Return<sp<V1_0::IGnssBatching>> Gnss::getExtensionGnssBatching()  {
+    ENTRY_LOG_CALLFLOW();
+    if (mGnssBatching == nullptr) {
+        mGnssBatching = new GnssBatching();
+    }
+    return mGnssBatching;
+}
+
+Return<sp<V1_0::IGnssDebug>> Gnss::getExtensionGnssDebug() {
+    ENTRY_LOG_CALLFLOW();
+    if (mGnssDebug == nullptr) {
+        mGnssDebug = new GnssDebug(this);
+    }
+    return mGnssDebug;
+}
+
+Return<sp<V1_0::IAGnssRil>> Gnss::getExtensionAGnssRil() {
+    ENTRY_LOG_CALLFLOW();
+    if (mGnssRil == nullptr) {
+        mGnssRil = new AGnssRil(this);
+    }
+    return mGnssRil;
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnss follow.
+Return<bool> Gnss::setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) {
+    ENTRY_LOG_CALLFLOW();
+    auto r = callback->gnssNameCb(getVersionString());
+    if (!r.isOk()) {
+        LOC_LOGE("%s] Error from gnssNameCb description=%s",
+                __func__, r.description().c_str());
+    }
+
+    // In case where previous call to setCallback/setCallback_2_0/setCallback_2_1, then
+    // we need to cleanup these interfaces/callbacks here since we no longer
+    // do so in cleanup() function to keep callbacks around after cleanup()
+    if (mApi != nullptr) {
+        mApi->gnssUpdateCallbacks_2_0(nullptr);
+        mApi->gnssUpdateCallbacks_2_1(nullptr);
+    }
+    if (mGnssCbIface != nullptr) {
+        mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
+        mGnssCbIface = nullptr;
+    }
+    if (mGnssCbIface_2_0 != nullptr) {
+        mGnssCbIface_2_0->unlinkToDeath(mGnssDeathRecipient);
+        mGnssCbIface_2_0 = nullptr;
+    }
+    if (mGnssCbIface_2_1 != nullptr) {
+        mGnssCbIface_2_1->unlinkToDeath(mGnssDeathRecipient);
+        mGnssCbIface_2_1 = nullptr;
+    }
+
+
+    if (mGnssCbIface_1_1 != nullptr) {
+        mGnssCbIface_1_1->unlinkToDeath(mGnssDeathRecipient);
+    }
+    mGnssCbIface_1_1 = callback;
+    if (mGnssCbIface_1_1 != nullptr) {
+        mGnssCbIface_1_1->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
+    }
+
+    const GnssInterface* gnssInterface = getGnssInterface();
+    if (nullptr != gnssInterface) {
+        OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) {
+            odcpiRequestCb(odcpiRequest);
+        };
+        gnssInterface->odcpiInit(cb, OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW);
+    }
+
+    GnssAPIClient* api = getApi();
+    if (api != nullptr) {
+        api->gnssUpdateCallbacks(mGnssCbIface_1_1, mGnssNiCbIface);
+        api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
+        api->requestCapabilities();
+    }
+
+    return true;
+}
+
+Return<bool> Gnss::setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode,
+        V1_0::IGnss::GnssPositionRecurrence recurrence,
+        uint32_t minIntervalMs,
+        uint32_t preferredAccuracyMeters,
+        uint32_t preferredTimeMs,
+        bool lowPowerMode) {
+    ENTRY_LOG_CALLFLOW();
+    bool retVal = false;
+    GnssAPIClient* api = getApi();
+    if (api) {
+        GnssPowerMode powerMode = lowPowerMode?
+                GNSS_POWER_MODE_M4 : GNSS_POWER_MODE_M2;
+        retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs,
+                preferredAccuracyMeters, preferredTimeMs, powerMode, minIntervalMs);
+    }
+    return retVal;
+}
+
+Return<sp<V1_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_1_1() {
+    ENTRY_LOG_CALLFLOW();
+#ifdef GNSS_HIDL_LEGACY_MEASURMENTS
+    return nullptr;
+#else
+    if (mGnssMeasurement == nullptr)
+        mGnssMeasurement = new GnssMeasurement();
+    return mGnssMeasurement;
+#endif
+}
+
+Return<sp<V1_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_1_1() {
+    ENTRY_LOG_CALLFLOW();
+    if (mGnssConfig == nullptr)
+        mGnssConfig = new GnssConfiguration(this);
+    return mGnssConfig;
+}
+
+Return<bool> Gnss::injectBestLocation(const GnssLocation& gnssLocation) {
+    ENTRY_LOG_CALLFLOW();
+    const GnssInterface* gnssInterface = getGnssInterface();
+    if (nullptr != gnssInterface) {
+        Location location = {};
+        convertGnssLocation(gnssLocation, location);
+        gnssInterface->odcpiInject(location);
+    }
+    return true;
+}
+
+void Gnss::odcpiRequestCb(const OdcpiRequestInfo& request) {
+    ENTRY_LOG_CALLFLOW();
+    if (ODCPI_REQUEST_TYPE_STOP == request.type) {
+        return;
+    }
+    if (mGnssCbIface_2_1 != nullptr) {
+        // For emergency mode, request DBH (Device based hybrid) location
+        // Mark Independent from GNSS flag to false.
+        if (ODCPI_REQUEST_TYPE_START == request.type) {
+            LOC_LOGd("gnssRequestLocationCb_2_1 isUserEmergency = %d", request.isEmergencyMode);
+            auto r = mGnssCbIface_2_1->gnssRequestLocationCb_2_0(!request.isEmergencyMode,
+                                                                 request.isEmergencyMode);
+            if (!r.isOk()) {
+                LOC_LOGe("Error invoking gnssRequestLocationCb_2_0 %s", r.description().c_str());
+            }
+        } else {
+            LOC_LOGv("Unsupported ODCPI request type: %d", request.type);
+        }
+    } else if (mGnssCbIface_2_0 != nullptr) {
+        // For emergency mode, request DBH (Device based hybrid) location
+        // Mark Independent from GNSS flag to false.
+        if (ODCPI_REQUEST_TYPE_START == request.type) {
+            LOC_LOGd("gnssRequestLocationCb_2_0 isUserEmergency = %d", request.isEmergencyMode);
+            auto r = mGnssCbIface_2_0->gnssRequestLocationCb_2_0(!request.isEmergencyMode,
+                                                                 request.isEmergencyMode);
+            if (!r.isOk()) {
+                LOC_LOGe("Error invoking gnssRequestLocationCb_2_0 %s", r.description().c_str());
+            }
+        } else {
+            LOC_LOGv("Unsupported ODCPI request type: %d", request.type);
+        }
+    } else if (mGnssCbIface_1_1 != nullptr) {
+        // For emergency mode, request DBH (Device based hybrid) location
+        // Mark Independent from GNSS flag to false.
+        if (ODCPI_REQUEST_TYPE_START == request.type) {
+            auto r = mGnssCbIface_1_1->gnssRequestLocationCb(!request.isEmergencyMode);
+            if (!r.isOk()) {
+                LOC_LOGe("Error invoking gnssRequestLocationCb %s", r.description().c_str());
+            }
+        } else {
+            LOC_LOGv("Unsupported ODCPI request type: %d", request.type);
+        }
+    } else {
+        LOC_LOGe("ODCPI request not supported.");
+    }
+}
+
+// Methods from ::android::hardware::gnss::V2_0::IGnss follow.
+Return<bool> Gnss::setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) {
+    ENTRY_LOG_CALLFLOW();
+    auto r = callback->gnssNameCb(getVersionString());
+    if (!r.isOk()) {
+        LOC_LOGE("%s] Error from gnssNameCb description=%s",
+                __func__, r.description().c_str());
+    }
+
+    // In case where previous call to setCallback/setCallback_1_1/setCallback_2_1, then
+    // we need to cleanup these interfaces/callbacks here since we no longer
+    // do so in cleanup() function to keep callbacks around after cleanup()
+    if (mApi != nullptr) {
+        mApi->gnssUpdateCallbacks(nullptr, nullptr);
+        mApi->gnssUpdateCallbacks_2_1(nullptr);
+    }
+    mGnssNiCbIface = nullptr;
+    if (mGnssCbIface != nullptr) {
+        mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
+        mGnssCbIface = nullptr;
+    }
+    if (mGnssCbIface_1_1 != nullptr) {
+        mGnssCbIface_1_1->unlinkToDeath(mGnssDeathRecipient);
+        mGnssCbIface_1_1 = nullptr;
+    }
+    if (mGnssCbIface_2_1 != nullptr) {
+        mGnssCbIface_2_1->unlinkToDeath(mGnssDeathRecipient);
+        mGnssCbIface_2_1 = nullptr;
+    }
+
+
+    if (mGnssCbIface_2_0 != nullptr) {
+        mGnssCbIface_2_0->unlinkToDeath(mGnssDeathRecipient);
+    }
+    mGnssCbIface_2_0 = callback;
+    if (mGnssCbIface_2_0 != nullptr) {
+        mGnssCbIface_2_0->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
+    }
+
+    const GnssInterface* gnssInterface = getGnssInterface();
+    if (nullptr != gnssInterface) {
+        OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) {
+            odcpiRequestCb(odcpiRequest);
+        };
+        gnssInterface->odcpiInit(cb, OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW);
+    }
+
+    GnssAPIClient* api = getApi();
+    if (api != nullptr) {
+        api->gnssUpdateCallbacks_2_0(mGnssCbIface_2_0);
+        api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
+        api->requestCapabilities();
+    }
+
+    return true;
+}
+
+Return<sp<V2_0::IAGnss>> Gnss::getExtensionAGnss_2_0() {
+    ENTRY_LOG_CALLFLOW();
+    if (mAGnssIface_2_0 == nullptr) {
+        mAGnssIface_2_0 = new AGnss(this);
+    }
+    return mAGnssIface_2_0;
+}
+Return<sp<V2_0::IAGnssRil>> Gnss::getExtensionAGnssRil_2_0() {
+
+    if (mGnssRil == nullptr) {
+        mGnssRil = new AGnssRil(this);
+    }
+    return mGnssRil;
+}
+
+Return<sp<V2_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_2_0() {
+    ENTRY_LOG_CALLFLOW();
+    if (mGnssConfig == nullptr) {
+        mGnssConfig = new GnssConfiguration(this);
+    }
+    return mGnssConfig;
+}
+Return<sp<V2_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_2_0() {
+    ENTRY_LOG_CALLFLOW();
+#ifdef GNSS_HIDL_LEGACY_MEASURMENTS
+    return nullptr;
+#else
+    if (mGnssMeasurement == nullptr)
+        mGnssMeasurement = new GnssMeasurement();
+    return mGnssMeasurement;
+#endif
+}
+
+Return<sp<IMeasurementCorrectionsV1_0>>
+        Gnss::getExtensionMeasurementCorrections() {
+    ENTRY_LOG_CALLFLOW();
+    if (mGnssMeasCorr == nullptr) {
+        mGnssMeasCorr = new MeasurementCorrections(this);
+    }
+    return mGnssMeasCorr;
+}
+
+Return<sp<IMeasurementCorrectionsV1_1>>
+        Gnss::getExtensionMeasurementCorrections_1_1() {
+    ENTRY_LOG_CALLFLOW();
+    if (mGnssMeasCorr == nullptr) {
+        mGnssMeasCorr = new MeasurementCorrections(this);
+    }
+    return mGnssMeasCorr;
+}
+
+Return<sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl>>
+        Gnss::getExtensionVisibilityControl() {
+    ENTRY_LOG_CALLFLOW();
+    if (mVisibCtrl == nullptr) {
+        mVisibCtrl = new GnssVisibilityControl(this);
+    }
+    return mVisibCtrl;
+}
+
+Return<bool> Gnss::injectBestLocation_2_0(const V2_0::GnssLocation& gnssLocation) {
+    ENTRY_LOG_CALLFLOW();
+    const GnssInterface* gnssInterface = getGnssInterface();
+    if (nullptr != gnssInterface) {
+        Location location = {};
+        convertGnssLocation(gnssLocation, location);
+        gnssInterface->odcpiInject(location);
+    }
+    return true;
+}
+
+Return<sp<V2_0::IGnssDebug>> Gnss::getExtensionGnssDebug_2_0() {
+    ENTRY_LOG_CALLFLOW();
+    if (mGnssDebug == nullptr) {
+        mGnssDebug = new GnssDebug(this);
+    }
+    return mGnssDebug;
+}
+
+Return<sp<V2_0::IGnssBatching>> Gnss::getExtensionGnssBatching_2_0() {
+    return nullptr;
+}
+
+// Methods from ::android::hardware::gnss::V2_1::IGnss follow.
+Return<bool> Gnss::setCallback_2_1(const sp<V2_1::IGnssCallback>& callback) {
+    ENTRY_LOG_CALLFLOW();
+    auto r = callback->gnssNameCb(getVersionString());
+    if (!r.isOk()) {
+        LOC_LOGE("%s] Error from gnssNameCb description=%s",
+                __func__, r.description().c_str());
+    }
+
+    // In case where previous call to setCallback/setCallback_1_1/setCallback_2_0, then
+    // we need to cleanup these interfaces/callbacks here since we no longer
+    // do so in cleanup() function to keep callbacks around after cleanup()
+    if (mApi != nullptr) {
+        mApi->gnssUpdateCallbacks(nullptr, nullptr);
+        mApi->gnssUpdateCallbacks_2_0(nullptr);
+    }
+    mGnssNiCbIface = nullptr;
+    if (mGnssCbIface != nullptr) {
+        mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
+        mGnssCbIface = nullptr;
+    }
+    if (mGnssCbIface_1_1 != nullptr) {
+        mGnssCbIface_1_1->unlinkToDeath(mGnssDeathRecipient);
+        mGnssCbIface_1_1 = nullptr;
+    }
+    if (mGnssCbIface_2_0 != nullptr) {
+        mGnssCbIface_2_0->unlinkToDeath(mGnssDeathRecipient);
+        mGnssCbIface_2_0 = nullptr;
+    }
+    if (mGnssCbIface_2_1 != nullptr) {
+        mGnssCbIface_2_1->unlinkToDeath(mGnssDeathRecipient);
+    }
+    mGnssCbIface_2_1 = callback;
+    if (mGnssCbIface_2_1 != nullptr) {
+        mGnssCbIface_2_1->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
+    }
+
+    const GnssInterface* gnssInterface = getGnssInterface();
+    if (gnssInterface != nullptr) {
+        OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) {
+            odcpiRequestCb(odcpiRequest);
+        };
+        gnssInterface->odcpiInit(cb, OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW);
+    }
+
+    GnssAPIClient* api = getApi();
+    if (api != nullptr) {
+        api->gnssUpdateCallbacks_2_1(mGnssCbIface_2_1);
+        api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
+        api->requestCapabilities();
+    }
+
+    return true;
+}
+Return<sp<V2_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_2_1() {
+    ENTRY_LOG_CALLFLOW();
+    if (mGnssMeasurement == nullptr) {
+        mGnssMeasurement = new GnssMeasurement();
+    }
+    return mGnssMeasurement;
+}
+Return<sp<V2_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_2_1() {
+    ENTRY_LOG_CALLFLOW();
+    if (mGnssConfig == nullptr) {
+        mGnssConfig = new GnssConfiguration(this);
+    }
+    return mGnssConfig;
+}
+
+Return<sp<V2_1::IGnssAntennaInfo>> Gnss::getExtensionGnssAntennaInfo() {
+    ENTRY_LOG_CALLFLOW();
+    if (mGnssAntennaInfo == nullptr) {
+        mGnssAntennaInfo = new GnssAntennaInfo(this);
+    }
+    return mGnssAntennaInfo;
+}
+
+V1_0::IGnss* HIDL_FETCH_IGnss(const char* hal) {
+    ENTRY_LOG_CALLFLOW();
+    V1_0::IGnss* iface = nullptr;
+    iface = new Gnss();
+    if (iface == nullptr) {
+        LOC_LOGE("%s]: failed to get %s", __FUNCTION__, hal);
+    }
+    return iface;
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/android/2.1/Gnss.h b/android/2.1/Gnss.h
new file mode 100644
index 0000000..c383882
--- /dev/null
+++ b/android/2.1/Gnss.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2_0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2_0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_1_GNSS_H
+#define ANDROID_HARDWARE_GNSS_V2_1_GNSS_H
+
+#include <AGnss.h>
+#include <AGnssRil.h>
+#include <GnssConfiguration.h>
+#include <GnssMeasurement.h>
+#include <GnssBatching.h>
+#include <GnssGeofencing.h>
+#include <GnssNi.h>
+#include <GnssDebug.h>
+#include <GnssAntennaInfo.h>
+
+#include <android/hardware/gnss/2.1/IGnss.h>
+#include <android/hardware/gnss/measurement_corrections/1.1/IMeasurementCorrections.h>
+#include <MeasurementCorrections.h>
+#include <GnssVisibilityControl.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include "GnssAPIClient.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+using IMeasurementCorrectionsV1_0 =
+        ::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
+using IMeasurementCorrectionsV1_1 =
+        ::android::hardware::gnss::measurement_corrections::V1_1::IMeasurementCorrections;
+using ::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl;
+
+struct Gnss : public IGnss {
+    Gnss();
+    ~Gnss();
+
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnss follow.
+     * These declarations were generated from Gnss.hal.
+     */
+    Return<bool> setCallback(const sp<V1_0::IGnssCallback>& callback)  override;
+    Return<bool> start()  override;
+    Return<bool> stop()  override;
+    Return<void> cleanup()  override;
+    Return<bool> injectLocation(double latitudeDegrees,
+                                double longitudeDegrees,
+                                float accuracyMeters)  override;
+    Return<bool> injectTime(int64_t timeMs,
+                            int64_t timeReferenceMs,
+                            int32_t uncertaintyMs) override;
+    Return<void> deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags)  override;
+    Return<bool> setPositionMode(V1_0::IGnss::GnssPositionMode mode,
+                                 V1_0::IGnss::GnssPositionRecurrence recurrence,
+                                 uint32_t minIntervalMs,
+                                 uint32_t preferredAccuracyMeters,
+                                 uint32_t preferredTimeMs)  override;
+    Return<sp<V1_0::IAGnss>> getExtensionAGnss() override;
+    Return<sp<V1_0::IGnssNi>> getExtensionGnssNi() override;
+    Return<sp<V1_0::IGnssMeasurement>> getExtensionGnssMeasurement() override;
+    Return<sp<V1_0::IGnssConfiguration>> getExtensionGnssConfiguration() override;
+    Return<sp<V1_0::IGnssGeofencing>> getExtensionGnssGeofencing() override;
+    Return<sp<V1_0::IGnssBatching>> getExtensionGnssBatching() override;
+
+    Return<sp<V1_0::IAGnssRil>> getExtensionAGnssRil() override;
+
+    inline Return<sp<V1_0::IGnssNavigationMessage>> getExtensionGnssNavigationMessage() override {
+        return nullptr;
+    }
+
+    inline Return<sp<V1_0::IGnssXtra>> getExtensionXtra() override {
+        return nullptr;
+    }
+
+    Return<sp<V1_0::IGnssDebug>> getExtensionGnssDebug() override;
+
+    // Methods from ::android::hardware::gnss::V1_1::IGnss follow.
+    Return<bool> setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) override;
+    Return<bool> setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode,
+            V1_0::IGnss::GnssPositionRecurrence recurrence,
+            uint32_t minIntervalMs, uint32_t preferredAccuracyMeters,
+            uint32_t preferredTimeMs, bool lowPowerMode) override;
+    Return<sp<V1_1::IGnssMeasurement>> getExtensionGnssMeasurement_1_1() override;
+    Return<sp<V1_1::IGnssConfiguration>> getExtensionGnssConfiguration_1_1() override;
+    Return<bool> injectBestLocation(const GnssLocation& location) override;
+
+    // Methods from ::android::hardware::gnss::V2_0::IGnss follow.
+    Return<bool> setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) override;
+    Return<sp<V2_0::IAGnss>> getExtensionAGnss_2_0() override;
+    Return<sp<V2_0::IAGnssRil>> getExtensionAGnssRil_2_0() override;
+
+    Return<sp<V2_0::IGnssConfiguration>> getExtensionGnssConfiguration_2_0() override;
+    Return<sp<IMeasurementCorrectionsV1_0>> getExtensionMeasurementCorrections() override;
+    Return<sp<IMeasurementCorrectionsV1_1>> getExtensionMeasurementCorrections_1_1() override;
+    Return<sp<V2_0::IGnssMeasurement>> getExtensionGnssMeasurement_2_0() override;
+
+    Return<bool> injectBestLocation_2_0(
+            const ::android::hardware::gnss::V2_0::GnssLocation& location) override;
+
+    Return<sp<V2_0::IGnssBatching>> getExtensionGnssBatching_2_0() override;
+    Return<sp<V2_0::IGnssDebug>> getExtensionGnssDebug_2_0() override;
+    Return<sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl>>
+            getExtensionVisibilityControl() override;
+
+    // Methods from ::android::hardware::gnss::V2_1::IGnss follow.
+    Return<bool> setCallback_2_1(const sp<V2_1::IGnssCallback>& callback) override;
+    Return<sp<V2_1::IGnssMeasurement>> getExtensionGnssMeasurement_2_1() override;
+    Return<sp<V2_1::IGnssConfiguration>> getExtensionGnssConfiguration_2_1() override;
+    Return<sp<V2_1::IGnssAntennaInfo>> getExtensionGnssAntennaInfo() override;
+
+    // These methods are not part of the IGnss base class.
+    GnssAPIClient* getApi();
+    Return<bool> setGnssNiCb(const sp<IGnssNiCallback>& niCb);
+    Return<bool> updateConfiguration(GnssConfig& gnssConfig);
+    const GnssInterface* getGnssInterface();
+
+    // Callback for ODCPI request
+    void odcpiRequestCb(const OdcpiRequestInfo& request);
+
+ private:
+    struct GnssDeathRecipient : hidl_death_recipient {
+        GnssDeathRecipient(sp<Gnss> gnss) : mGnss(gnss) {
+        }
+        ~GnssDeathRecipient() = default;
+        virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+        sp<Gnss> mGnss;
+    };
+
+ private:
+    sp<GnssDeathRecipient> mGnssDeathRecipient = nullptr;
+
+    sp<V1_0::IGnssNi> mGnssNi = nullptr;
+    sp<V1_0::IGnssGeofencing> mGnssGeofencingIface = nullptr;
+    sp<V1_0::IAGnss> mAGnssIface = nullptr;
+    sp<V1_0::IGnssCallback> mGnssCbIface = nullptr;
+    sp<V1_0::IGnssNiCallback> mGnssNiCbIface = nullptr;
+    sp<V1_1::IGnssCallback> mGnssCbIface_1_1 = nullptr;
+    sp<V2_0::IAGnss> mAGnssIface_2_0 = nullptr;
+    sp<V2_0::IAGnssRil> mGnssRil = nullptr;
+    sp<V2_0::IGnssBatching> mGnssBatching = nullptr;
+    sp<V2_0::IGnssDebug> mGnssDebug = nullptr;
+    sp<V2_0::IGnssCallback> mGnssCbIface_2_0 = nullptr;
+    sp<V2_1::IGnssCallback> mGnssCbIface_2_1 = nullptr;
+    sp<V2_1::IGnssMeasurement> mGnssMeasurement = nullptr;
+    sp<V2_1::IGnssConfiguration> mGnssConfig = nullptr;
+    sp<V2_1::IGnssAntennaInfo> mGnssAntennaInfo = nullptr;
+    sp<IMeasurementCorrectionsV1_1> mGnssMeasCorr = nullptr;
+    sp<IGnssVisibilityControl> mVisibCtrl = nullptr;
+
+    GnssAPIClient* mApi = nullptr;
+    GnssConfig mPendingConfig;
+    const GnssInterface* mGnssInterface = nullptr;
+};
+
+extern "C" V1_0::IGnss* HIDL_FETCH_IGnss(const char* name);
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GNSS_V2_1_GNSS_H
diff --git a/android/2.1/GnssAntennaInfo.cpp b/android/2.1/GnssAntennaInfo.cpp
new file mode 100644
index 0000000..62c4cc7
--- /dev/null
+++ b/android/2.1/GnssAntennaInfo.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#define LOG_TAG "LocSvc_GnssAntennaInfoInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssAntennaInfo.h"
+#include <android/hardware/gnss/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+static GnssAntennaInfo* spGnssAntennaInfo = nullptr;
+
+static void convertGnssAntennaInfo(std::vector<GnssAntennaInformation>& in,
+        hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& antennaInfos);
+
+void GnssAntennaInfo::GnssAntennaInfoDeathRecipient::serviceDied(uint64_t cookie,
+                                                                 const wp<IBase>& who) {
+    LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+            __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+    // we do nothing here
+    // Gnss::GnssDeathRecipient will stop the session
+    // However, we need to inform the adapter that the service has died
+    if (nullptr == spGnssAntennaInfo) {
+        LOC_LOGE("%s]: spGnssAntennaInfo is nullptr", __FUNCTION__);
+        return;
+    }
+    if (nullptr == spGnssAntennaInfo->mGnss) {
+        LOC_LOGE("%s]: spGnssAntennaInfo->mGnss is nullptr", __FUNCTION__);
+        return;
+    }
+
+    spGnssAntennaInfo->mGnss->getGnssInterface()->antennaInfoClose();
+}
+
+static void convertGnssAntennaInfo(std::vector<GnssAntennaInformation>& in,
+        hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& out) {
+
+    uint32_t vecSize, numberOfRows, numberOfColumns;
+    vecSize = in.size();
+    out.resize(vecSize);
+    for (uint32_t i = 0; i < vecSize; i++) {
+        out[i].carrierFrequencyMHz = in[i].carrierFrequencyMHz;
+        out[i].phaseCenterOffsetCoordinateMillimeters.x =
+                in[i].phaseCenterOffsetCoordinateMillimeters.x;
+        out[i].phaseCenterOffsetCoordinateMillimeters.xUncertainty =
+                in[i].phaseCenterOffsetCoordinateMillimeters.xUncertainty;
+        out[i].phaseCenterOffsetCoordinateMillimeters.y =
+                in[i].phaseCenterOffsetCoordinateMillimeters.y;
+        out[i].phaseCenterOffsetCoordinateMillimeters.yUncertainty =
+                in[i].phaseCenterOffsetCoordinateMillimeters.yUncertainty;
+        out[i].phaseCenterOffsetCoordinateMillimeters.z =
+                in[i].phaseCenterOffsetCoordinateMillimeters.z;
+        out[i].phaseCenterOffsetCoordinateMillimeters.zUncertainty =
+                in[i].phaseCenterOffsetCoordinateMillimeters.zUncertainty;
+
+        numberOfRows = in[i].phaseCenterVariationCorrectionMillimeters.size();
+        out[i].phaseCenterVariationCorrectionMillimeters.resize(numberOfRows);
+        for (uint32_t j = 0; j < numberOfRows; j++) {
+            numberOfColumns = in[i].phaseCenterVariationCorrectionMillimeters[j].size();
+            out[i].phaseCenterVariationCorrectionMillimeters[j].row.resize(numberOfColumns);
+            for (uint32_t k = 0; k < numberOfColumns; k++) {
+                out[i].phaseCenterVariationCorrectionMillimeters[j].row[k] =
+                        in[i].phaseCenterVariationCorrectionMillimeters[j][k];
+            }
+        }
+
+        numberOfRows = in[i].phaseCenterVariationCorrectionUncertaintyMillimeters.size();
+        out[i].phaseCenterVariationCorrectionUncertaintyMillimeters.resize(numberOfRows);
+        for (uint32_t j = 0; j < numberOfRows; j++) {
+            numberOfColumns = in[i].phaseCenterVariationCorrectionUncertaintyMillimeters[j].size();
+            out[i].phaseCenterVariationCorrectionUncertaintyMillimeters[j].
+                    row.resize(numberOfColumns);
+            for (uint32_t k = 0; k < numberOfColumns; k++) {
+                out[i].phaseCenterVariationCorrectionUncertaintyMillimeters[j].row[k] =
+                        in[i].phaseCenterVariationCorrectionUncertaintyMillimeters[j][k];
+            }
+        }
+
+        numberOfRows = in[i].signalGainCorrectionDbi.size();
+        out[i].signalGainCorrectionDbi.resize(numberOfRows);
+        for (uint32_t j = 0; j < numberOfRows; j++) {
+            numberOfColumns = in[i].signalGainCorrectionDbi[j].size();
+            out[i].signalGainCorrectionDbi[j].row.resize(numberOfColumns);
+            for (uint32_t k = 0; k < numberOfColumns; k++) {
+                out[i].signalGainCorrectionDbi[j].row[k] = in[i].signalGainCorrectionDbi[j][k];
+            }
+        }
+
+        numberOfRows = in[i].signalGainCorrectionUncertaintyDbi.size();
+        out[i].signalGainCorrectionUncertaintyDbi.resize(numberOfRows);
+        for (uint32_t j = 0; j < numberOfRows; j++) {
+            numberOfColumns = in[i].signalGainCorrectionUncertaintyDbi[j].size();
+            out[i].signalGainCorrectionUncertaintyDbi[j].row.resize(numberOfColumns);
+            for (uint32_t k = 0; k < numberOfColumns; k++) {
+                out[i].signalGainCorrectionUncertaintyDbi[j].row[k] =
+                        in[i].signalGainCorrectionUncertaintyDbi[j][k];
+            }
+        }
+    }
+}
+
+GnssAntennaInfo::GnssAntennaInfo(Gnss* gnss) : mGnss(gnss) {
+    mGnssAntennaInfoDeathRecipient = new GnssAntennaInfoDeathRecipient(this);
+    spGnssAntennaInfo = this;
+}
+
+GnssAntennaInfo::~GnssAntennaInfo() {
+    spGnssAntennaInfo = nullptr;
+}
+
+// Methods from ::android::hardware::gnss::V2_1::IGnssAntennaInfo follow.
+Return<GnssAntennaInfo::GnssAntennaInfoStatus>
+        GnssAntennaInfo::setCallback(const sp<IGnssAntennaInfoCallback>& callback)  {
+    uint32_t retValue;
+    if (mGnss == nullptr) {
+        LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+        return GnssAntennaInfoStatus::ERROR_GENERIC;
+    }
+
+    mGnssAntennaInfoCbIface = callback;
+    retValue = mGnss->getGnssInterface()->antennaInfoInit(aiGnssAntennaInfoCb);
+
+    switch (retValue) {
+    case ANTENNA_INFO_SUCCESS: return GnssAntennaInfoStatus::SUCCESS;
+    case ANTENNA_INFO_ERROR_ALREADY_INIT: return GnssAntennaInfoStatus::ERROR_ALREADY_INIT;
+    case ANTENNA_INFO_ERROR_GENERIC:
+    default: return GnssAntennaInfoStatus::ERROR_GENERIC;
+    }
+}
+
+Return<void> GnssAntennaInfo::close(void)  {
+    if (mGnss == nullptr) {
+        LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+        return Void();
+    }
+
+    mGnss->getGnssInterface()->antennaInfoClose();
+
+    return Void();
+}
+
+void GnssAntennaInfo::aiGnssAntennaInfoCb
+        (std::vector<GnssAntennaInformation> gnssAntennaInformations) {
+    if (nullptr != spGnssAntennaInfo) {
+        spGnssAntennaInfo->gnssAntennaInfoCb(gnssAntennaInformations);
+    }
+}
+
+void GnssAntennaInfo::gnssAntennaInfoCb
+        (std::vector<GnssAntennaInformation> gnssAntennaInformations) {
+
+    if (mGnssAntennaInfoCbIface != nullptr) {
+        hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo> antennaInfos;
+
+        // Convert from one structure to another
+        convertGnssAntennaInfo(gnssAntennaInformations, antennaInfos);
+
+        auto r = mGnssAntennaInfoCbIface->gnssAntennaInfoCb(antennaInfos);
+        if (!r.isOk()) {
+            LOC_LOGw("Error antenna info cb %s", r.description().c_str());
+        }
+    } else {
+        LOC_LOGw("setCallback has not been called yet");
+    }
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/android/2.1/GnssAntennaInfo.h b/android/2.1/GnssAntennaInfo.h
new file mode 100644
index 0000000..02ddd28
--- /dev/null
+++ b/android/2.1/GnssAntennaInfo.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_1_GNSSANTENNAINFO_H
+#define ANDROID_HARDWARE_GNSS_V2_1_GNSSANTENNAINFO_H
+
+#include <android/hardware/gnss/2.1/IGnssAntennaInfo.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_1::IGnssAntennaInfo;
+using ::android::hardware::gnss::V2_1::IGnssAntennaInfoCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+struct GnssAntennaInfo : public IGnssAntennaInfo {
+    GnssAntennaInfo(Gnss* gnss);
+    ~GnssAntennaInfo();
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_1::IGnssAntennaInfo follow.
+     * These declarations were generated from IGnssAntennaInfo.hal.
+     */
+    Return<GnssAntennaInfoStatus>
+            setCallback(const sp<IGnssAntennaInfoCallback>& callback) override;
+    Return<void> close(void) override;
+
+    void gnssAntennaInfoCb(std::vector<GnssAntennaInformation> gnssAntennaInformations);
+
+    static void aiGnssAntennaInfoCb(std::vector<GnssAntennaInformation> gnssAntennaInformations);
+
+ private:
+    struct GnssAntennaInfoDeathRecipient : hidl_death_recipient {
+        GnssAntennaInfoDeathRecipient(sp<GnssAntennaInfo> gnssAntennaInfo) :
+                mGnssAntennaInfo(gnssAntennaInfo) {
+        }
+        ~GnssAntennaInfoDeathRecipient() = default;
+        virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+        sp<GnssAntennaInfo> mGnssAntennaInfo;
+    };
+
+ private:
+    sp<GnssAntennaInfoDeathRecipient> mGnssAntennaInfoDeathRecipient = nullptr;
+    sp<IGnssAntennaInfoCallback> mGnssAntennaInfoCbIface = nullptr;
+    Gnss* mGnss = nullptr;
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GNSS_V2_1_GNSSANTENNAINFO_H
diff --git a/android/2.1/GnssBatching.cpp b/android/2.1/GnssBatching.cpp
new file mode 100644
index 0000000..73e3532
--- /dev/null
+++ b/android/2.1/GnssBatching.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssBatchingInterface"
+
+#include <log_util.h>
+#include <BatchingAPIClient.h>
+#include "GnssBatching.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+void GnssBatching::GnssBatchingDeathRecipient::serviceDied(
+        uint64_t cookie, const wp<IBase>& who) {
+    LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+            __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+    if (mGnssBatching != nullptr) {
+        mGnssBatching->stop();
+        mGnssBatching->cleanup();
+    }
+}
+
+GnssBatching::GnssBatching() : mApi(nullptr) {
+    mGnssBatchingDeathRecipient = new GnssBatchingDeathRecipient(this);
+}
+
+GnssBatching::~GnssBatching() {
+    if (mApi != nullptr) {
+        mApi->destroy();
+        mApi = nullptr;
+    }
+}
+
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+Return<bool> GnssBatching::init(const sp<V1_0::IGnssBatchingCallback>& callback) {
+    if (mApi != nullptr) {
+        LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__);
+        mApi->destroy();
+        mApi = nullptr;
+    }
+
+    mApi = new BatchingAPIClient(callback);
+    if (mApi == nullptr) {
+        LOC_LOGE("%s]: failed to create mApi", __FUNCTION__);
+        return false;
+    }
+
+    if (mGnssBatchingCbIface != nullptr) {
+        mGnssBatchingCbIface->unlinkToDeath(mGnssBatchingDeathRecipient);
+    }
+    mGnssBatchingCbIface = callback;
+    if (mGnssBatchingCbIface != nullptr) {
+        mGnssBatchingCbIface->linkToDeath(mGnssBatchingDeathRecipient, 0 /*cookie*/);
+    }
+
+    return true;
+}
+
+Return<uint16_t> GnssBatching::getBatchSize() {
+    uint16_t ret = 0;
+    if (mApi == nullptr) {
+        LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+    } else {
+        ret = mApi->getBatchSize();
+    }
+    return ret;
+}
+
+Return<bool> GnssBatching::start(const IGnssBatching::Options& options) {
+    bool ret = false;
+    if (mApi == nullptr) {
+        LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+    } else {
+        ret = mApi->startSession(options);
+    }
+    return ret;
+}
+
+Return<void> GnssBatching::flush() {
+    if (mApi == nullptr) {
+        LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+    } else {
+        mApi->flushBatchedLocations();
+    }
+    return Void();
+}
+
+Return<bool> GnssBatching::stop() {
+    bool ret = false;
+    if (mApi == nullptr) {
+        LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+    } else {
+        ret = mApi->stopSession();
+    }
+    return ret;
+}
+
+Return<void> GnssBatching::cleanup() {
+    if (mApi != nullptr) {
+        mApi->stopSession();
+    }
+    if (mGnssBatchingCbIface != nullptr) {
+        mGnssBatchingCbIface->unlinkToDeath(mGnssBatchingDeathRecipient);
+        mGnssBatchingCbIface = nullptr;
+    }
+    if (mGnssBatchingCbIface_2_0 != nullptr) {
+        mGnssBatchingCbIface_2_0->unlinkToDeath(mGnssBatchingDeathRecipient);
+        mGnssBatchingCbIface_2_0 = nullptr;
+    }
+    return Void();
+}
+
+// Methods from ::android::hardware::gnss::V2_0::IGnssBatching follow.
+Return<bool> GnssBatching::init_2_0(const sp<V2_0::IGnssBatchingCallback>& callback) {
+    if (mApi != nullptr) {
+        LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__);
+        mApi->destroy();
+        mApi = nullptr;
+    }
+
+    mApi = new BatchingAPIClient(callback);
+    if (mApi == nullptr) {
+        LOC_LOGE("%s]: failed to create mApi", __FUNCTION__);
+        return false;
+    }
+
+    if (mGnssBatchingCbIface_2_0 != nullptr) {
+        mGnssBatchingCbIface_2_0->unlinkToDeath(mGnssBatchingDeathRecipient);
+    }
+    mGnssBatchingCbIface_2_0 = callback;
+    if (mGnssBatchingCbIface_2_0 != nullptr) {
+        mGnssBatchingCbIface_2_0->linkToDeath(mGnssBatchingDeathRecipient, 0 /*cookie*/);
+    }
+
+    return true;
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/android/2.1/GnssBatching.h b/android/2.1/GnssBatching.h
new file mode 100644
index 0000000..908748f
--- /dev/null
+++ b/android/2.1/GnssBatching.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSBATCHING_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSBATCHING_H
+
+#include <android/hardware/gnss/2.0/IGnssBatching.h>
+#include <hidl/Status.h>
+
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_0::IGnssBatching;
+using ::android::hardware::gnss::V2_0::IGnssBatchingCallback;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+class BatchingAPIClient;
+struct GnssBatching : public IGnssBatching {
+    GnssBatching();
+    ~GnssBatching();
+
+    // Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+    Return<bool> init(const sp<V1_0::IGnssBatchingCallback>& callback) override;
+    Return<uint16_t> getBatchSize() override;
+    Return<bool> start(const IGnssBatching::Options& options ) override;
+    Return<void> flush() override;
+    Return<bool> stop() override;
+    Return<void> cleanup() override;
+
+    // Methods from ::android::hardware::gnss::V2_0::IGnssBatching follow.
+    Return<bool> init_2_0(const sp<V2_0::IGnssBatchingCallback>& callback) override;
+
+ private:
+    struct GnssBatchingDeathRecipient : hidl_death_recipient {
+        GnssBatchingDeathRecipient(sp<GnssBatching> gnssBatching) :
+            mGnssBatching(gnssBatching) {
+        }
+        ~GnssBatchingDeathRecipient() = default;
+        virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+        sp<GnssBatching> mGnssBatching;
+    };
+
+ private:
+    sp<GnssBatchingDeathRecipient> mGnssBatchingDeathRecipient = nullptr;
+    sp<V1_0::IGnssBatchingCallback> mGnssBatchingCbIface = nullptr;
+    BatchingAPIClient* mApi = nullptr;
+    sp<V2_0::IGnssBatchingCallback> mGnssBatchingCbIface_2_0 = nullptr;
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GNSS_V2_0_GNSSBATCHING_H
diff --git a/android/2.1/GnssConfiguration.cpp b/android/2.1/GnssConfiguration.cpp
new file mode 100644
index 0000000..b6077ae
--- /dev/null
+++ b/android/2.1/GnssConfiguration.cpp
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2_0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2_0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssConfigurationInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssConfiguration.h"
+#include "ContextBase.h"
+#include <android/hardware/gnss/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_0::GnssConstellationType;
+using namespace loc_core;
+
+GnssConfiguration::GnssConfiguration(Gnss* gnss) : mGnss(gnss) {
+}
+
+// Methods from ::android::hardware::gps::V1_0::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setSuplEs(bool enabled)  {
+    // deprecated function. Must return false to pass VTS
+    return false;
+}
+
+Return<bool> GnssConfiguration::setSuplVersion(uint32_t version)  {
+    if (mGnss == nullptr) {
+        LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+        return false;
+    }
+
+    GnssConfig config;
+    memset(&config, 0, sizeof(GnssConfig));
+    config.size = sizeof(GnssConfig);
+    config.flags = GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT;
+    switch (version) {
+        case 0x00020004:
+            config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_4;
+            break;
+        case 0x00020002:
+            config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_2;
+            break;
+        case 0x00020000:
+            config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_0;
+            break;
+        case 0x00010000:
+            config.suplVersion = GNSS_CONFIG_SUPL_VERSION_1_0_0;
+            break;
+        default:
+            LOC_LOGE("%s]: invalid version: 0x%x.", __FUNCTION__, version);
+            return false;
+    }
+
+    return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setSuplMode(uint8_t mode)  {
+    if (mGnss == nullptr) {
+        LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+        return false;
+    }
+
+    GnssConfig config;
+    memset(&config, 0, sizeof(GnssConfig));
+    config.size = sizeof(GnssConfig);
+    config.flags = GNSS_CONFIG_FLAGS_SUPL_MODE_BIT;
+    switch (mode) {
+        case 0:
+            config.suplModeMask = 0; // STANDALONE ONLY
+            break;
+        case 1:
+            config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSB_BIT;
+            break;
+        case 2:
+            config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSA_BIT;
+            break;
+        case 3:
+            config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSB_BIT | GNSS_CONFIG_SUPL_MODE_MSA_BIT;
+            break;
+        default:
+            LOC_LOGE("%s]: invalid mode: %d.", __FUNCTION__, mode);
+            return false;
+    }
+
+    return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setLppProfile(uint8_t lppProfileMask) {
+    if (mGnss == nullptr) {
+        LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+        return false;
+    }
+
+    GnssConfig config = {};
+    config.size = sizeof(GnssConfig);
+    config.flags = GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
+    config.lppProfileMask = GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE; //default
+
+    if (lppProfileMask & (1<<0)) {
+        config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_BIT;
+    }
+    if (lppProfileMask & (1<<1)) {
+        config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_BIT;
+    }
+    if (lppProfileMask & (1<<2)) {
+        config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_OVER_NR5G_SA_BIT;
+    }
+    if (lppProfileMask & (1<<3)) {
+        config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_OVER_NR5G_SA_BIT;
+    }
+
+    return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setGlonassPositioningProtocol(uint8_t protocol) {
+    if (mGnss == nullptr) {
+        LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+        return false;
+    }
+
+    GnssConfig config;
+    memset(&config, 0, sizeof(GnssConfig));
+    config.size = sizeof(GnssConfig);
+
+    config.flags = GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT;
+    if (protocol & (1<<0)) {
+        config.aGlonassPositionProtocolMask |= GNSS_CONFIG_RRC_CONTROL_PLANE_BIT;
+    }
+    if (protocol & (1<<1)) {
+        config.aGlonassPositionProtocolMask |= GNSS_CONFIG_RRLP_USER_PLANE_BIT;
+    }
+    if (protocol & (1<<2)) {
+        config.aGlonassPositionProtocolMask |= GNSS_CONFIG_LLP_USER_PLANE_BIT;
+    }
+    if (protocol & (1<<3)) {
+        config.aGlonassPositionProtocolMask |= GNSS_CONFIG_LLP_CONTROL_PLANE_BIT;
+    }
+
+    return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setGpsLock(uint8_t lock) {
+
+    if (mGnss == nullptr) {
+        LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+        return false;
+    }
+
+    GnssConfig config = {};
+    config.size = sizeof(GnssConfig);
+    config.flags = GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT;
+    switch (lock) {
+    case 0:
+        config.gpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
+        break;
+    case 1:
+        config.gpsLock = GNSS_CONFIG_GPS_LOCK_MO;
+        break;
+    case 2:
+        config.gpsLock = GNSS_CONFIG_GPS_LOCK_NI;
+        break;
+    case 3:
+        config.gpsLock = GNSS_CONFIG_GPS_LOCK_MO_AND_NI;
+        break;
+    default:
+        LOC_LOGE("%s]: invalid lock: %d.", __FUNCTION__, lock);
+        return false;
+    }
+
+    mGnss->updateConfiguration(config);
+    // Must return false to pass VTS
+    return false;
+}
+
+Return<bool> GnssConfiguration::setEmergencySuplPdn(bool enabled) {
+    if (mGnss == nullptr) {
+        LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+        return false;
+    }
+
+    GnssConfig config;
+    memset(&config, 0, sizeof(GnssConfig));
+    config.size = sizeof(GnssConfig);
+    config.flags = GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT;
+    config.emergencyPdnForEmergencySupl = (enabled ?
+            GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES :
+            GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO);
+
+    return mGnss->updateConfiguration(config);
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setBlacklist(
+            const hidl_vec<V1_1::IGnssConfiguration::BlacklistedSource>& blacklist) {
+
+    ENTRY_LOG_CALLFLOW();
+    if (nullptr == mGnss) {
+        LOC_LOGe("mGnss is null");
+        return false;
+    }
+
+    // blValid is true if blacklist is empty, i.e. clearing the BL;
+    // if blacklist is not empty, blValid is initialied to false, and later
+    // updated in the for loop to become true only if there is at least
+    // one {constellation, svid} in the list that is valid.
+    bool blValid = (0 == blacklist.size());
+    GnssConfig config;
+    memset(&config, 0, sizeof(GnssConfig));
+    config.size = sizeof(GnssConfig);
+    config.flags = GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
+    config.blacklistedSvIds.clear();
+
+    GnssSvIdSource source = {};
+    for (int idx = 0; idx < (int)blacklist.size(); idx++) {
+        // Set blValid true if any one source is valid
+        blValid = setBlacklistedSource(source, (GnssConstellationType)blacklist[idx].constellation,
+                blacklist[idx].svid) || blValid;
+        config.blacklistedSvIds.push_back(source);
+    }
+
+    // Update configuration only if blValid is true
+    // i.e. only if atleast one source is valid for blacklisting
+    return (blValid && mGnss->updateConfiguration(config));
+}
+
+bool GnssConfiguration::setBlacklistedSource(
+            GnssSvIdSource& copyToSource, const GnssConstellationType& constellation,
+            const int16_t svid) {
+
+    bool retVal = true;
+    uint16_t svIdOffset = 0;
+    copyToSource.size = sizeof(GnssSvIdSource);
+    copyToSource.svId = svid;
+
+    switch(constellation) {
+    case GnssConstellationType::GPS:
+        copyToSource.constellation = GNSS_SV_TYPE_GPS;
+        LOC_LOGe("GPS SVs can't be blacklisted.");
+        retVal = false;
+        break;
+    case GnssConstellationType::SBAS:
+        copyToSource.constellation = GNSS_SV_TYPE_SBAS;
+        LOC_LOGe("SBAS SVs can't be blacklisted.");
+        retVal = false;
+        break;
+    case GnssConstellationType::GLONASS:
+        copyToSource.constellation = GNSS_SV_TYPE_GLONASS;
+        svIdOffset = GNSS_SV_CONFIG_GLO_INITIAL_SV_ID - 1;
+        break;
+    case GnssConstellationType::QZSS:
+        copyToSource.constellation = GNSS_SV_TYPE_QZSS;
+        svIdOffset = 0;
+        break;
+    case GnssConstellationType::BEIDOU:
+        copyToSource.constellation = GNSS_SV_TYPE_BEIDOU;
+        svIdOffset = GNSS_SV_CONFIG_BDS_INITIAL_SV_ID - 1;
+        break;
+    case GnssConstellationType::GALILEO:
+        copyToSource.constellation = GNSS_SV_TYPE_GALILEO;
+        svIdOffset = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID - 1;
+        break;
+    case GnssConstellationType::IRNSS:
+        copyToSource.constellation = GNSS_SV_TYPE_NAVIC;
+        svIdOffset = 0;
+        break;
+    default:
+        copyToSource.constellation = GNSS_SV_TYPE_UNKNOWN;
+        LOC_LOGe("Invalid constellation %hhu", constellation);
+        retVal = false;
+        break;
+    }
+
+    if (copyToSource.svId > 0 && svIdOffset > 0) {
+        copyToSource.svId += svIdOffset;
+    }
+
+    return retVal;
+}
+
+bool GnssConfiguration::setBlacklistedSource(
+        GnssSvIdSource& copyToSource,
+        const GnssConfiguration::BlacklistedSource& copyFromSource) {
+
+    bool retVal = true;
+    uint16_t svIdOffset = 0;
+    copyToSource.size = sizeof(GnssSvIdSource);
+    copyToSource.svId = copyFromSource.svid;
+
+    switch(copyFromSource.constellation) {
+    case GnssConstellationType::GPS:
+        copyToSource.constellation = GNSS_SV_TYPE_GPS;
+        LOC_LOGe("GPS SVs can't be blacklisted.");
+        retVal = false;
+        break;
+    case GnssConstellationType::SBAS:
+        copyToSource.constellation = GNSS_SV_TYPE_SBAS;
+        LOC_LOGe("SBAS SVs can't be blacklisted.");
+        retVal = false;
+        break;
+    case GnssConstellationType::GLONASS:
+        copyToSource.constellation = GNSS_SV_TYPE_GLONASS;
+        svIdOffset = GNSS_SV_CONFIG_GLO_INITIAL_SV_ID - 1;
+        break;
+    case GnssConstellationType::QZSS:
+        copyToSource.constellation = GNSS_SV_TYPE_QZSS;
+        svIdOffset = GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID - 1;
+        break;
+    case GnssConstellationType::BEIDOU:
+        copyToSource.constellation = GNSS_SV_TYPE_BEIDOU;
+        svIdOffset = GNSS_SV_CONFIG_BDS_INITIAL_SV_ID - 1;
+        break;
+    case GnssConstellationType::GALILEO:
+        copyToSource.constellation = GNSS_SV_TYPE_GALILEO;
+        svIdOffset = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID - 1;
+        break;
+    case GnssConstellationType::IRNSS:
+        copyToSource.constellation = GNSS_SV_TYPE_NAVIC;
+        svIdOffset = GNSS_SV_CONFIG_NAVIC_INITIAL_SV_ID - 1;
+        break;
+    default:
+        copyToSource.constellation = GNSS_SV_TYPE_UNKNOWN;
+        LOC_LOGe("Invalid constellation %hhu", copyFromSource.constellation);
+        retVal = false;
+        break;
+    }
+
+    if (copyToSource.svId > 0 && svIdOffset > 0) {
+        copyToSource.svId += svIdOffset;
+    }
+
+    return retVal;
+}
+
+// Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setEsExtensionSec(uint32_t emergencyExtensionSeconds) {
+    ENTRY_LOG_CALLFLOW();
+    if (mGnss == nullptr) {
+        LOC_LOGe("mGnss is nullptr");
+        return false;
+    }
+
+    GnssConfig config;
+    memset(&config, 0, sizeof(GnssConfig));
+    config.size = sizeof(GnssConfig);
+    config.flags = GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT;
+    config.emergencyExtensionSeconds = emergencyExtensionSeconds;
+
+    return mGnss->updateConfiguration(config);
+}
+
+// Methods from ::android::hardware::gnss::V2_1::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setBlacklist_2_1(
+        const hidl_vec<V2_1::IGnssConfiguration::BlacklistedSource>& blacklist) {
+    ENTRY_LOG_CALLFLOW();
+    if (nullptr == mGnss) {
+        LOC_LOGe("mGnss is null");
+        return false;
+    }
+
+    // blValid is true if blacklist is empty, i.e. clearing the BL;
+    // if blacklist is not empty, blValid is initialied to false, and later
+    // updated in the for loop to become true only if there is at least
+    // one {constellation, svid} in the list that is valid.
+    bool blValid = (0 == blacklist.size());
+    GnssConfig config;
+    memset(&config, 0, sizeof(GnssConfig));
+    config.size = sizeof(GnssConfig);
+    config.flags = GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
+    config.blacklistedSvIds.clear();
+
+    GnssSvIdSource source = {};
+    for (int idx = 0; idx < (int)blacklist.size(); idx++) {
+        // Set blValid true if any one source is valid
+        blValid = setBlacklistedSource(source, blacklist[idx]) || blValid;
+        config.blacklistedSvIds.push_back(source);
+    }
+
+    // Update configuration only if blValid is true
+    // i.e. only if atleast one source is valid for blacklisting
+    return (blValid && mGnss->updateConfiguration(config));
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/android/2.1/GnssConfiguration.h b/android/2.1/GnssConfiguration.h
new file mode 100644
index 0000000..f000dbd
--- /dev/null
+++ b/android/2.1/GnssConfiguration.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+
+ /* Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2_0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2_0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H
+#define ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H
+
+#include <android/hardware/gnss/2.1/IGnssConfiguration.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::hardware::gnss::V2_0::GnssConstellationType;
+using ::android::sp;
+
+/*
+ * Interface for passing GNSS configuration info from platform to HAL.
+ */
+struct Gnss;
+struct GnssConfiguration : public V2_1::IGnssConfiguration {
+    GnssConfiguration(Gnss* gnss);
+    ~GnssConfiguration() = default;
+
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow.
+     * These declarations were generated from IGnssConfiguration.hal.
+     */
+    Return<bool> setSuplVersion(uint32_t version) override;
+    Return<bool> setSuplMode(uint8_t mode) override;
+    Return<bool> setSuplEs(bool enabled) override;
+    Return<bool> setLppProfile(uint8_t lppProfileMask) override;
+    Return<bool> setGlonassPositioningProtocol(uint8_t protocol) override;
+    Return<bool> setEmergencySuplPdn(bool enable) override;
+    Return<bool> setGpsLock(uint8_t lock) override;
+
+    // Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
+    Return<bool> setBlacklist(
+            const hidl_vec<V1_1::IGnssConfiguration::BlacklistedSource>& blacklist) override;
+
+    // Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow.
+    Return<bool> setEsExtensionSec(uint32_t emergencyExtensionSeconds) override;
+    // Methods from ::android::hardware::gnss::V2_1::IGnssConfiguration follow.
+    Return<bool> setBlacklist_2_1(
+            const hidl_vec<V2_1::IGnssConfiguration::BlacklistedSource>& blacklist) override;
+
+ private:
+    Gnss* mGnss = nullptr;
+    bool setBlacklistedSource(
+            GnssSvIdSource& copyToSource,
+            const GnssConfiguration::BlacklistedSource& copyFromSource);
+    bool setBlacklistedSource(
+            GnssSvIdSource& copyToSource, const GnssConstellationType& constellation,
+            const int16_t svid);
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H
diff --git a/android/2.1/GnssDebug.cpp b/android/2.1/GnssDebug.cpp
new file mode 100644
index 0000000..27ff964
--- /dev/null
+++ b/android/2.1/GnssDebug.cpp
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssDebugInterface"
+
+#include <log/log.h>
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssDebug.h"
+#include "LocationUtil.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::gnss::V2_0::IGnssDebug;
+
+#define GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS (20000000)
+#define GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS   (20000)
+#define GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC     (500)
+#define GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG       (180)
+
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME            (1483228800000LL) // 1/1/2017 00:00 GMT
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MIN    (999) // 999 ns
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX    (1.57783680E17) // 5 years in ns
+#define GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC (2.0e5)  // ppm
+
+GnssDebug::GnssDebug(Gnss* gnss) : mGnss(gnss)
+{
+}
+
+/*
+ * This methods requests position, time and satellite ephemeris debug information
+ * from the HAL.
+ *
+ * @return void
+*/
+Return<void> GnssDebug::getDebugData(getDebugData_cb _hidl_cb)
+{
+    LOC_LOGD("%s]: ", __func__);
+
+    V1_0::IGnssDebug::DebugData data = { };
+
+    if((nullptr == mGnss) || (nullptr == mGnss->getGnssInterface())){
+        LOC_LOGE("GnssDebug - Null GNSS interface");
+        _hidl_cb(data);
+        return Void();
+    }
+
+    // get debug report snapshot via hal interface
+    GnssDebugReport reports = { };
+    mGnss->getGnssInterface()->getDebugReport(reports);
+
+    // location block
+    if (reports.mLocation.mValid) {
+        data.position.valid = true;
+        data.position.latitudeDegrees = reports.mLocation.mLocation.latitude;
+        data.position.longitudeDegrees = reports.mLocation.mLocation.longitude;
+        data.position.altitudeMeters = reports.mLocation.mLocation.altitude;
+
+        data.position.speedMetersPerSec =
+            (double)(reports.mLocation.mLocation.speed);
+        data.position.bearingDegrees =
+            (double)(reports.mLocation.mLocation.bearing);
+        data.position.horizontalAccuracyMeters =
+            (double)(reports.mLocation.mLocation.accuracy);
+        data.position.verticalAccuracyMeters =
+            reports.mLocation.verticalAccuracyMeters;
+        data.position.speedAccuracyMetersPerSecond =
+            reports.mLocation.speedAccuracyMetersPerSecond;
+        data.position.bearingAccuracyDegrees =
+            reports.mLocation.bearingAccuracyDegrees;
+
+        timeval tv_now, tv_report;
+        tv_report.tv_sec  = reports.mLocation.mUtcReported.tv_sec;
+        tv_report.tv_usec = reports.mLocation.mUtcReported.tv_nsec / 1000ULL;
+        gettimeofday(&tv_now, NULL);
+        data.position.ageSeconds =
+            (tv_now.tv_sec - tv_report.tv_sec) +
+            (float)((tv_now.tv_usec - tv_report.tv_usec)) / 1000000;
+    }
+    else {
+        data.position.valid = false;
+    }
+
+    if (data.position.horizontalAccuracyMeters <= 0 ||
+        data.position.horizontalAccuracyMeters > GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS) {
+        data.position.horizontalAccuracyMeters = GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS;
+    }
+    if (data.position.verticalAccuracyMeters <= 0 ||
+        data.position.verticalAccuracyMeters > GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS) {
+        data.position.verticalAccuracyMeters = GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS;
+    }
+    if (data.position.speedAccuracyMetersPerSecond <= 0 ||
+        data.position.speedAccuracyMetersPerSecond > GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC) {
+        data.position.speedAccuracyMetersPerSecond = GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC;
+    }
+    if (data.position.bearingAccuracyDegrees <= 0 ||
+        data.position.bearingAccuracyDegrees > GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG) {
+        data.position.bearingAccuracyDegrees = GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG;
+    }
+
+    // time block
+    if (reports.mTime.mValid) {
+        data.time.timeEstimate = reports.mTime.timeEstimate;
+        data.time.timeUncertaintyNs = reports.mTime.timeUncertaintyNs;
+        data.time.frequencyUncertaintyNsPerSec =
+            reports.mTime.frequencyUncertaintyNsPerSec;
+    }
+
+    if (data.time.timeEstimate < GNSS_DEBUG_UNKNOWN_UTC_TIME) {
+        data.time.timeEstimate = GNSS_DEBUG_UNKNOWN_UTC_TIME;
+    }
+    if (data.time.timeUncertaintyNs <= 0) {
+        data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MIN;
+    } else if (data.time.timeUncertaintyNs > GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX) {
+        data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX;
+    }
+    if (data.time.frequencyUncertaintyNsPerSec <= 0 ||
+        data.time.frequencyUncertaintyNsPerSec > (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC) {
+        data.time.frequencyUncertaintyNsPerSec = (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC;
+    }
+
+    // satellite data block
+    V1_0::IGnssDebug::SatelliteData s = { };
+    std::vector<V1_0::IGnssDebug::SatelliteData> s_array;
+
+    for (uint32_t i=0; i<reports.mSatelliteInfo.size(); i++) {
+        memset(&s, 0, sizeof(s));
+        s.svid = reports.mSatelliteInfo[i].svid;
+        convertGnssConstellationType(
+            reports.mSatelliteInfo[i].constellation, s.constellation);
+        convertGnssEphemerisType(
+            reports.mSatelliteInfo[i].mEphemerisType, s.ephemerisType);
+        convertGnssEphemerisSource(
+            reports.mSatelliteInfo[i].mEphemerisSource, s.ephemerisSource);
+        convertGnssEphemerisHealth(
+            reports.mSatelliteInfo[i].mEphemerisHealth, s.ephemerisHealth);
+
+        s.ephemerisAgeSeconds =
+            reports.mSatelliteInfo[i].ephemerisAgeSeconds;
+        s.serverPredictionIsAvailable =
+            reports.mSatelliteInfo[i].serverPredictionIsAvailable;
+        s.serverPredictionAgeSeconds =
+            reports.mSatelliteInfo[i].serverPredictionAgeSeconds;
+
+        s_array.push_back(s);
+    }
+    data.satelliteDataArray = s_array;
+
+    // callback HIDL with collected debug data
+    _hidl_cb(data);
+    return Void();
+}
+
+Return<void> GnssDebug::getDebugData_2_0(getDebugData_2_0_cb _hidl_cb)
+{
+    LOC_LOGD("%s]: ", __func__);
+
+    V2_0::IGnssDebug::DebugData data = { };
+
+    if((nullptr == mGnss) || (nullptr == mGnss->getGnssInterface())){
+        LOC_LOGE("GnssDebug - Null GNSS interface");
+        _hidl_cb(data);
+        return Void();
+    }
+
+    // get debug report snapshot via hal interface
+    GnssDebugReport reports = { };
+    mGnss->getGnssInterface()->getDebugReport(reports);
+
+    // location block
+    if (reports.mLocation.mValid) {
+        data.position.valid = true;
+        data.position.latitudeDegrees = reports.mLocation.mLocation.latitude;
+        data.position.longitudeDegrees = reports.mLocation.mLocation.longitude;
+        data.position.altitudeMeters = reports.mLocation.mLocation.altitude;
+
+        data.position.speedMetersPerSec =
+            (double)(reports.mLocation.mLocation.speed);
+        data.position.bearingDegrees =
+            (double)(reports.mLocation.mLocation.bearing);
+        data.position.horizontalAccuracyMeters =
+            (double)(reports.mLocation.mLocation.accuracy);
+        data.position.verticalAccuracyMeters =
+            reports.mLocation.verticalAccuracyMeters;
+        data.position.speedAccuracyMetersPerSecond =
+            reports.mLocation.speedAccuracyMetersPerSecond;
+        data.position.bearingAccuracyDegrees =
+            reports.mLocation.bearingAccuracyDegrees;
+
+        timeval tv_now, tv_report;
+        tv_report.tv_sec  = reports.mLocation.mUtcReported.tv_sec;
+        tv_report.tv_usec = reports.mLocation.mUtcReported.tv_nsec / 1000ULL;
+        gettimeofday(&tv_now, NULL);
+        data.position.ageSeconds =
+            (tv_now.tv_sec - tv_report.tv_sec) +
+            (float)((tv_now.tv_usec - tv_report.tv_usec)) / 1000000;
+    }
+    else {
+        data.position.valid = false;
+    }
+
+    if (data.position.horizontalAccuracyMeters <= 0 ||
+        data.position.horizontalAccuracyMeters > GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS) {
+        data.position.horizontalAccuracyMeters = GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS;
+    }
+    if (data.position.verticalAccuracyMeters <= 0 ||
+        data.position.verticalAccuracyMeters > GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS) {
+        data.position.verticalAccuracyMeters = GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS;
+    }
+    if (data.position.speedAccuracyMetersPerSecond <= 0 ||
+        data.position.speedAccuracyMetersPerSecond > GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC) {
+        data.position.speedAccuracyMetersPerSecond = GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC;
+    }
+    if (data.position.bearingAccuracyDegrees <= 0 ||
+        data.position.bearingAccuracyDegrees > GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG) {
+        data.position.bearingAccuracyDegrees = GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG;
+    }
+
+    // time block
+    if (reports.mTime.mValid) {
+        data.time.timeEstimate = reports.mTime.timeEstimate;
+        data.time.timeUncertaintyNs = reports.mTime.timeUncertaintyNs;
+        data.time.frequencyUncertaintyNsPerSec =
+            reports.mTime.frequencyUncertaintyNsPerSec;
+    }
+
+    if (data.time.timeEstimate < GNSS_DEBUG_UNKNOWN_UTC_TIME) {
+        data.time.timeEstimate = GNSS_DEBUG_UNKNOWN_UTC_TIME;
+    }
+    if (data.time.timeUncertaintyNs <= 0) {
+        data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MIN;
+    }
+    else if (data.time.timeUncertaintyNs > GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX) {
+        data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX;
+    }
+    if (data.time.frequencyUncertaintyNsPerSec <= 0 ||
+        data.time.frequencyUncertaintyNsPerSec > (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC) {
+        data.time.frequencyUncertaintyNsPerSec = (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC;
+    }
+
+    // satellite data block
+    V2_0::IGnssDebug::SatelliteData s = { };
+    std::vector<V2_0::IGnssDebug::SatelliteData> s_array;
+
+    for (uint32_t i=0; i<reports.mSatelliteInfo.size(); i++) {
+        memset(&s, 0, sizeof(s));
+        s.v1_0.svid = reports.mSatelliteInfo[i].svid;
+        convertGnssConstellationType(
+            reports.mSatelliteInfo[i].constellation, s.constellation);
+        convertGnssEphemerisType(
+            reports.mSatelliteInfo[i].mEphemerisType, s.v1_0.ephemerisType);
+        convertGnssEphemerisSource(
+            reports.mSatelliteInfo[i].mEphemerisSource, s.v1_0.ephemerisSource);
+        convertGnssEphemerisHealth(
+            reports.mSatelliteInfo[i].mEphemerisHealth, s.v1_0.ephemerisHealth);
+
+        s.v1_0.ephemerisAgeSeconds =
+            reports.mSatelliteInfo[i].ephemerisAgeSeconds;
+        s.v1_0.serverPredictionIsAvailable =
+            reports.mSatelliteInfo[i].serverPredictionIsAvailable;
+        s.v1_0.serverPredictionAgeSeconds =
+            reports.mSatelliteInfo[i].serverPredictionAgeSeconds;
+
+        s_array.push_back(s);
+    }
+    data.satelliteDataArray = s_array;
+
+    // callback HIDL with collected debug data
+    _hidl_cb(data);
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/android/2.1/GnssDebug.h b/android/2.1/GnssDebug.h
new file mode 100644
index 0000000..4eaf34a
--- /dev/null
+++ b/android/2.1/GnssDebug.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSDEBUG_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSDEBUG_H
+
+
+#include <android/hardware/gnss/2.0/IGnssDebug.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_0::IGnssDebug;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/* Interface for GNSS Debug support. */
+struct Gnss;
+struct GnssDebug : public IGnssDebug {
+    GnssDebug(Gnss* gnss);
+    ~GnssDebug() {};
+
+    //  Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow
+    Return<void> getDebugData(getDebugData_cb _hidl_cb) override;
+    //  Methods from ::android::hardware::gnss::V2_0::IGnssDebug follow.
+    Return<void> getDebugData_2_0(getDebugData_2_0_cb _hidl_cb) override;
+
+private:
+    Gnss* mGnss = nullptr;
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GNSS_V2_0_GNSSDEBUG_H
diff --git a/android/2.1/GnssGeofencing.cpp b/android/2.1/GnssGeofencing.cpp
new file mode 100644
index 0000000..0ca3e6d
--- /dev/null
+++ b/android/2.1/GnssGeofencing.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHal_GnssGeofencing"
+
+#include <log_util.h>
+#include <GeofenceAPIClient.h>
+#include "GnssGeofencing.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+void GnssGeofencing::GnssGeofencingDeathRecipient::serviceDied(
+        uint64_t cookie, const wp<IBase>& who) {
+    LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+            __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+    if (mGnssGeofencing != nullptr) {
+        mGnssGeofencing->removeAllGeofences();
+    }
+}
+
+GnssGeofencing::GnssGeofencing() : mApi(nullptr) {
+    mGnssGeofencingDeathRecipient = new GnssGeofencingDeathRecipient(this);
+}
+
+GnssGeofencing::~GnssGeofencing() {
+    if (mApi != nullptr) {
+        mApi->destroy();
+        mApi = nullptr;
+    }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+Return<void> GnssGeofencing::setCallback(const sp<IGnssGeofenceCallback>& callback)  {
+    if (mApi != nullptr) {
+        LOC_LOGd("mApi is NOT nullptr");
+        return Void();
+    }
+
+    mApi = new GeofenceAPIClient(callback);
+    if (mApi == nullptr) {
+        LOC_LOGE("%s]: failed to create mApi", __FUNCTION__);
+    }
+
+    if (mGnssGeofencingCbIface != nullptr) {
+        mGnssGeofencingCbIface->unlinkToDeath(mGnssGeofencingDeathRecipient);
+    }
+    mGnssGeofencingCbIface = callback;
+    if (mGnssGeofencingCbIface != nullptr) {
+        mGnssGeofencingCbIface->linkToDeath(mGnssGeofencingDeathRecipient, 0 /*cookie*/);
+    }
+
+    return Void();
+}
+
+Return<void> GnssGeofencing::addGeofence(
+        int32_t geofenceId,
+        double latitudeDegrees,
+        double longitudeDegrees,
+        double radiusMeters,
+        IGnssGeofenceCallback::GeofenceTransition lastTransition,
+        int32_t monitorTransitions,
+        uint32_t notificationResponsivenessMs,
+        uint32_t unknownTimerMs)  {
+    if (mApi == nullptr) {
+        LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+    } else {
+        mApi->geofenceAdd(
+                geofenceId,
+                latitudeDegrees,
+                longitudeDegrees,
+                radiusMeters,
+                static_cast<int32_t>(lastTransition),
+                monitorTransitions,
+                notificationResponsivenessMs,
+                unknownTimerMs);
+    }
+    return Void();
+}
+
+Return<void> GnssGeofencing::pauseGeofence(int32_t geofenceId)  {
+    if (mApi == nullptr) {
+        LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+    } else {
+        mApi->geofencePause(geofenceId);
+    }
+    return Void();
+}
+
+Return<void> GnssGeofencing::resumeGeofence(int32_t geofenceId, int32_t monitorTransitions)  {
+    if (mApi == nullptr) {
+        LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+    } else {
+        mApi->geofenceResume(geofenceId, monitorTransitions);
+    }
+    return Void();
+}
+
+Return<void> GnssGeofencing::removeGeofence(int32_t geofenceId)  {
+    if (mApi == nullptr) {
+        LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+    } else {
+        mApi->geofenceRemove(geofenceId);
+    }
+    return Void();
+}
+
+Return<void> GnssGeofencing::removeAllGeofences()  {
+    if (mApi == nullptr) {
+        LOC_LOGD("%s]: mApi is nullptr, do nothing", __FUNCTION__);
+    } else {
+        mApi->geofenceRemoveAll();
+    }
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/android/2.1/GnssGeofencing.h b/android/2.1/GnssGeofencing.h
new file mode 100644
index 0000000..1cdca12
--- /dev/null
+++ b/android/2.1/GnssGeofencing.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSGEOFENCING_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSGEOFENCING_H
+
+#include <android/hardware/gnss/1.0/IGnssGeofencing.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback;
+using ::android::hardware::gnss::V1_0::IGnssGeofencing;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+class GeofenceAPIClient;
+struct GnssGeofencing : public IGnssGeofencing {
+    GnssGeofencing();
+    ~GnssGeofencing();
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+     * These declarations were generated from IGnssGeofencing.hal.
+     */
+    Return<void> setCallback(const sp<IGnssGeofenceCallback>& callback)  override;
+    Return<void> addGeofence(int32_t geofenceId,
+                             double latitudeDegrees,
+                             double longitudeDegrees,
+                             double radiusMeters,
+                             IGnssGeofenceCallback::GeofenceTransition lastTransition,
+                             int32_t monitorTransitions,
+                             uint32_t notificationResponsivenessMs,
+                             uint32_t unknownTimerMs)  override;
+
+    Return<void> pauseGeofence(int32_t geofenceId)  override;
+    Return<void> resumeGeofence(int32_t geofenceId, int32_t monitorTransitions)  override;
+    Return<void> removeGeofence(int32_t geofenceId)  override;
+
+ private:
+    // This method is not part of the IGnss base class.
+    // It is called by GnssGeofencingDeathRecipient to remove all geofences added so far.
+    Return<void> removeAllGeofences();
+
+ private:
+    struct GnssGeofencingDeathRecipient : hidl_death_recipient {
+        GnssGeofencingDeathRecipient(sp<GnssGeofencing> gnssGeofencing) :
+            mGnssGeofencing(gnssGeofencing) {
+        }
+        ~GnssGeofencingDeathRecipient() = default;
+        virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+        sp<GnssGeofencing> mGnssGeofencing;
+    };
+
+ private:
+    sp<GnssGeofencingDeathRecipient> mGnssGeofencingDeathRecipient = nullptr;
+    sp<IGnssGeofenceCallback> mGnssGeofencingCbIface = nullptr;
+    GeofenceAPIClient* mApi = nullptr;
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GNSS_V2_0_GNSSGEOFENCING_H
diff --git a/android/2.1/GnssMeasurement.cpp b/android/2.1/GnssMeasurement.cpp
new file mode 100644
index 0000000..af75802
--- /dev/null
+++ b/android/2.1/GnssMeasurement.cpp
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2_0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2_0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssMeasurementInterface"
+
+#include <log_util.h>
+#include "GnssMeasurement.h"
+#include "MeasurementAPIClient.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+void GnssMeasurement::GnssMeasurementDeathRecipient::serviceDied(
+        uint64_t cookie, const wp<IBase>& who) {
+    LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+            __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+    if (mGnssMeasurement != nullptr) {
+        mGnssMeasurement->close();
+    }
+}
+
+GnssMeasurement::GnssMeasurement() {
+    mGnssMeasurementDeathRecipient = new GnssMeasurementDeathRecipient(this);
+    mApi = new MeasurementAPIClient();
+}
+
+GnssMeasurement::~GnssMeasurement() {
+    if (mApi) {
+        mApi->destroy();
+        mApi = nullptr;
+    }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+Return<GnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback(
+        const sp<V1_0::IGnssMeasurementCallback>& callback)  {
+
+    Return<GnssMeasurement::GnssMeasurementStatus> ret =
+        IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+    if (mGnssMeasurementCbIface != nullptr) {
+        LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+        return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+    }
+
+    if (callback == nullptr) {
+        LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+        return ret;
+    }
+    if (mApi == nullptr) {
+        LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+        return ret;
+    }
+
+    clearInterfaces();
+
+    mGnssMeasurementCbIface = callback;
+    mGnssMeasurementCbIface->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+    return mApi->measurementSetCallback(callback);
+}
+
+void GnssMeasurement::clearInterfaces() {
+    if (mGnssMeasurementCbIface != nullptr) {
+        mGnssMeasurementCbIface->unlinkToDeath(mGnssMeasurementDeathRecipient);
+        mGnssMeasurementCbIface = nullptr;
+    }
+    if (mGnssMeasurementCbIface_1_1 != nullptr) {
+        mGnssMeasurementCbIface_1_1->unlinkToDeath(mGnssMeasurementDeathRecipient);
+        mGnssMeasurementCbIface_1_1 = nullptr;
+    }
+    if (mGnssMeasurementCbIface_2_0 != nullptr) {
+        mGnssMeasurementCbIface_2_0->unlinkToDeath(mGnssMeasurementDeathRecipient);
+        mGnssMeasurementCbIface_2_0 = nullptr;
+    }
+    if (mGnssMeasurementCbIface_2_1 != nullptr) {
+        mGnssMeasurementCbIface_2_1->unlinkToDeath(mGnssMeasurementDeathRecipient);
+        mGnssMeasurementCbIface_2_1 = nullptr;
+    }
+}
+
+Return<void> GnssMeasurement::close()  {
+    if (mApi == nullptr) {
+        LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+        return Void();
+    }
+
+    clearInterfaces();
+    mApi->measurementClose();
+
+    return Void();
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnssMeasurement follow.
+Return<GnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_1_1(
+        const sp<V1_1::IGnssMeasurementCallback>& callback, bool enableFullTracking) {
+
+    Return<GnssMeasurement::GnssMeasurementStatus> ret =
+        IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+    if (mGnssMeasurementCbIface_1_1 != nullptr) {
+        LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+        return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+    }
+
+    if (callback == nullptr) {
+        LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+        return ret;
+    }
+    if (nullptr == mApi) {
+        LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+        return ret;
+    }
+
+    clearInterfaces();
+
+    mGnssMeasurementCbIface_1_1 = callback;
+    mGnssMeasurementCbIface_1_1->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+    GnssPowerMode powerMode = enableFullTracking?
+            GNSS_POWER_MODE_M1 : GNSS_POWER_MODE_M2;
+
+    return mApi->measurementSetCallback_1_1(callback, powerMode);
+}
+// Methods from ::android::hardware::gnss::V2_0::IGnssMeasurement follow.
+Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_2_0(
+        const sp<V2_0::IGnssMeasurementCallback>& callback,
+        bool enableFullTracking) {
+
+    Return<GnssMeasurement::GnssMeasurementStatus> ret =
+        IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+    if (mGnssMeasurementCbIface_2_0 != nullptr) {
+        LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+        return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+    }
+
+    if (callback == nullptr) {
+        LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+        return ret;
+    }
+    if (nullptr == mApi) {
+        LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+        return ret;
+    }
+
+    clearInterfaces();
+
+    mGnssMeasurementCbIface_2_0 = callback;
+    mGnssMeasurementCbIface_2_0->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+    GnssPowerMode powerMode = enableFullTracking ?
+        GNSS_POWER_MODE_M1 : GNSS_POWER_MODE_M2;
+
+    return mApi->measurementSetCallback_2_0(callback, powerMode);
+}
+
+// Methods from ::android::hardware::gnss::V2_1::IGnssMeasurement follow.
+Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_2_1(
+        const sp<::android::hardware::gnss::V2_1::IGnssMeasurementCallback>& callback,
+        bool enableFullTracking) {
+    Return<GnssMeasurement::GnssMeasurementStatus> ret =
+        IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+    if (mGnssMeasurementCbIface_2_1 != nullptr) {
+        LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+        return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+    }
+
+    if (callback == nullptr) {
+        LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+        return ret;
+    }
+    if (nullptr == mApi) {
+        LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+        return ret;
+    }
+
+    clearInterfaces();
+
+    mGnssMeasurementCbIface_2_1 = callback;
+    mGnssMeasurementCbIface_2_1->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+    GnssPowerMode powerMode = enableFullTracking ?
+            GNSS_POWER_MODE_M1 : GNSS_POWER_MODE_M2;
+
+    return mApi->measurementSetCallback_2_1(callback, powerMode);
+
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/android/2.1/GnssMeasurement.h b/android/2.1/GnssMeasurement.h
new file mode 100644
index 0000000..2ac45c6
--- /dev/null
+++ b/android/2.1/GnssMeasurement.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2_0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2_0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_1_GNSSMEASUREMENT_H
+#define ANDROID_HARDWARE_GNSS_V2_1_GNSSMEASUREMENT_H
+
+#include <android/hardware/gnss/2.1/IGnssMeasurement.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+class MeasurementAPIClient;
+struct GnssMeasurement : public V2_1::IGnssMeasurement {
+    GnssMeasurement();
+    ~GnssMeasurement();
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+     * These declarations were generated from IGnssMeasurement.hal.
+     */
+    Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback(
+        const sp<V1_0::IGnssMeasurementCallback>& callback) override;
+    Return<void> close() override;
+
+    // Methods from ::android::hardware::gnss::V1_1::IGnssMeasurement follow.
+    Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback_1_1(
+            const sp<V1_1::IGnssMeasurementCallback>& callback,
+            bool enableFullTracking) override;
+
+    // Methods from ::android::hardware::gnss::V2_0::IGnssMeasurement follow.
+    Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback_2_0(
+            const sp<V2_0::IGnssMeasurementCallback>& callback,
+            bool enableFullTracking) override;
+    // Methods from ::android::hardware::gnss::V2_1::IGnssMeasurement follow.
+    Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback_2_1(
+            const sp<::android::hardware::gnss::V2_1::IGnssMeasurementCallback>& callback,
+            bool enableFullTracking) override;
+
+ private:
+    struct GnssMeasurementDeathRecipient : hidl_death_recipient {
+        GnssMeasurementDeathRecipient(sp<GnssMeasurement> gnssMeasurement) :
+            mGnssMeasurement(gnssMeasurement) {
+        }
+        ~GnssMeasurementDeathRecipient() = default;
+        virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+        sp<GnssMeasurement> mGnssMeasurement;
+    };
+
+ private:
+    sp<GnssMeasurementDeathRecipient> mGnssMeasurementDeathRecipient = nullptr;
+    sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface = nullptr;
+    sp<V1_1::IGnssMeasurementCallback> mGnssMeasurementCbIface_1_1 = nullptr;
+    sp<V2_0::IGnssMeasurementCallback> mGnssMeasurementCbIface_2_0 = nullptr;
+    sp<V2_1::IGnssMeasurementCallback> mGnssMeasurementCbIface_2_1 = nullptr;
+    MeasurementAPIClient* mApi;
+    void clearInterfaces();
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GNSS_V2_1_GNSSMEASUREMENT_H
diff --git a/android/2.1/GnssNi.cpp b/android/2.1/GnssNi.cpp
new file mode 100644
index 0000000..ba5e8d9
--- /dev/null
+++ b/android/2.1/GnssNi.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssNiInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssNi.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+void GnssNi::GnssNiDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) {
+    LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+            __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+    // we do nothing here
+    // Gnss::GnssDeathRecipient will stop the session
+}
+
+GnssNi::GnssNi(Gnss* gnss) : mGnss(gnss) {
+    mGnssNiDeathRecipient = new GnssNiDeathRecipient(this);
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+Return<void> GnssNi::setCallback(const sp<IGnssNiCallback>& callback)  {
+    if (mGnss == nullptr) {
+        LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+        return Void();
+    }
+
+    mGnss->setGnssNiCb(callback);
+
+    if (mGnssNiCbIface != nullptr) {
+        mGnssNiCbIface->unlinkToDeath(mGnssNiDeathRecipient);
+    }
+    mGnssNiCbIface = callback;
+    if (mGnssNiCbIface != nullptr) {
+        mGnssNiCbIface->linkToDeath(mGnssNiDeathRecipient, 0 /*cookie*/);
+    }
+
+    return Void();
+}
+
+Return<void> GnssNi::respond(int32_t notifId, IGnssNiCallback::GnssUserResponseType userResponse)  {
+    if (mGnss == nullptr) {
+        LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+        return Void();
+    }
+
+    GnssAPIClient* api = mGnss->getApi();
+    if (api == nullptr) {
+        LOC_LOGE("%s]: api is nullptr", __FUNCTION__);
+        return Void();
+    }
+
+    api->gnssNiRespond(notifId, userResponse);
+
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/android/2.1/GnssNi.h b/android/2.1/GnssNi.h
new file mode 100644
index 0000000..9a8fb69
--- /dev/null
+++ b/android/2.1/GnssNi.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSNI_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSNI_H
+
+#include <android/hardware/gnss/1.0/IGnssNi.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssNi;
+using ::android::hardware::gnss::V1_0::IGnssNiCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+struct GnssNi : public IGnssNi {
+    GnssNi(Gnss* gnss);
+    ~GnssNi() = default;
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+     * These declarations were generated from IGnssNi.hal.
+     */
+    Return<void> setCallback(const sp<IGnssNiCallback>& callback) override;
+    Return<void> respond(int32_t notifId,
+                         IGnssNiCallback::GnssUserResponseType userResponse) override;
+
+ private:
+    struct GnssNiDeathRecipient : hidl_death_recipient {
+        GnssNiDeathRecipient(sp<GnssNi> gnssNi) : mGnssNi(gnssNi) {
+        }
+        ~GnssNiDeathRecipient() = default;
+        virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+        sp<GnssNi> mGnssNi;
+    };
+
+ private:
+    sp<GnssNiDeathRecipient> mGnssNiDeathRecipient = nullptr;
+    sp<IGnssNiCallback> mGnssNiCbIface = nullptr;
+    Gnss* mGnss = nullptr;
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GNSS_V2_0_GNSSNI_H
diff --git a/android/visibility_control/1.0/GnssVisibilityControl.cpp b/android/2.1/GnssVisibilityControl.cpp
similarity index 100%
copy from android/visibility_control/1.0/GnssVisibilityControl.cpp
copy to android/2.1/GnssVisibilityControl.cpp
diff --git a/android/2.1/GnssVisibilityControl.h b/android/2.1/GnssVisibilityControl.h
new file mode 100644
index 0000000..6794a64
--- /dev/null
+++ b/android/2.1/GnssVisibilityControl.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_GnssVisibilityControl_H
+#define ANDROID_HARDWARE_GNSS_V1_0_GnssVisibilityControl_H
+
+#include <android/hardware/gnss/visibility_control/1.0/IGnssVisibilityControl.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <gps_extended_c.h>
+#include <location_interface.h>
+#include "Gnss.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace visibility_control {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::V2_1::implementation::Gnss;
+
+struct GnssVisibilityControl : public IGnssVisibilityControl {
+    GnssVisibilityControl(Gnss* gnss);
+    ~GnssVisibilityControl();
+
+    // Methods from ::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl follow.
+    Return<bool> enableNfwLocationAccess(const hidl_vec<::android::hardware::hidl_string>& proxyApps) override;
+    /**
+     * Registers the callback for HAL implementation to use.
+     *
+     * @param callback Handle to IGnssVisibilityControlCallback interface.
+     */
+    Return<bool> setCallback(const ::android::sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControlCallback>& callback) override;
+
+    void statusCb(GnssNfwNotification notification);
+    bool isE911Session();
+
+    /* Data call setup callback passed down to GNSS HAL implementation */
+    static void nfwStatusCb(GnssNfwNotification notification);
+    static bool isInEmergencySession();
+
+private:
+    Gnss* mGnss = nullptr;
+    sp<IGnssVisibilityControlCallback> mGnssVisibilityControlCbIface = nullptr;
+};
+
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace visibility_control
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GNSS_V1_0_GnssVisibilityControl_H
diff --git a/android/2.1/MeasurementCorrections.cpp b/android/2.1/MeasurementCorrections.cpp
new file mode 100644
index 0000000..5159f2f
--- /dev/null
+++ b/android/2.1/MeasurementCorrections.cpp
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_TAG "LocSvc_MeasurementCorrectionsInterface"
+
+#include <log_util.h>
+#include "MeasurementCorrections.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace measurement_corrections {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback;
+using ::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
+using MeasurementCorrectionsV1_0 =
+        ::android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections;
+using MeasurementCorrectionsV1_1 =
+        ::android::hardware::gnss::measurement_corrections::V1_1::MeasurementCorrections;
+
+static MeasurementCorrections* spMeasurementCorrections = nullptr;
+
+void MeasurementCorrections::GnssMeasurementCorrectionsDeathRecipient::serviceDied(uint64_t cookie,
+        const wp<IBase>& who) {
+    LOC_LOGe("service died. cookie: %llu, who: %p", static_cast<unsigned long long>(cookie), &who);
+    // Gnss::GnssDeathrecipient will stop the session
+    // we inform the adapter that service has died
+    if (nullptr == spMeasurementCorrections) {
+        LOC_LOGe("spMeasurementCorrections is nullptr");
+        return;
+    }
+    if (nullptr == spMeasurementCorrections->mGnss ||
+        nullptr == spMeasurementCorrections->mGnss->getGnssInterface()) {
+        LOC_LOGe("Null GNSS interface");
+        return;
+    }
+    spMeasurementCorrections->mGnss->getGnssInterface()->measCorrClose();
+}
+
+MeasurementCorrections::MeasurementCorrections(Gnss* gnss) : mGnss(gnss) {
+    mGnssMeasurementCorrectionsDeathRecipient = new GnssMeasurementCorrectionsDeathRecipient(this);
+    spMeasurementCorrections = this;
+}
+
+MeasurementCorrections::~MeasurementCorrections() {
+    spMeasurementCorrections = nullptr;
+}
+
+void MeasurementCorrections::measCorrSetCapabilitiesCb(
+        GnssMeasurementCorrectionsCapabilitiesMask capabilities) {
+    if (nullptr != spMeasurementCorrections) {
+        spMeasurementCorrections->setCapabilitiesCb(capabilities);
+    }
+}
+
+void MeasurementCorrections::setCapabilitiesCb(
+    GnssMeasurementCorrectionsCapabilitiesMask capabilities) {
+
+    std::unique_lock<std::mutex> lock(mMutex);
+    auto measCorrCbIface(mMeasurementCorrectionsCbIface);
+    lock.unlock();
+    if (measCorrCbIface != nullptr) {
+        uint32_t measCorrCapabilities = 0;
+
+        // Convert from one enum to another
+        if (capabilities & GNSS_MEAS_CORR_LOS_SATS) {
+            measCorrCapabilities |=
+                    IMeasurementCorrectionsCallback::Capabilities::LOS_SATS;
+        }
+        if (capabilities & GNSS_MEAS_CORR_EXCESS_PATH_LENGTH) {
+            measCorrCapabilities |=
+                    IMeasurementCorrectionsCallback::Capabilities::EXCESS_PATH_LENGTH;
+        }
+        if (capabilities & GNSS_MEAS_CORR_REFLECTING_PLANE) {
+            measCorrCapabilities |=
+                    IMeasurementCorrectionsCallback::Capabilities::REFLECTING_PLANE;
+        }
+
+        auto r = measCorrCbIface->setCapabilitiesCb(measCorrCapabilities);
+        if (!r.isOk()) {
+            LOC_LOGw("Error invoking setCapabilitiesCb %s", r.description().c_str());
+        }
+    } else {
+        LOC_LOGw("setCallback has not been called yet");
+    }
+}
+
+Return<bool> MeasurementCorrections::setCorrections(
+        const MeasurementCorrectionsV1_0& corrections) {
+
+    GnssMeasurementCorrections gnssMeasurementCorrections = {};
+
+    V2_1::implementation::convertMeasurementCorrections(corrections, gnssMeasurementCorrections);
+
+    return mGnss->getGnssInterface()->measCorrSetCorrections(gnssMeasurementCorrections);
+}
+
+Return<bool> MeasurementCorrections::setCorrections_1_1(
+        const MeasurementCorrectionsV1_1& corrections) {
+
+    GnssMeasurementCorrections gnssMeasurementCorrections = {};
+
+    V2_1::implementation::convertMeasurementCorrections(
+            corrections.v1_0, gnssMeasurementCorrections);
+
+    gnssMeasurementCorrections.hasEnvironmentBearing = corrections.hasEnvironmentBearing;
+    gnssMeasurementCorrections.environmentBearingDegrees =
+            corrections.environmentBearingDegrees;
+    gnssMeasurementCorrections.environmentBearingUncertaintyDegrees =
+            corrections.environmentBearingUncertaintyDegrees;
+
+    for (int i = 0; i < corrections.satCorrections.size(); i++) {
+        GnssSingleSatCorrection gnssSingleSatCorrection = {};
+
+        V2_1::implementation::convertSingleSatCorrections(
+                corrections.satCorrections[i].v1_0, gnssSingleSatCorrection);
+        switch (corrections.satCorrections[i].constellation) {
+        case (::android::hardware::gnss::V2_0::GnssConstellationType::GPS):
+            gnssSingleSatCorrection.svType = GNSS_SV_TYPE_GPS;
+            break;
+        case (::android::hardware::gnss::V2_0::GnssConstellationType::SBAS):
+            gnssSingleSatCorrection.svType = GNSS_SV_TYPE_SBAS;
+            break;
+        case (::android::hardware::gnss::V2_0::GnssConstellationType::GLONASS):
+            gnssSingleSatCorrection.svType = GNSS_SV_TYPE_GLONASS;
+            break;
+        case (::android::hardware::gnss::V2_0::GnssConstellationType::QZSS):
+            gnssSingleSatCorrection.svType = GNSS_SV_TYPE_QZSS;
+            break;
+        case (::android::hardware::gnss::V2_0::GnssConstellationType::BEIDOU):
+            gnssSingleSatCorrection.svType = GNSS_SV_TYPE_BEIDOU;
+            break;
+        case (::android::hardware::gnss::V2_0::GnssConstellationType::GALILEO):
+            gnssSingleSatCorrection.svType = GNSS_SV_TYPE_GALILEO;
+            break;
+        case (::android::hardware::gnss::V2_0::GnssConstellationType::IRNSS):
+            gnssSingleSatCorrection.svType = GNSS_SV_TYPE_NAVIC;
+            break;
+        case (::android::hardware::gnss::V2_0::GnssConstellationType::UNKNOWN):
+        default:
+            gnssSingleSatCorrection.svType = GNSS_SV_TYPE_UNKNOWN;
+            break;
+        }
+        gnssMeasurementCorrections.satCorrections.push_back(gnssSingleSatCorrection);
+    }
+
+    return mGnss->getGnssInterface()->measCorrSetCorrections(gnssMeasurementCorrections);
+}
+
+Return<bool> MeasurementCorrections::setCallback(
+        const sp<V1_0::IMeasurementCorrectionsCallback>& callback) {
+
+    if (nullptr == mGnss || nullptr == mGnss->getGnssInterface()) {
+        LOC_LOGe("Null GNSS interface");
+        return false;
+    }
+    std::unique_lock<std::mutex> lock(mMutex);
+    mMeasurementCorrectionsCbIface = callback;
+    lock.unlock();
+
+    return mGnss->getGnssInterface()->measCorrInit(measCorrSetCapabilitiesCb);
+}
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace measurement_corrections
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/android/2.1/MeasurementCorrections.h b/android/2.1/MeasurementCorrections.h
new file mode 100644
index 0000000..0247231
--- /dev/null
+++ b/android/2.1/MeasurementCorrections.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_1_MeasurementCorrections_H
+#define ANDROID_HARDWARE_GNSS_V1_1_MeasurementCorrections_H
+
+#include <android/hardware/gnss/measurement_corrections/1.1/IMeasurementCorrections.h>
+#include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrectionsCallback.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <gps_extended_c.h>
+#include <location_interface.h>
+#include "Gnss.h"
+#include <LocationUtil.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace measurement_corrections {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+using ::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback;
+using ::android::hardware::gnss::V2_1::implementation::Gnss;
+using MeasurementCorrectionsV1_0 =
+        ::android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections;
+using MeasurementCorrectionsV1_1 =
+        ::android::hardware::gnss::measurement_corrections::V1_1::MeasurementCorrections;
+
+struct MeasurementCorrections : public V1_1::IMeasurementCorrections {
+    MeasurementCorrections(Gnss* gnss);
+    ~MeasurementCorrections();
+
+    Return<bool> setCorrections(const MeasurementCorrectionsV1_0& corrections) override;
+
+    // Methods from
+    // ::android::hardware::gnss::measurement_corrections::V1_1::IMeasurementCorrections follow.
+    Return<bool> setCorrections_1_1(const MeasurementCorrectionsV1_1& corrections);
+
+    Return<bool> setCallback(const sp<IMeasurementCorrectionsCallback>& callback) override;
+
+    void setCapabilitiesCb(GnssMeasurementCorrectionsCapabilitiesMask capabilities);
+
+    /* Data call setup callback passed down to GNSS HAL implementation */
+    static void measCorrSetCapabilitiesCb(GnssMeasurementCorrectionsCapabilitiesMask capabilities);
+
+private:
+    mutable std::mutex mMutex;
+    struct GnssMeasurementCorrectionsDeathRecipient : hidl_death_recipient {
+        GnssMeasurementCorrectionsDeathRecipient(
+            sp<MeasurementCorrections> gnssMeasurementCorrections) :
+                    mGnssMeasurementCorrections(gnssMeasurementCorrections) {
+        }
+        ~GnssMeasurementCorrectionsDeathRecipient() = default;
+        virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+        sp<MeasurementCorrections> mGnssMeasurementCorrections;
+    };
+    Gnss* mGnss = nullptr;
+    sp<GnssMeasurementCorrectionsDeathRecipient> mGnssMeasurementCorrectionsDeathRecipient =
+            nullptr;
+    sp<IMeasurementCorrectionsCallback> mMeasurementCorrectionsCbIface = nullptr;
+};
+
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace measurement_corrections
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GNSS_V1_1_MeasurementCorrections_H
diff --git a/android/2.1/android.hardware.gnss@2.1-service-qti.rc b/android/2.1/android.hardware.gnss@2.1-service-qti.rc
new file mode 100644
index 0000000..71b43bc
--- /dev/null
+++ b/android/2.1/android.hardware.gnss@2.1-service-qti.rc
@@ -0,0 +1,4 @@
+service gnss_service /vendor/bin/hw/android.hardware.gnss@2.1-service-qti
+    class hal
+    user gps
+    group system gps radio
diff --git a/android/2.1/android.hardware.gnss@2.1-service-qti.xml b/android/2.1/android.hardware.gnss@2.1-service-qti.xml
new file mode 100755
index 0000000..842fb6e
--- /dev/null
+++ b/android/2.1/android.hardware.gnss@2.1-service-qti.xml
@@ -0,0 +1,36 @@
+<!-- Copyright (c) 2020, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.gnss</name>
+        <transport>hwbinder</transport>
+        <fqname>@1.1::IGnss/default</fqname>
+        <fqname>@2.1::IGnss/default</fqname>
+    </hal>
+</manifest>
+
diff --git a/android/2.1/location_api/BatchingAPIClient.cpp b/android/2.1/location_api/BatchingAPIClient.cpp
new file mode 100644
index 0000000..0c871b7
--- /dev/null
+++ b/android/2.1/location_api/BatchingAPIClient.cpp
@@ -0,0 +1,292 @@
+/* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation, nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_BatchingAPIClient"
+
+#include <inttypes.h>
+#include <log_util.h>
+#include <loc_cfg.h>
+#include <thread>
+#include "LocationUtil.h"
+#include "BatchingAPIClient.h"
+
+#include "limits.h"
+
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_0::IGnssBatching;
+using ::android::hardware::gnss::V2_0::IGnssBatchingCallback;
+using ::android::hardware::gnss::V2_0::GnssLocation;
+
+static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out,
+        LocationCapabilitiesMask mask);
+
+BatchingAPIClient::BatchingAPIClient(const sp<V1_0::IGnssBatchingCallback>& callback) :
+    LocationAPIClientBase(),
+    mGnssBatchingCbIface(nullptr),
+    mDefaultId(UINT_MAX),
+    mLocationCapabilitiesMask(0),
+    mGnssBatchingCbIface_2_0(nullptr)
+{
+    LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+    gnssUpdateCallbacks(callback);
+}
+
+BatchingAPIClient::BatchingAPIClient(const sp<V2_0::IGnssBatchingCallback>& callback) :
+    LocationAPIClientBase(),
+    mGnssBatchingCbIface(nullptr),
+    mDefaultId(UINT_MAX),
+    mLocationCapabilitiesMask(0),
+    mGnssBatchingCbIface_2_0(nullptr)
+{
+    LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+    gnssUpdateCallbacks_2_0(callback);
+}
+
+BatchingAPIClient::~BatchingAPIClient()
+{
+    LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+int BatchingAPIClient::getBatchSize() {
+    int batchSize = locAPIGetBatchSize();
+    LOC_LOGd("batchSize: %d", batchSize);
+    return batchSize;
+}
+
+void BatchingAPIClient::setCallbacks()
+{
+    LocationCallbacks locationCallbacks;
+    memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+    locationCallbacks.size = sizeof(LocationCallbacks);
+
+    locationCallbacks.trackingCb = nullptr;
+    locationCallbacks.batchingCb = nullptr;
+    locationCallbacks.batchingCb = [this](size_t count, Location* location,
+        BatchingOptions batchOptions) {
+        onBatchingCb(count, location, batchOptions);
+    };
+    locationCallbacks.geofenceBreachCb = nullptr;
+    locationCallbacks.geofenceStatusCb = nullptr;
+    locationCallbacks.gnssLocationInfoCb = nullptr;
+    locationCallbacks.gnssNiCb = nullptr;
+    locationCallbacks.gnssSvCb = nullptr;
+    locationCallbacks.gnssNmeaCb = nullptr;
+    locationCallbacks.gnssMeasurementsCb = nullptr;
+
+    locAPISetCallbacks(locationCallbacks);
+}
+
+void BatchingAPIClient::gnssUpdateCallbacks(const sp<V1_0::IGnssBatchingCallback>& callback)
+{
+    mMutex.lock();
+    mGnssBatchingCbIface = callback;
+    mMutex.unlock();
+
+    if (mGnssBatchingCbIface != nullptr) {
+        setCallbacks();
+    }
+}
+
+void BatchingAPIClient::gnssUpdateCallbacks_2_0(const sp<V2_0::IGnssBatchingCallback>& callback)
+{
+    mMutex.lock();
+    mGnssBatchingCbIface_2_0 = callback;
+    mMutex.unlock();
+
+    if (mGnssBatchingCbIface_2_0 != nullptr) {
+        setCallbacks();
+    }
+}
+
+int BatchingAPIClient::startSession(const IGnssBatching::Options& opts) {
+    mMutex.lock();
+    mState = STARTED;
+    mMutex.unlock();
+    LOC_LOGD("%s]: (%lld %d)", __FUNCTION__,
+            static_cast<long long>(opts.periodNanos), static_cast<uint8_t>(opts.flags));
+    int retVal = -1;
+    LocationOptions options;
+    convertBatchOption(opts, options, mLocationCapabilitiesMask);
+    uint32_t mode = 0;
+    if (opts.flags == static_cast<uint8_t>(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) {
+        mode = SESSION_MODE_ON_FULL;
+    }
+    if (locAPIStartSession(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) {
+        retVal = 1;
+    }
+    return retVal;
+}
+
+int BatchingAPIClient::updateSessionOptions(const IGnssBatching::Options& opts)
+{
+    LOC_LOGD("%s]: (%lld %d)", __FUNCTION__,
+            static_cast<long long>(opts.periodNanos), static_cast<uint8_t>(opts.flags));
+    int retVal = -1;
+    LocationOptions options;
+    convertBatchOption(opts, options, mLocationCapabilitiesMask);
+
+    uint32_t mode = 0;
+    if (opts.flags == static_cast<uint8_t>(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) {
+        mode = SESSION_MODE_ON_FULL;
+    }
+    if (locAPIUpdateSessionOptions(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) {
+        retVal = 1;
+    }
+    return retVal;
+}
+
+int BatchingAPIClient::stopSession() {
+    mMutex.lock();
+    mState = STOPPING;
+    mMutex.unlock();
+    LOC_LOGD("%s]: ", __FUNCTION__);
+    int retVal = -1;
+    locAPIGetBatchedLocations(mDefaultId, SIZE_MAX);
+    if (locAPIStopSession(mDefaultId) == LOCATION_ERROR_SUCCESS) {
+        retVal = 1;
+    }
+    return retVal;
+}
+
+void BatchingAPIClient::getBatchedLocation(int last_n_locations)
+{
+    LOC_LOGD("%s]: (%d)", __FUNCTION__, last_n_locations);
+    locAPIGetBatchedLocations(mDefaultId, last_n_locations);
+}
+
+void BatchingAPIClient::flushBatchedLocations() {
+    LOC_LOGD("%s]: ()", __FUNCTION__);
+    uint32_t retVal = locAPIGetBatchedLocations(mDefaultId, SIZE_MAX);
+    // when flush a stopped session or one doesn't exist, just report an empty batch.
+    if (LOCATION_ERROR_ID_UNKNOWN == retVal) {
+        BatchingOptions opt = {};
+        ::std::thread thd(&BatchingAPIClient::onBatchingCb, this, 0, nullptr, opt);
+        thd.detach();
+    }
+}
+
+void BatchingAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)
+{
+    LOC_LOGD("%s]: (%" PRIu64 ")", __FUNCTION__, capabilitiesMask);
+    mLocationCapabilitiesMask = capabilitiesMask;
+}
+
+void BatchingAPIClient::onBatchingCb(size_t count, Location* location,
+        BatchingOptions /*batchOptions*/) {
+    bool processReport = false;
+    LOC_LOGd("(count: %zu)", count);
+    mMutex.lock();
+    // back to back stop() and flush() could bring twice onBatchingCb(). Each one might come first.
+    // Combine them both (the first goes to cache, the second in location*) before report to FW
+    switch (mState) {
+        case STOPPING:
+            mState = STOPPED;
+            for (size_t i = 0; i < count; i++) {
+                mBatchedLocationInCache.push_back(location[i]);
+            }
+            break;
+        case STARTED:
+        case STOPPED: // flush() always trigger report, even on a stopped session
+            processReport = true;
+            break;
+        default:
+            break;
+    }
+    // report location batch when in STARTED state or flush(), combined with cache in last stop()
+    if (processReport) {
+        auto gnssBatchingCbIface(mGnssBatchingCbIface);
+        auto gnssBatchingCbIface_2_0(mGnssBatchingCbIface_2_0);
+        size_t batchCacheCnt = mBatchedLocationInCache.size();
+        LOC_LOGd("(batchCacheCnt: %zu)", batchCacheCnt);
+        if (gnssBatchingCbIface_2_0 != nullptr) {
+            hidl_vec<V2_0::GnssLocation> locationVec;
+            if (count+batchCacheCnt > 0) {
+                locationVec.resize(count+batchCacheCnt);
+                for (size_t i = 0; i < batchCacheCnt; ++i) {
+                    convertGnssLocation(mBatchedLocationInCache[i], locationVec[i]);
+                }
+                for (size_t i = 0; i < count; i++) {
+                    convertGnssLocation(location[i], locationVec[i+batchCacheCnt]);
+                }
+            }
+            auto r = gnssBatchingCbIface_2_0->gnssLocationBatchCb(locationVec);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssLocationBatchCb 2_0 description=%s",
+                        __func__, r.description().c_str());
+            }
+        } else if (gnssBatchingCbIface != nullptr) {
+            hidl_vec<V1_0::GnssLocation> locationVec;
+            if (count+batchCacheCnt > 0) {
+                locationVec.resize(count+batchCacheCnt);
+                for (size_t i = 0; i < batchCacheCnt; ++i) {
+                    convertGnssLocation(mBatchedLocationInCache[i], locationVec[i]);
+                }
+                for (size_t i = 0; i < count; i++) {
+                    convertGnssLocation(location[i], locationVec[i+batchCacheCnt]);
+                }
+            }
+            auto r = gnssBatchingCbIface->gnssLocationBatchCb(locationVec);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssLocationBatchCb 1.0 description=%s",
+                        __func__, r.description().c_str());
+            }
+        }
+        mBatchedLocationInCache.clear();
+    }
+    mMutex.unlock();
+}
+
+static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out,
+        LocationCapabilitiesMask mask)
+{
+    memset(&out, 0, sizeof(LocationOptions));
+    out.size = sizeof(LocationOptions);
+    out.minInterval = (uint32_t)(in.periodNanos / 1000000L);
+    out.minDistance = 0;
+    out.mode = GNSS_SUPL_MODE_STANDALONE;
+    if (mask & LOCATION_CAPABILITIES_GNSS_MSA_BIT)
+        out.mode = GNSS_SUPL_MODE_MSA;
+    if (mask & LOCATION_CAPABILITIES_GNSS_MSB_BIT)
+        out.mode = GNSS_SUPL_MODE_MSB;
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/android/2.1/location_api/BatchingAPIClient.h b/android/2.1/location_api/BatchingAPIClient.h
new file mode 100755
index 0000000..2d9ab74
--- /dev/null
+++ b/android/2.1/location_api/BatchingAPIClient.h
@@ -0,0 +1,88 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation, nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef BATCHING_API_CLINET_H
+#define BATCHING_API_CLINET_H
+
+#include <mutex>
+#include <android/hardware/gnss/2.0/IGnssBatching.h>
+#include <android/hardware/gnss/2.0/IGnssBatchingCallback.h>
+#include <pthread.h>
+
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+
+enum BATCHING_STATE { STARTED, STOPPING, STOPPED };
+
+class BatchingAPIClient : public LocationAPIClientBase
+{
+public:
+    BatchingAPIClient(const sp<V1_0::IGnssBatchingCallback>& callback);
+    BatchingAPIClient(const sp<V2_0::IGnssBatchingCallback>& callback);
+    void gnssUpdateCallbacks(const sp<V1_0::IGnssBatchingCallback>& callback);
+    void gnssUpdateCallbacks_2_0(const sp<V2_0::IGnssBatchingCallback>& callback);
+    int getBatchSize();
+    int startSession(const V1_0::IGnssBatching::Options& options);
+    int updateSessionOptions(const V1_0::IGnssBatching::Options& options);
+    int stopSession();
+    void getBatchedLocation(int last_n_locations);
+    void flushBatchedLocations();
+
+    inline LocationCapabilitiesMask getCapabilities() { return mLocationCapabilitiesMask; }
+
+    // callbacks
+    void onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) final;
+    void onBatchingCb(size_t count, Location* location, BatchingOptions batchOptions) final;
+
+private:
+    ~BatchingAPIClient();
+
+    void setCallbacks();
+    std::mutex mMutex;
+    sp<V1_0::IGnssBatchingCallback> mGnssBatchingCbIface;
+    uint32_t mDefaultId;
+    LocationCapabilitiesMask mLocationCapabilitiesMask;
+    sp<V2_0::IGnssBatchingCallback> mGnssBatchingCbIface_2_0;
+    volatile BATCHING_STATE mState = STOPPED;
+
+    std::vector<Location> mBatchedLocationInCache;
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+#endif // BATCHING_API_CLINET_H
diff --git a/android/2.1/location_api/GeofenceAPIClient.cpp b/android/2.1/location_api/GeofenceAPIClient.cpp
new file mode 100755
index 0000000..6e63465
--- /dev/null
+++ b/android/2.1/location_api/GeofenceAPIClient.cpp
@@ -0,0 +1,275 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation, nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_GeofenceApiClient"
+
+#include <log_util.h>
+#include <loc_cfg.h>
+
+#include "LocationUtil.h"
+#include "GeofenceAPIClient.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+
+GeofenceAPIClient::GeofenceAPIClient(const sp<IGnssGeofenceCallback>& callback) :
+    LocationAPIClientBase(),
+    mGnssGeofencingCbIface(callback)
+{
+    LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+    LocationCallbacks locationCallbacks;
+    memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+    locationCallbacks.size = sizeof(LocationCallbacks);
+
+    locationCallbacks.trackingCb = nullptr;
+    locationCallbacks.batchingCb = nullptr;
+
+    locationCallbacks.geofenceBreachCb = nullptr;
+    if (mGnssGeofencingCbIface != nullptr) {
+        locationCallbacks.geofenceBreachCb =
+            [this](GeofenceBreachNotification geofenceBreachNotification) {
+                onGeofenceBreachCb(geofenceBreachNotification);
+            };
+
+        locationCallbacks.geofenceStatusCb =
+            [this](GeofenceStatusNotification geofenceStatusNotification) {
+                onGeofenceStatusCb(geofenceStatusNotification);
+            };
+    }
+
+    locationCallbacks.gnssLocationInfoCb = nullptr;
+    locationCallbacks.gnssNiCb = nullptr;
+    locationCallbacks.gnssSvCb = nullptr;
+    locationCallbacks.gnssNmeaCb = nullptr;
+    locationCallbacks.gnssMeasurementsCb = nullptr;
+
+    locAPISetCallbacks(locationCallbacks);
+}
+
+void GeofenceAPIClient::geofenceAdd(uint32_t geofence_id, double latitude, double longitude,
+        double radius_meters, int32_t last_transition, int32_t monitor_transitions,
+        uint32_t notification_responsiveness_ms, uint32_t unknown_timer_ms)
+{
+    LOC_LOGD("%s]: (%d %f %f %f %d %d %d %d)", __FUNCTION__,
+            geofence_id, latitude, longitude, radius_meters,
+            last_transition, monitor_transitions, notification_responsiveness_ms, unknown_timer_ms);
+
+    GeofenceOption options;
+    memset(&options, 0, sizeof(GeofenceOption));
+    options.size = sizeof(GeofenceOption);
+    if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::ENTERED)
+        options.breachTypeMask |= GEOFENCE_BREACH_ENTER_BIT;
+    if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::EXITED)
+        options.breachTypeMask |=  GEOFENCE_BREACH_EXIT_BIT;
+    options.responsiveness = notification_responsiveness_ms;
+
+    GeofenceInfo data;
+    data.size = sizeof(GeofenceInfo);
+    data.latitude = latitude;
+    data.longitude = longitude;
+    data.radius = radius_meters;
+
+    LocationError err = (LocationError)locAPIAddGeofences(1, &geofence_id, &options, &data);
+    if (LOCATION_ERROR_SUCCESS != err) {
+        onAddGeofencesCb(1, &err, &geofence_id);
+    }
+}
+
+void GeofenceAPIClient::geofencePause(uint32_t geofence_id)
+{
+    LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id);
+    locAPIPauseGeofences(1, &geofence_id);
+}
+
+void GeofenceAPIClient::geofenceResume(uint32_t geofence_id, int32_t monitor_transitions)
+{
+    LOC_LOGD("%s]: (%d %d)", __FUNCTION__, geofence_id, monitor_transitions);
+    GeofenceBreachTypeMask mask = 0;
+    if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::ENTERED)
+        mask |= GEOFENCE_BREACH_ENTER_BIT;
+    if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::EXITED)
+        mask |=  GEOFENCE_BREACH_EXIT_BIT;
+    locAPIResumeGeofences(1, &geofence_id, &mask);
+}
+
+void GeofenceAPIClient::geofenceRemove(uint32_t geofence_id)
+{
+    LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id);
+    locAPIRemoveGeofences(1, &geofence_id);
+}
+
+void GeofenceAPIClient::geofenceRemoveAll()
+{
+    LOC_LOGD("%s]", __FUNCTION__);
+    // TODO locAPIRemoveAllGeofences();
+}
+
+// callbacks
+void GeofenceAPIClient::onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification)
+{
+    LOC_LOGD("%s]: (%d)", __FUNCTION__, geofenceBreachNotification.count);
+    if (mGnssGeofencingCbIface != nullptr) {
+        for (size_t i = 0; i < geofenceBreachNotification.count; i++) {
+            GnssLocation gnssLocation;
+            convertGnssLocation(geofenceBreachNotification.location, gnssLocation);
+
+            IGnssGeofenceCallback::GeofenceTransition transition;
+            if (geofenceBreachNotification.type == GEOFENCE_BREACH_ENTER)
+                transition = IGnssGeofenceCallback::GeofenceTransition::ENTERED;
+            else if (geofenceBreachNotification.type == GEOFENCE_BREACH_EXIT)
+                transition = IGnssGeofenceCallback::GeofenceTransition::EXITED;
+            else {
+                // continue with other breach if transition is
+                // nether GPS_GEOFENCE_ENTERED nor GPS_GEOFENCE_EXITED
+                continue;
+            }
+
+            auto r = mGnssGeofencingCbIface->gnssGeofenceTransitionCb(
+                    geofenceBreachNotification.ids[i], gnssLocation, transition,
+                    static_cast<V1_0::GnssUtcTime>(geofenceBreachNotification.timestamp));
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssGeofenceTransitionCb description=%s",
+                    __func__, r.description().c_str());
+            }
+        }
+    }
+}
+
+void GeofenceAPIClient::onGeofenceStatusCb(GeofenceStatusNotification geofenceStatusNotification)
+{
+    LOC_LOGD("%s]: (%d)", __FUNCTION__, geofenceStatusNotification.available);
+    if (mGnssGeofencingCbIface != nullptr) {
+        IGnssGeofenceCallback::GeofenceAvailability status =
+            IGnssGeofenceCallback::GeofenceAvailability::UNAVAILABLE;
+        if (geofenceStatusNotification.available == GEOFENCE_STATUS_AVAILABILE_YES) {
+            status = IGnssGeofenceCallback::GeofenceAvailability::AVAILABLE;
+        }
+        GnssLocation gnssLocation;
+        memset(&gnssLocation, 0, sizeof(GnssLocation));
+        auto r = mGnssGeofencingCbIface->gnssGeofenceStatusCb(status, gnssLocation);
+        if (!r.isOk()) {
+            LOC_LOGE("%s] Error from gnssGeofenceStatusCb description=%s",
+                __func__, r.description().c_str());
+        }
+    }
+}
+
+void GeofenceAPIClient::onAddGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
+{
+    LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
+    if (mGnssGeofencingCbIface != nullptr) {
+        for (size_t i = 0; i < count; i++) {
+            IGnssGeofenceCallback::GeofenceStatus status =
+                IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
+            if (errors[i] == LOCATION_ERROR_SUCCESS)
+                status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
+            else if (errors[i] == LOCATION_ERROR_ID_EXISTS)
+                status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_EXISTS;
+            auto r = mGnssGeofencingCbIface->gnssGeofenceAddCb(ids[i], status);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssGeofenceAddCb description=%s",
+                    __func__, r.description().c_str());
+            }
+        }
+    }
+}
+
+void GeofenceAPIClient::onRemoveGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
+{
+    LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
+    if (mGnssGeofencingCbIface != nullptr) {
+        for (size_t i = 0; i < count; i++) {
+            IGnssGeofenceCallback::GeofenceStatus status =
+                IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
+            if (errors[i] == LOCATION_ERROR_SUCCESS)
+                status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
+            else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN)
+                status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN;
+            auto r = mGnssGeofencingCbIface->gnssGeofenceRemoveCb(ids[i], status);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssGeofenceRemoveCb description=%s",
+                    __func__, r.description().c_str());
+            }
+        }
+    }
+}
+
+void GeofenceAPIClient::onPauseGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
+{
+    LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
+    if (mGnssGeofencingCbIface != nullptr) {
+        for (size_t i = 0; i < count; i++) {
+            IGnssGeofenceCallback::GeofenceStatus status =
+                IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
+            if (errors[i] == LOCATION_ERROR_SUCCESS)
+                status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
+            else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN)
+                status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN;
+            auto r = mGnssGeofencingCbIface->gnssGeofencePauseCb(ids[i], status);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssGeofencePauseCb description=%s",
+                    __func__, r.description().c_str());
+            }
+        }
+    }
+}
+
+void GeofenceAPIClient::onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
+{
+    LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
+    if (mGnssGeofencingCbIface != nullptr) {
+        for (size_t i = 0; i < count; i++) {
+            IGnssGeofenceCallback::GeofenceStatus status =
+                IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
+            if (errors[i] == LOCATION_ERROR_SUCCESS)
+                status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
+            else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN)
+                status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN;
+            auto r = mGnssGeofencingCbIface->gnssGeofenceResumeCb(ids[i], status);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssGeofenceResumeCb description=%s",
+                    __func__, r.description().c_str());
+            }
+        }
+    }
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/android/2.1/location_api/GeofenceAPIClient.h b/android/2.1/location_api/GeofenceAPIClient.h
new file mode 100755
index 0000000..9ed289f
--- /dev/null
+++ b/android/2.1/location_api/GeofenceAPIClient.h
@@ -0,0 +1,77 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation, nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GEOFENCE_API_CLINET_H
+#define GEOFENCE_API_CLINET_H
+
+
+#include <android/hardware/gnss/1.0/IGnssGeofenceCallback.h>
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::sp;
+
+class GeofenceAPIClient : public LocationAPIClientBase
+{
+public:
+    GeofenceAPIClient(const sp<V1_0::IGnssGeofenceCallback>& callback);
+
+    void geofenceAdd(uint32_t geofence_id, double latitude, double longitude,
+            double radius_meters, int32_t last_transition, int32_t monitor_transitions,
+            uint32_t notification_responsiveness_ms, uint32_t unknown_timer_ms);
+    void geofencePause(uint32_t geofence_id);
+    void geofenceResume(uint32_t geofence_id, int32_t monitor_transitions);
+    void geofenceRemove(uint32_t geofence_id);
+    void geofenceRemoveAll();
+
+    // callbacks
+    void onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification) final;
+    void onGeofenceStatusCb(GeofenceStatusNotification geofenceStatusNotification) final;
+    void onAddGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final;
+    void onRemoveGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final;
+    void onPauseGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final;
+    void onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final;
+
+private:
+    virtual ~GeofenceAPIClient() = default;
+
+    sp<V1_0::IGnssGeofenceCallback> mGnssGeofencingCbIface;
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+#endif // GEOFENCE_API_CLINET_H
diff --git a/android/2.1/location_api/GnssAPIClient.cpp b/android/2.1/location_api/GnssAPIClient.cpp
new file mode 100644
index 0000000..e1dc0d4
--- /dev/null
+++ b/android/2.1/location_api/GnssAPIClient.cpp
@@ -0,0 +1,864 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation, nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_GnssAPIClient"
+#define SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC (590 * 60 * 60 * 1000) // 590 hours
+
+#include <inttypes.h>
+#include <log_util.h>
+#include <loc_cfg.h>
+
+#include "LocationUtil.h"
+#include "GnssAPIClient.h"
+#include <LocContext.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_1::IGnss;
+using ::android::hardware::gnss::V2_1::IGnssCallback;
+using ::android::hardware::gnss::V1_0::IGnssNiCallback;
+using ::android::hardware::gnss::V2_0::GnssLocation;
+
+static void convertGnssSvStatus(GnssSvNotification& in, V1_0::IGnssCallback::GnssSvStatus& out);
+static void convertGnssSvStatus(GnssSvNotification& in,
+        hidl_vec<V2_0::IGnssCallback::GnssSvInfo>& out);
+static void convertGnssSvStatus(GnssSvNotification& in,
+        hidl_vec<V2_1::IGnssCallback::GnssSvInfo>& out);
+
+GnssAPIClient::GnssAPIClient(const sp<V1_0::IGnssCallback>& gpsCb,
+        const sp<V1_0::IGnssNiCallback>& niCb) :
+    LocationAPIClientBase(),
+    mGnssCbIface(nullptr),
+    mGnssNiCbIface(nullptr),
+    mControlClient(new LocationAPIControlClient()),
+    mLocationCapabilitiesMask(0),
+    mLocationCapabilitiesCached(false),
+    mTracking(false),
+    mGnssCbIface_2_0(nullptr)
+{
+    LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
+
+    initLocationOptions();
+    gnssUpdateCallbacks(gpsCb, niCb);
+}
+
+GnssAPIClient::GnssAPIClient(const sp<V2_0::IGnssCallback>& gpsCb) :
+    LocationAPIClientBase(),
+    mGnssCbIface(nullptr),
+    mGnssNiCbIface(nullptr),
+    mControlClient(new LocationAPIControlClient()),
+    mLocationCapabilitiesMask(0),
+    mLocationCapabilitiesCached(false),
+    mTracking(false),
+    mGnssCbIface_2_0(nullptr)
+{
+    LOC_LOGD("%s]: (%p)", __FUNCTION__, &gpsCb);
+
+    initLocationOptions();
+    gnssUpdateCallbacks_2_0(gpsCb);
+}
+
+GnssAPIClient::GnssAPIClient(const sp<V2_1::IGnssCallback>& gpsCb) :
+    LocationAPIClientBase(),
+    mGnssCbIface(nullptr),
+    mGnssNiCbIface(nullptr),
+    mControlClient(new LocationAPIControlClient()),
+    mLocationCapabilitiesMask(0),
+    mLocationCapabilitiesCached(false),
+    mTracking(false),
+    mGnssCbIface_2_1(nullptr)
+{
+    LOC_LOGD("%s]: (%p)", __FUNCTION__, &gpsCb);
+
+    initLocationOptions();
+    gnssUpdateCallbacks_2_1(gpsCb);
+}
+
+GnssAPIClient::~GnssAPIClient()
+{
+    LOC_LOGD("%s]: ()", __FUNCTION__);
+    if (mControlClient) {
+        delete mControlClient;
+        mControlClient = nullptr;
+    }
+}
+
+void GnssAPIClient::initLocationOptions()
+{
+    // set default LocationOptions.
+    memset(&mTrackingOptions, 0, sizeof(TrackingOptions));
+    mTrackingOptions.size = sizeof(TrackingOptions);
+    mTrackingOptions.minInterval = 1000;
+    mTrackingOptions.minDistance = 0;
+    mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE;
+}
+
+void GnssAPIClient::setCallbacks()
+{
+    LocationCallbacks locationCallbacks;
+    memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+    locationCallbacks.size = sizeof(LocationCallbacks);
+
+    locationCallbacks.trackingCb = nullptr;
+    locationCallbacks.trackingCb = [this](Location location) {
+        onTrackingCb(location);
+    };
+
+    locationCallbacks.batchingCb = nullptr;
+    locationCallbacks.geofenceBreachCb = nullptr;
+    locationCallbacks.geofenceStatusCb = nullptr;
+    locationCallbacks.gnssLocationInfoCb = nullptr;
+    locationCallbacks.gnssNiCb = nullptr;
+    if (mGnssNiCbIface != nullptr) {
+        loc_core::ContextBase* context =
+                loc_core::LocContext::getLocContext(loc_core::LocContext::mLocationHalName);
+        if (!context->hasAgpsExtendedCapabilities()) {
+            LOC_LOGD("Registering NI CB");
+            locationCallbacks.gnssNiCb = [this](uint32_t id, GnssNiNotification gnssNiNotify) {
+                onGnssNiCb(id, gnssNiNotify);
+            };
+        }
+    }
+
+    locationCallbacks.gnssSvCb = nullptr;
+    locationCallbacks.gnssSvCb = [this](GnssSvNotification gnssSvNotification) {
+        onGnssSvCb(gnssSvNotification);
+    };
+
+    locationCallbacks.gnssNmeaCb = nullptr;
+    locationCallbacks.gnssNmeaCb = [this](GnssNmeaNotification gnssNmeaNotification) {
+        onGnssNmeaCb(gnssNmeaNotification);
+    };
+
+    locationCallbacks.gnssMeasurementsCb = nullptr;
+
+    locAPISetCallbacks(locationCallbacks);
+}
+
+// for GpsInterface
+void GnssAPIClient::gnssUpdateCallbacks(const sp<V1_0::IGnssCallback>& gpsCb,
+    const sp<IGnssNiCallback>& niCb)
+{
+    LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
+
+    mMutex.lock();
+    mGnssCbIface = gpsCb;
+    mGnssNiCbIface = niCb;
+    mMutex.unlock();
+
+    if (mGnssCbIface != nullptr || mGnssNiCbIface != nullptr) {
+        setCallbacks();
+    }
+}
+
+void GnssAPIClient::gnssUpdateCallbacks_2_0(const sp<V2_0::IGnssCallback>& gpsCb)
+{
+    LOC_LOGD("%s]: (%p)", __FUNCTION__, &gpsCb);
+
+    mMutex.lock();
+    mGnssCbIface_2_0 = gpsCb;
+    mMutex.unlock();
+
+    if (mGnssCbIface_2_0 != nullptr) {
+        setCallbacks();
+    }
+}
+
+void GnssAPIClient::gnssUpdateCallbacks_2_1(const sp<V2_1::IGnssCallback>& gpsCb)
+{
+    LOC_LOGD("%s]: (%p)", __FUNCTION__, &gpsCb);
+
+    mMutex.lock();
+    mGnssCbIface_2_1 = gpsCb;
+    mMutex.unlock();
+
+    if (mGnssCbIface_2_1 != nullptr) {
+        setCallbacks();
+    }
+}
+
+bool GnssAPIClient::gnssStart()
+{
+    LOC_LOGD("%s]: ()", __FUNCTION__);
+
+    mMutex.lock();
+    mTracking = true;
+    mMutex.unlock();
+
+    bool retVal = true;
+    locAPIStartTracking(mTrackingOptions);
+    return retVal;
+}
+
+bool GnssAPIClient::gnssStop()
+{
+    LOC_LOGD("%s]: ()", __FUNCTION__);
+
+    mMutex.lock();
+    mTracking = false;
+    mMutex.unlock();
+
+    bool retVal = true;
+    locAPIStopTracking();
+    return retVal;
+}
+
+bool GnssAPIClient::gnssSetPositionMode(IGnss::GnssPositionMode mode,
+        IGnss::GnssPositionRecurrence recurrence, uint32_t minIntervalMs,
+        uint32_t preferredAccuracyMeters, uint32_t preferredTimeMs,
+        GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
+{
+    LOC_LOGD("%s]: (%d %d %d %d %d %d %d)", __FUNCTION__,
+            (int)mode, recurrence, minIntervalMs, preferredAccuracyMeters,
+            preferredTimeMs, (int)powerMode, timeBetweenMeasurement);
+    bool retVal = true;
+    memset(&mTrackingOptions, 0, sizeof(TrackingOptions));
+    mTrackingOptions.size = sizeof(TrackingOptions);
+    mTrackingOptions.minInterval = minIntervalMs;
+    if (IGnss::GnssPositionMode::MS_ASSISTED == mode ||
+            IGnss::GnssPositionRecurrence::RECURRENCE_SINGLE == recurrence) {
+        // We set a very large interval to simulate SINGLE mode. Once we report a fix,
+        // the caller should take the responsibility to stop the session.
+        // For MSA, we always treat it as SINGLE mode.
+        mTrackingOptions.minInterval = SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC;
+    }
+    if (mode == IGnss::GnssPositionMode::STANDALONE)
+        mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE;
+    else if (mode == IGnss::GnssPositionMode::MS_BASED)
+        mTrackingOptions.mode = GNSS_SUPL_MODE_MSB;
+    else if (mode ==  IGnss::GnssPositionMode::MS_ASSISTED)
+        mTrackingOptions.mode = GNSS_SUPL_MODE_MSA;
+    else {
+        LOC_LOGD("%s]: invalid GnssPositionMode: %d", __FUNCTION__, (int)mode);
+        retVal = false;
+    }
+    if (GNSS_POWER_MODE_INVALID != powerMode) {
+        mTrackingOptions.powerMode = powerMode;
+        mTrackingOptions.tbm = timeBetweenMeasurement;
+    }
+    locAPIUpdateTrackingOptions(mTrackingOptions);
+    return retVal;
+}
+
+// for GpsNiInterface
+void GnssAPIClient::gnssNiRespond(int32_t notifId,
+        IGnssNiCallback::GnssUserResponseType userResponse)
+{
+    LOC_LOGD("%s]: (%d %d)", __FUNCTION__, notifId, static_cast<int>(userResponse));
+    GnssNiResponse data;
+    switch (userResponse) {
+    case IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT:
+        data = GNSS_NI_RESPONSE_ACCEPT;
+        break;
+    case IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY:
+        data = GNSS_NI_RESPONSE_DENY;
+        break;
+    case IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP:
+        data = GNSS_NI_RESPONSE_NO_RESPONSE;
+        break;
+    default:
+        data = GNSS_NI_RESPONSE_IGNORE;
+        break;
+    }
+
+    locAPIGnssNiResponse(notifId, data);
+}
+
+// these apis using LocationAPIControlClient
+void GnssAPIClient::gnssDeleteAidingData(IGnss::GnssAidingData aidingDataFlags)
+{
+    LOC_LOGD("%s]: (%02hx)", __FUNCTION__, aidingDataFlags);
+    if (mControlClient == nullptr) {
+        return;
+    }
+    GnssAidingData data;
+    memset(&data, 0, sizeof (GnssAidingData));
+    data.sv.svTypeMask = GNSS_AIDING_DATA_SV_TYPE_GPS_BIT |
+        GNSS_AIDING_DATA_SV_TYPE_GLONASS_BIT |
+        GNSS_AIDING_DATA_SV_TYPE_QZSS_BIT |
+        GNSS_AIDING_DATA_SV_TYPE_BEIDOU_BIT |
+        GNSS_AIDING_DATA_SV_TYPE_GALILEO_BIT |
+        GNSS_AIDING_DATA_SV_TYPE_NAVIC_BIT;
+    data.posEngineMask = STANDARD_POSITIONING_ENGINE;
+
+    if (aidingDataFlags == IGnss::GnssAidingData::DELETE_ALL)
+        data.deleteAll = true;
+    else {
+        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_EPHEMERIS)
+            data.sv.svMask |= GNSS_AIDING_DATA_SV_EPHEMERIS_BIT;
+        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_ALMANAC)
+            data.sv.svMask |= GNSS_AIDING_DATA_SV_ALMANAC_BIT;
+        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_POSITION)
+            data.common.mask |= GNSS_AIDING_DATA_COMMON_POSITION_BIT;
+        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_TIME)
+            data.common.mask |= GNSS_AIDING_DATA_COMMON_TIME_BIT;
+        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_IONO)
+            data.sv.svMask |= GNSS_AIDING_DATA_SV_IONOSPHERE_BIT;
+        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_UTC)
+            data.common.mask |= GNSS_AIDING_DATA_COMMON_UTC_BIT;
+        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_HEALTH)
+            data.sv.svMask |= GNSS_AIDING_DATA_SV_HEALTH_BIT;
+        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVDIR)
+            data.sv.svMask |= GNSS_AIDING_DATA_SV_DIRECTION_BIT;
+        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVSTEER)
+            data.sv.svMask |= GNSS_AIDING_DATA_SV_STEER_BIT;
+        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SADATA)
+            data.sv.svMask |= GNSS_AIDING_DATA_SV_SA_DATA_BIT;
+        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_RTI)
+            data.common.mask |= GNSS_AIDING_DATA_COMMON_RTI_BIT;
+        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_CELLDB_INFO)
+            data.common.mask |= GNSS_AIDING_DATA_COMMON_CELLDB_BIT;
+    }
+    mControlClient->locAPIGnssDeleteAidingData(data);
+}
+
+void GnssAPIClient::gnssEnable(LocationTechnologyType techType)
+{
+    LOC_LOGD("%s]: (%0d)", __FUNCTION__, techType);
+    if (mControlClient == nullptr) {
+        return;
+    }
+    mControlClient->locAPIEnable(techType);
+}
+
+void GnssAPIClient::gnssDisable()
+{
+    LOC_LOGD("%s]: ()", __FUNCTION__);
+    if (mControlClient == nullptr) {
+        return;
+    }
+    mControlClient->locAPIDisable();
+}
+
+void GnssAPIClient::gnssConfigurationUpdate(const GnssConfig& gnssConfig)
+{
+    LOC_LOGD("%s]: (%02x)", __FUNCTION__, gnssConfig.flags);
+    if (mControlClient == nullptr) {
+        return;
+    }
+    mControlClient->locAPIGnssUpdateConfig(gnssConfig);
+}
+
+void GnssAPIClient::requestCapabilities() {
+    // only send capablities if it's already cached, otherwise the first time LocationAPI
+    // is initialized, capabilities will be sent by LocationAPI
+    if (mLocationCapabilitiesCached) {
+        onCapabilitiesCb(mLocationCapabilitiesMask);
+    }
+}
+
+// callbacks
+void GnssAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)
+{
+    LOC_LOGD("%s]: (%" PRIu64 ")", __FUNCTION__, capabilitiesMask);
+    mLocationCapabilitiesMask = capabilitiesMask;
+    mLocationCapabilitiesCached = true;
+
+    mMutex.lock();
+    auto gnssCbIface(mGnssCbIface);
+    auto gnssCbIface_2_0(mGnssCbIface_2_0);
+    auto gnssCbIface_2_1(mGnssCbIface_2_1);
+    mMutex.unlock();
+
+    if (gnssCbIface_2_1 != nullptr ||gnssCbIface_2_0 != nullptr || gnssCbIface != nullptr) {
+
+        uint32_t antennaInfoVectorSize = 0;
+        uint32_t data = 0;
+        loc_param_s_type ant_info_vector_table[] =
+        {
+            { "ANTENNA_INFO_VECTOR_SIZE", &antennaInfoVectorSize, NULL, 'n' }
+        };
+        UTIL_READ_CONF(LOC_PATH_ANT_CORR, ant_info_vector_table);
+
+        if (0 != antennaInfoVectorSize) {
+            data |= V2_1::IGnssCallback::Capabilities::ANTENNA_INFO;
+        }
+
+        if ((capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT) ||
+                (capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT) ||
+                (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT) ||
+                (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT))
+            data |= IGnssCallback::Capabilities::SCHEDULING;
+        if (capabilitiesMask & LOCATION_CAPABILITIES_GEOFENCE_BIT)
+            data |= V1_0::IGnssCallback::Capabilities::GEOFENCING;
+        if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT)
+            data |= V1_0::IGnssCallback::Capabilities::MEASUREMENTS;
+        if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSB_BIT)
+            data |= IGnssCallback::Capabilities::MSB;
+        if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSA_BIT)
+            data |= IGnssCallback::Capabilities::MSA;
+        if (capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT)
+            data |= IGnssCallback::Capabilities::LOW_POWER_MODE;
+        if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT)
+            data |= IGnssCallback::Capabilities::SATELLITE_BLACKLIST;
+        if (capabilitiesMask & LOCATION_CAPABILITIES_MEASUREMENTS_CORRECTION_BIT)
+            data |= V2_0::IGnssCallback::Capabilities::MEASUREMENT_CORRECTIONS;
+
+        IGnssCallback::GnssSystemInfo gnssInfo = { .yearOfHw = 2015 };
+
+        if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) {
+            gnssInfo.yearOfHw++; // 2016
+            if (capabilitiesMask & LOCATION_CAPABILITIES_DEBUG_NMEA_BIT) {
+                gnssInfo.yearOfHw++; // 2017
+                if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT ||
+                    capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT) {
+                    gnssInfo.yearOfHw++; // 2018
+                    if (capabilitiesMask & LOCATION_CAPABILITIES_PRIVACY_BIT) {
+                        gnssInfo.yearOfHw++; // 2019
+                        if (capabilitiesMask & LOCATION_CAPABILITIES_MEASUREMENTS_CORRECTION_BIT) {
+                            gnssInfo.yearOfHw++; // 2020
+                        }
+                    }
+                }
+            }
+        }
+        LOC_LOGV("%s:%d] set_system_info_cb (%d)", __FUNCTION__, __LINE__, gnssInfo.yearOfHw);
+
+        if (gnssCbIface_2_1 != nullptr) {
+            auto r = gnssCbIface_2_1->gnssSetCapabilitiesCb_2_1(data);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssSetCapabilitiesCb_2_1 description=%s",
+                    __func__, r.description().c_str());
+            }
+            r = gnssCbIface_2_1->gnssSetSystemInfoCb(gnssInfo);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssSetSystemInfoCb description=%s",
+                    __func__, r.description().c_str());
+            }
+        } else if (gnssCbIface_2_0 != nullptr) {
+            auto r = gnssCbIface_2_0->gnssSetCapabilitiesCb_2_0(data);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssSetCapabilitiesCb_2_0 description=%s",
+                    __func__, r.description().c_str());
+            }
+            r = gnssCbIface_2_0->gnssSetSystemInfoCb(gnssInfo);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssSetSystemInfoCb description=%s",
+                    __func__, r.description().c_str());
+            }
+        } else if (gnssCbIface != nullptr) {
+            auto r = gnssCbIface->gnssSetCapabilitesCb(data);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssSetCapabilitesCb description=%s",
+                    __func__, r.description().c_str());
+            }
+            r = gnssCbIface->gnssSetSystemInfoCb(gnssInfo);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssSetSystemInfoCb description=%s",
+                    __func__, r.description().c_str());
+            }
+        }
+
+    }
+
+}
+
+void GnssAPIClient::onTrackingCb(Location location)
+{
+    mMutex.lock();
+    auto gnssCbIface(mGnssCbIface);
+    auto gnssCbIface_2_0(mGnssCbIface_2_0);
+    auto gnssCbIface_2_1(mGnssCbIface_2_1);
+    bool isTracking = mTracking;
+    mMutex.unlock();
+
+    LOC_LOGD("%s]: (flags: %02x isTracking: %d)", __FUNCTION__, location.flags, isTracking);
+
+    if (!isTracking) {
+        return;
+    }
+
+    if (gnssCbIface_2_1 != nullptr) {
+        V2_0::GnssLocation gnssLocation;
+        convertGnssLocation(location, gnssLocation);
+        auto r = gnssCbIface_2_1->gnssLocationCb_2_0(gnssLocation);
+        if (!r.isOk()) {
+            LOC_LOGE("%s] Error from gnssLocationCb_2_0 description=%s",
+                __func__, r.description().c_str());
+        }
+    } else if (gnssCbIface_2_0 != nullptr) {
+        V2_0::GnssLocation gnssLocation;
+        convertGnssLocation(location, gnssLocation);
+        auto r = gnssCbIface_2_0->gnssLocationCb_2_0(gnssLocation);
+        if (!r.isOk()) {
+            LOC_LOGE("%s] Error from gnssLocationCb_2_0 description=%s",
+                __func__, r.description().c_str());
+        }
+    } else if (gnssCbIface != nullptr) {
+        V1_0::GnssLocation gnssLocation;
+        convertGnssLocation(location, gnssLocation);
+        auto r = gnssCbIface->gnssLocationCb(gnssLocation);
+        if (!r.isOk()) {
+            LOC_LOGE("%s] Error from gnssLocationCb description=%s",
+                __func__, r.description().c_str());
+        }
+    } else {
+        LOC_LOGW("%s] No GNSS Interface ready for gnssLocationCb ", __FUNCTION__);
+    }
+
+}
+
+void GnssAPIClient::onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification)
+{
+    LOC_LOGD("%s]: (id: %d)", __FUNCTION__, id);
+    mMutex.lock();
+    auto gnssNiCbIface(mGnssNiCbIface);
+    mMutex.unlock();
+
+    if (gnssNiCbIface == nullptr) {
+        LOC_LOGE("%s]: mGnssNiCbIface is nullptr", __FUNCTION__);
+        return;
+    }
+
+    IGnssNiCallback::GnssNiNotification notificationGnss = {};
+
+    notificationGnss.notificationId = id;
+
+    if (gnssNiNotification.type == GNSS_NI_TYPE_VOICE)
+        notificationGnss.niType = IGnssNiCallback::GnssNiType::VOICE;
+    else if (gnssNiNotification.type == GNSS_NI_TYPE_SUPL)
+        notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_SUPL;
+    else if (gnssNiNotification.type == GNSS_NI_TYPE_CONTROL_PLANE)
+        notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_CTRL_PLANE;
+    else if (gnssNiNotification.type == GNSS_NI_TYPE_EMERGENCY_SUPL)
+        notificationGnss.niType = IGnssNiCallback::GnssNiType::EMERGENCY_SUPL;
+
+    if (gnssNiNotification.options & GNSS_NI_OPTIONS_NOTIFICATION_BIT)
+        notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_NOTIFY;
+    if (gnssNiNotification.options & GNSS_NI_OPTIONS_VERIFICATION_BIT)
+        notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_VERIFY;
+    if (gnssNiNotification.options & GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT)
+        notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::PRIVACY_OVERRIDE;
+
+    notificationGnss.timeoutSec = gnssNiNotification.timeout;
+
+    if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_ACCEPT)
+        notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT;
+    else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_DENY)
+        notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY;
+    else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_NO_RESPONSE ||
+            gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_IGNORE)
+        notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP;
+
+    notificationGnss.requestorId = gnssNiNotification.requestor;
+
+    notificationGnss.notificationMessage = gnssNiNotification.message;
+
+    if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_NONE)
+        notificationGnss.requestorIdEncoding =
+            IGnssNiCallback::GnssNiEncodingType::ENC_NONE;
+    else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT)
+        notificationGnss.requestorIdEncoding =
+            IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT;
+    else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UTF8)
+        notificationGnss.requestorIdEncoding =
+            IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8;
+    else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UCS2)
+        notificationGnss.requestorIdEncoding =
+            IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2;
+
+    if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_NONE)
+        notificationGnss.notificationIdEncoding =
+            IGnssNiCallback::GnssNiEncodingType::ENC_NONE;
+    else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT)
+        notificationGnss.notificationIdEncoding =
+            IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT;
+    else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UTF8)
+        notificationGnss.notificationIdEncoding =
+            IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8;
+    else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UCS2)
+        notificationGnss.notificationIdEncoding =
+            IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2;
+
+    gnssNiCbIface->niNotifyCb(notificationGnss);
+}
+
+void GnssAPIClient::onGnssSvCb(GnssSvNotification gnssSvNotification)
+{
+    LOC_LOGD("%s]: (count: %u)", __FUNCTION__, gnssSvNotification.count);
+    mMutex.lock();
+    auto gnssCbIface(mGnssCbIface);
+    auto gnssCbIface_2_0(mGnssCbIface_2_0);
+    auto gnssCbIface_2_1(mGnssCbIface_2_1);
+    mMutex.unlock();
+
+    if (gnssCbIface_2_1 != nullptr) {
+        hidl_vec<V2_1::IGnssCallback::GnssSvInfo> svInfoList;
+        convertGnssSvStatus(gnssSvNotification, svInfoList);
+        auto r = gnssCbIface_2_1->gnssSvStatusCb_2_1(svInfoList);
+        if (!r.isOk()) {
+            LOC_LOGE("%s] Error from gnssSvStatusCb_2_1 description=%s",
+                __func__, r.description().c_str());
+        }
+    } else if (gnssCbIface_2_0 != nullptr) {
+        hidl_vec<V2_0::IGnssCallback::GnssSvInfo> svInfoList;
+        convertGnssSvStatus(gnssSvNotification, svInfoList);
+        auto r = gnssCbIface_2_0->gnssSvStatusCb_2_0(svInfoList);
+        if (!r.isOk()) {
+            LOC_LOGE("%s] Error from gnssSvStatusCb_2_0 description=%s",
+                __func__, r.description().c_str());
+        }
+    } else if (gnssCbIface != nullptr) {
+        V1_0::IGnssCallback::GnssSvStatus svStatus;
+        convertGnssSvStatus(gnssSvNotification, svStatus);
+        auto r = gnssCbIface->gnssSvStatusCb(svStatus);
+        if (!r.isOk()) {
+            LOC_LOGE("%s] Error from gnssSvStatusCb description=%s",
+                __func__, r.description().c_str());
+        }
+    }
+}
+
+void GnssAPIClient::onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification)
+{
+    mMutex.lock();
+    auto gnssCbIface(mGnssCbIface);
+    auto gnssCbIface_2_0(mGnssCbIface_2_0);
+    auto gnssCbIface_2_1(mGnssCbIface_2_1);
+    mMutex.unlock();
+
+    if (gnssCbIface != nullptr || gnssCbIface_2_0 != nullptr || gnssCbIface_2_1 != nullptr) {
+        const std::string s(gnssNmeaNotification.nmea);
+        std::stringstream ss(s);
+        std::string each;
+        while(std::getline(ss, each, '\n')) {
+            each += '\n';
+            android::hardware::hidl_string nmeaString;
+            nmeaString.setToExternal(each.c_str(), each.length());
+            if (gnssCbIface_2_1 != nullptr) {
+                auto r = gnssCbIface_2_1->gnssNmeaCb(
+                        static_cast<V1_0::GnssUtcTime>(gnssNmeaNotification.timestamp), nmeaString);
+                if (!r.isOk()) {
+                    LOC_LOGE("%s] Error from gnssCbIface_2_1 nmea=%s length=%u description=%s",
+                             __func__, gnssNmeaNotification.nmea, gnssNmeaNotification.length,
+                             r.description().c_str());
+                }
+            } else if (gnssCbIface_2_0 != nullptr) {
+                auto r = gnssCbIface_2_0->gnssNmeaCb(
+                        static_cast<V1_0::GnssUtcTime>(gnssNmeaNotification.timestamp), nmeaString);
+                if (!r.isOk()) {
+                    LOC_LOGE("%s] Error from gnssCbIface_2_0 nmea=%s length=%u description=%s",
+                             __func__, gnssNmeaNotification.nmea, gnssNmeaNotification.length,
+                             r.description().c_str());
+                }
+            } else if (gnssCbIface != nullptr) {
+                auto r = gnssCbIface->gnssNmeaCb(
+                        static_cast<V1_0::GnssUtcTime>(gnssNmeaNotification.timestamp), nmeaString);
+                if (!r.isOk()) {
+                    LOC_LOGE("%s] Error from gnssNmeaCb nmea=%s length=%u description=%s",
+                             __func__, gnssNmeaNotification.nmea, gnssNmeaNotification.length,
+                             r.description().c_str());
+                }
+            }
+        }
+    }
+}
+
+void GnssAPIClient::onStartTrackingCb(LocationError error)
+{
+    LOC_LOGD("%s]: (%d)", __FUNCTION__, error);
+    mMutex.lock();
+    auto gnssCbIface(mGnssCbIface);
+    auto gnssCbIface_2_0(mGnssCbIface_2_0);
+    auto gnssCbIface_2_1(mGnssCbIface_2_1);
+    mMutex.unlock();
+
+    if (error == LOCATION_ERROR_SUCCESS) {
+        if (gnssCbIface_2_1 != nullptr) {
+            auto r = gnssCbIface_2_1->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssStatusCb 2_0 ENGINE_ON description=%s",
+                    __func__, r.description().c_str());
+            }
+            r = gnssCbIface_2_1->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssStatusCb 2_0 SESSION_BEGIN description=%s",
+                    __func__, r.description().c_str());
+            }
+        } else if (gnssCbIface_2_0 != nullptr) {
+            auto r = gnssCbIface_2_0->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssStatusCb 2_0 ENGINE_ON description=%s",
+                    __func__, r.description().c_str());
+            }
+            r = gnssCbIface_2_0->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssStatusCb 2_0 SESSION_BEGIN description=%s",
+                    __func__, r.description().c_str());
+            }
+        } else if (gnssCbIface != nullptr) {
+            auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssStatusCb ENGINE_ON description=%s",
+                    __func__, r.description().c_str());
+            }
+            r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssStatusCb SESSION_BEGIN description=%s",
+                    __func__, r.description().c_str());
+            }
+        }
+    }
+}
+
+void GnssAPIClient::onStopTrackingCb(LocationError error)
+{
+    LOC_LOGD("%s]: (%d)", __FUNCTION__, error);
+    mMutex.lock();
+    auto gnssCbIface(mGnssCbIface);
+    auto gnssCbIface_2_0(mGnssCbIface_2_0);
+    auto gnssCbIface_2_1(mGnssCbIface_2_1);
+    mMutex.unlock();
+
+    if (error == LOCATION_ERROR_SUCCESS) {
+        if (gnssCbIface_2_1 != nullptr) {
+            auto r = gnssCbIface_2_1->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssStatusCb 2_0 SESSION_END description=%s",
+                    __func__, r.description().c_str());
+            }
+            r = gnssCbIface_2_1->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssStatusCb 2_0 ENGINE_OFF description=%s",
+                    __func__, r.description().c_str());
+            }
+        } else if (gnssCbIface_2_0 != nullptr) {
+            auto r = gnssCbIface_2_0->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssStatusCb 2_0 SESSION_END description=%s",
+                    __func__, r.description().c_str());
+            }
+            r = gnssCbIface_2_0->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssStatusCb 2_0 ENGINE_OFF description=%s",
+                    __func__, r.description().c_str());
+            }
+
+        } else if (gnssCbIface != nullptr) {
+            auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssStatusCb SESSION_END description=%s",
+                    __func__, r.description().c_str());
+            }
+            r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssStatusCb ENGINE_OFF description=%s",
+                    __func__, r.description().c_str());
+            }
+        }
+    }
+}
+
+static void convertGnssSvStatus(GnssSvNotification& in, V1_0::IGnssCallback::GnssSvStatus& out)
+{
+    memset(&out, 0, sizeof(IGnssCallback::GnssSvStatus));
+    out.numSvs = in.count;
+    if (out.numSvs > static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT)) {
+        LOC_LOGW("%s]: Too many satellites %u. Clamps to %d.",
+                __FUNCTION__,  out.numSvs, V1_0::GnssMax::SVS_COUNT);
+        out.numSvs = static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT);
+    }
+    for (size_t i = 0; i < out.numSvs; i++) {
+        convertGnssSvid(in.gnssSvs[i], out.gnssSvList[i].svid);
+        convertGnssConstellationType(in.gnssSvs[i].type, out.gnssSvList[i].constellation);
+        out.gnssSvList[i].cN0Dbhz = in.gnssSvs[i].cN0Dbhz;
+        out.gnssSvList[i].elevationDegrees = in.gnssSvs[i].elevation;
+        out.gnssSvList[i].azimuthDegrees = in.gnssSvs[i].azimuth;
+        out.gnssSvList[i].carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz;
+        out.gnssSvList[i].svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
+        if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT)
+            out.gnssSvList[i].svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
+        if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT)
+            out.gnssSvList[i].svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
+        if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)
+            out.gnssSvList[i].svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
+        if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT)
+            out.gnssSvList[i].svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY;
+    }
+}
+
+static void convertGnssSvStatus(GnssSvNotification& in,
+        hidl_vec<V2_0::IGnssCallback::GnssSvInfo>& out)
+{
+    out.resize(in.count);
+    for (size_t i = 0; i < in.count; i++) {
+        convertGnssSvid(in.gnssSvs[i], out[i].v1_0.svid);
+        out[i].v1_0.cN0Dbhz = in.gnssSvs[i].cN0Dbhz;
+        out[i].v1_0.elevationDegrees = in.gnssSvs[i].elevation;
+        out[i].v1_0.azimuthDegrees = in.gnssSvs[i].azimuth;
+        out[i].v1_0.carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz;
+        out[i].v1_0.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
+        if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT)
+            out[i].v1_0.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
+        if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT)
+            out[i].v1_0.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
+        if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)
+            out[i].v1_0.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
+        if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT)
+            out[i].v1_0.svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY;
+
+        convertGnssConstellationType(in.gnssSvs[i].type, out[i].constellation);
+    }
+}
+
+static void convertGnssSvStatus(GnssSvNotification& in,
+        hidl_vec<V2_1::IGnssCallback::GnssSvInfo>& out)
+{
+    out.resize(in.count);
+    for (size_t i = 0; i < in.count; i++) {
+        convertGnssSvid(in.gnssSvs[i], out[i].v2_0.v1_0.svid);
+        out[i].v2_0.v1_0.cN0Dbhz = in.gnssSvs[i].cN0Dbhz;
+        out[i].v2_0.v1_0.elevationDegrees = in.gnssSvs[i].elevation;
+        out[i].v2_0.v1_0.azimuthDegrees = in.gnssSvs[i].azimuth;
+        out[i].v2_0.v1_0.carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz;
+        out[i].v2_0.v1_0.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
+        if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT)
+            out[i].v2_0.v1_0.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
+        if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT)
+            out[i].v2_0.v1_0.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
+        if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)
+            out[i].v2_0.v1_0.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
+        if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT)
+            out[i].v2_0.v1_0.svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY;
+
+        convertGnssConstellationType(in.gnssSvs[i].type, out[i].v2_0.constellation);
+        out[i].basebandCN0DbHz = in.gnssSvs[i].basebandCarrierToNoiseDbHz;
+    }
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/android/2.1/location_api/GnssAPIClient.h b/android/2.1/location_api/GnssAPIClient.h
new file mode 100755
index 0000000..c4dbe9a
--- /dev/null
+++ b/android/2.1/location_api/GnssAPIClient.h
@@ -0,0 +1,118 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation, nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GNSS_API_CLINET_H
+#define GNSS_API_CLINET_H
+
+
+#include <mutex>
+#include <android/hardware/gnss/2.1/IGnss.h>
+#include <android/hardware/gnss/2.1/IGnssCallback.h>
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::sp;
+
+class GnssAPIClient : public LocationAPIClientBase
+{
+public:
+    GnssAPIClient(const sp<V1_0::IGnssCallback>& gpsCb,
+            const sp<V1_0::IGnssNiCallback>& niCb);
+    GnssAPIClient(const sp<V2_0::IGnssCallback>& gpsCb);
+    GnssAPIClient(const sp<V2_1::IGnssCallback>& gpsCb);
+    GnssAPIClient(const GnssAPIClient&) = delete;
+    GnssAPIClient& operator=(const GnssAPIClient&) = delete;
+
+    // for GpsInterface
+    void gnssUpdateCallbacks(const sp<V1_0::IGnssCallback>& gpsCb,
+            const sp<V1_0::IGnssNiCallback>& niCb);
+    void gnssUpdateCallbacks_2_0(const sp<V2_0::IGnssCallback>& gpsCb);
+    void gnssUpdateCallbacks_2_1(const sp<V2_1::IGnssCallback>& gpsCb);
+    bool gnssStart();
+    bool gnssStop();
+    bool gnssSetPositionMode(V1_0::IGnss::GnssPositionMode mode,
+            V1_0::IGnss::GnssPositionRecurrence recurrence,
+            uint32_t minIntervalMs,
+            uint32_t preferredAccuracyMeters,
+            uint32_t preferredTimeMs,
+            GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+            uint32_t timeBetweenMeasurement = 0);
+
+    // for GpsNiInterface
+    void gnssNiRespond(int32_t notifId, V1_0::IGnssNiCallback::GnssUserResponseType userResponse);
+
+    // these apis using LocationAPIControlClient
+    void gnssDeleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags);
+    void gnssEnable(LocationTechnologyType techType);
+    void gnssDisable();
+    void gnssConfigurationUpdate(const GnssConfig& gnssConfig);
+
+    inline LocationCapabilitiesMask gnssGetCapabilities() const {
+        return mLocationCapabilitiesMask;
+    }
+    void requestCapabilities();
+
+    // callbacks we are interested in
+    void onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) final;
+    void onTrackingCb(Location location) final;
+    void onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification) final;
+    void onGnssSvCb(GnssSvNotification gnssSvNotification) final;
+    void onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification) final;
+
+    void onStartTrackingCb(LocationError error) final;
+    void onStopTrackingCb(LocationError error) final;
+
+private:
+    virtual ~GnssAPIClient();
+    void setCallbacks();
+    void initLocationOptions();
+
+    sp<V1_0::IGnssCallback> mGnssCbIface;
+    sp<V1_0::IGnssNiCallback> mGnssNiCbIface;
+    std::mutex mMutex;
+    LocationAPIControlClient* mControlClient;
+    LocationCapabilitiesMask mLocationCapabilitiesMask;
+    bool mLocationCapabilitiesCached;
+    TrackingOptions mTrackingOptions;
+    bool mTracking;
+    sp<V2_0::IGnssCallback> mGnssCbIface_2_0;
+    sp<V2_1::IGnssCallback> mGnssCbIface_2_1;
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+#endif // GNSS_API_CLINET_H
diff --git a/android/2.1/location_api/LocationUtil.cpp b/android/2.1/location_api/LocationUtil.cpp
new file mode 100644
index 0000000..5154e70
--- /dev/null
+++ b/android/2.1/location_api/LocationUtil.cpp
@@ -0,0 +1,405 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation, nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <LocationUtil.h>
+#include <log_util.h>
+#include <inttypes.h>
+#include <loc_misc_utils.h>
+#include <gps_extended_c.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_0::GnssLocation;
+using ::android::hardware::gnss::V2_0::ElapsedRealtimeFlags;
+using ::android::hardware::gnss::V2_0::GnssConstellationType;
+using ::android::hardware::gnss::V1_0::GnssLocationFlags;
+using ::android::hardware::gnss::measurement_corrections::V1_0::GnssSingleSatCorrectionFlags;
+
+void convertGnssLocation(Location& in, V1_0::GnssLocation& out)
+{
+    memset(&out, 0, sizeof(V1_0::GnssLocation));
+    if (in.flags & LOCATION_HAS_LAT_LONG_BIT) {
+        out.gnssLocationFlags |= GnssLocationFlags::HAS_LAT_LONG;
+        out.latitudeDegrees = in.latitude;
+        out.longitudeDegrees = in.longitude;
+    }
+    if (in.flags & LOCATION_HAS_ALTITUDE_BIT) {
+        out.gnssLocationFlags |= GnssLocationFlags::HAS_ALTITUDE;
+        out.altitudeMeters = in.altitude;
+    }
+    if (in.flags & LOCATION_HAS_SPEED_BIT) {
+        out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED;
+        out.speedMetersPerSec = in.speed;
+    }
+    if (in.flags & LOCATION_HAS_BEARING_BIT) {
+        out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING;
+        out.bearingDegrees = in.bearing;
+    }
+    if (in.flags & LOCATION_HAS_ACCURACY_BIT) {
+        out.gnssLocationFlags |= GnssLocationFlags::HAS_HORIZONTAL_ACCURACY;
+        out.horizontalAccuracyMeters = in.accuracy;
+    }
+    if (in.flags & LOCATION_HAS_VERTICAL_ACCURACY_BIT) {
+        out.gnssLocationFlags |= GnssLocationFlags::HAS_VERTICAL_ACCURACY;
+        out.verticalAccuracyMeters = in.verticalAccuracy;
+    }
+    if (in.flags & LOCATION_HAS_SPEED_ACCURACY_BIT) {
+        out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED_ACCURACY;
+        out.speedAccuracyMetersPerSecond = in.speedAccuracy;
+    }
+    if (in.flags & LOCATION_HAS_BEARING_ACCURACY_BIT) {
+        out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING_ACCURACY;
+        out.bearingAccuracyDegrees = in.bearingAccuracy;
+    }
+
+    out.timestamp = static_cast<V1_0::GnssUtcTime>(in.timestamp);
+}
+
+void convertGnssLocation(Location& in, V2_0::GnssLocation& out)
+{
+    memset(&out, 0, sizeof(V2_0::GnssLocation));
+    convertGnssLocation(in, out.v1_0);
+
+    if (in.flags & LOCATION_HAS_ELAPSED_REAL_TIME) {
+        out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS;
+        out.elapsedRealtime.timestampNs = in.elapsedRealTime;
+        out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS;
+        out.elapsedRealtime.timeUncertaintyNs = in.elapsedRealTimeUnc;
+        LOC_LOGd("out.elapsedRealtime.timestampNs=%" PRIi64 ""
+                 " out.elapsedRealtime.timeUncertaintyNs=%" PRIi64 ""
+                 " out.elapsedRealtime.flags=0x%X",
+                 out.elapsedRealtime.timestampNs,
+                 out.elapsedRealtime.timeUncertaintyNs, out.elapsedRealtime.flags);
+    }
+}
+
+void convertGnssLocation(const V1_0::GnssLocation& in, Location& out)
+{
+    memset(&out, 0, sizeof(out));
+    if (in.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG) {
+        out.flags |= LOCATION_HAS_LAT_LONG_BIT;
+        out.latitude = in.latitudeDegrees;
+        out.longitude = in.longitudeDegrees;
+    }
+    if (in.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE) {
+        out.flags |= LOCATION_HAS_ALTITUDE_BIT;
+        out.altitude = in.altitudeMeters;
+    }
+    if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED) {
+        out.flags |= LOCATION_HAS_SPEED_BIT;
+        out.speed = in.speedMetersPerSec;
+    }
+    if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) {
+        out.flags |= LOCATION_HAS_BEARING_BIT;
+        out.bearing = in.bearingDegrees;
+    }
+    if (in.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) {
+        out.flags |= LOCATION_HAS_ACCURACY_BIT;
+        out.accuracy = in.horizontalAccuracyMeters;
+    }
+    if (in.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
+        out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT;
+        out.verticalAccuracy = in.verticalAccuracyMeters;
+    }
+    if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) {
+        out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT;
+        out.speedAccuracy = in.speedAccuracyMetersPerSecond;
+    }
+    if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) {
+        out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
+        out.bearingAccuracy = in.bearingAccuracyDegrees;
+    }
+
+    out.timestamp = static_cast<uint64_t>(in.timestamp);
+}
+
+void convertGnssLocation(const V2_0::GnssLocation& in, Location& out)
+{
+    memset(&out, 0, sizeof(out));
+    convertGnssLocation(in.v1_0, out);
+}
+
+void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out)
+{
+    switch(in) {
+        case GNSS_SV_TYPE_GPS:
+            out = V1_0::GnssConstellationType::GPS;
+            break;
+        case GNSS_SV_TYPE_SBAS:
+            out = V1_0::GnssConstellationType::SBAS;
+            break;
+        case GNSS_SV_TYPE_GLONASS:
+            out = V1_0::GnssConstellationType::GLONASS;
+            break;
+        case GNSS_SV_TYPE_QZSS:
+            out = V1_0::GnssConstellationType::QZSS;
+            break;
+        case GNSS_SV_TYPE_BEIDOU:
+            out = V1_0::GnssConstellationType::BEIDOU;
+            break;
+        case GNSS_SV_TYPE_GALILEO:
+            out = V1_0::GnssConstellationType::GALILEO;
+            break;
+        case GNSS_SV_TYPE_UNKNOWN:
+        default:
+            out = V1_0::GnssConstellationType::UNKNOWN;
+            break;
+    }
+}
+
+void convertGnssConstellationType(GnssSvType& in, V2_0::GnssConstellationType& out)
+{
+    switch(in) {
+        case GNSS_SV_TYPE_GPS:
+            out = V2_0::GnssConstellationType::GPS;
+            break;
+        case GNSS_SV_TYPE_SBAS:
+            out = V2_0::GnssConstellationType::SBAS;
+            break;
+        case GNSS_SV_TYPE_GLONASS:
+            out = V2_0::GnssConstellationType::GLONASS;
+            break;
+        case GNSS_SV_TYPE_QZSS:
+            out = V2_0::GnssConstellationType::QZSS;
+            break;
+        case GNSS_SV_TYPE_BEIDOU:
+            out = V2_0::GnssConstellationType::BEIDOU;
+            break;
+        case GNSS_SV_TYPE_GALILEO:
+            out = V2_0::GnssConstellationType::GALILEO;
+            break;
+        case GNSS_SV_TYPE_NAVIC:
+            out = V2_0::GnssConstellationType::IRNSS;
+            break;
+        case GNSS_SV_TYPE_UNKNOWN:
+        default:
+            out = V2_0::GnssConstellationType::UNKNOWN;
+            break;
+    }
+}
+
+void convertGnssSvid(GnssSv& in, int16_t& out)
+{
+    switch (in.type) {
+        case GNSS_SV_TYPE_GPS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_SBAS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_GLONASS:
+            if (!isGloSlotUnknown(in.svId)) { // OSN is known
+                out = in.svId - GLO_SV_PRN_MIN + 1;
+            } else { // OSN is not known, report FCN
+                out = in.gloFrequency + 92;
+            }
+            break;
+        case GNSS_SV_TYPE_QZSS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_BEIDOU:
+            out = in.svId - BDS_SV_PRN_MIN + 1;
+            break;
+        case GNSS_SV_TYPE_GALILEO:
+            out = in.svId - GAL_SV_PRN_MIN + 1;
+            break;
+        case GNSS_SV_TYPE_NAVIC:
+            out = in.svId - NAVIC_SV_PRN_MIN + 1;
+            break;
+        default:
+            out = in.svId;
+            break;
+    }
+}
+
+void convertGnssSvid(GnssMeasurementsData& in, int16_t& out)
+{
+    switch (in.svType) {
+        case GNSS_SV_TYPE_GPS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_SBAS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_GLONASS:
+            if (!isGloSlotUnknown(in.svId)) { // OSN is known
+                out = in.svId - GLO_SV_PRN_MIN + 1;
+            } else { // OSN is not known, report FCN
+                out = in.gloFrequency + 92;
+            }
+            break;
+        case GNSS_SV_TYPE_QZSS:
+            out = in.svId;
+            break;
+        case GNSS_SV_TYPE_BEIDOU:
+            out = in.svId - BDS_SV_PRN_MIN + 1;
+            break;
+        case GNSS_SV_TYPE_GALILEO:
+            out = in.svId - GAL_SV_PRN_MIN + 1;
+            break;
+        case GNSS_SV_TYPE_NAVIC:
+            out = in.svId - NAVIC_SV_PRN_MIN + 1;
+            break;
+        default:
+            out = in.svId;
+            break;
+    }
+}
+
+void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out)
+{
+    switch(in) {
+        case GNSS_EPH_TYPE_EPHEMERIS:
+            out = GnssDebug::SatelliteEphemerisType::EPHEMERIS;
+            break;
+        case GNSS_EPH_TYPE_ALMANAC:
+            out = GnssDebug::SatelliteEphemerisType::ALMANAC_ONLY;
+            break;
+        case GNSS_EPH_TYPE_UNKNOWN:
+        default:
+            out = GnssDebug::SatelliteEphemerisType::NOT_AVAILABLE;
+            break;
+    }
+}
+
+void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out)
+{
+    switch(in) {
+        case GNSS_EPH_SOURCE_DEMODULATED:
+            out = GnssDebug::SatelliteEphemerisSource::DEMODULATED;
+            break;
+        case GNSS_EPH_SOURCE_SUPL_PROVIDED:
+            out = GnssDebug::SatelliteEphemerisSource::SUPL_PROVIDED;
+            break;
+        case GNSS_EPH_SOURCE_OTHER_SERVER_PROVIDED:
+            out = GnssDebug::SatelliteEphemerisSource::OTHER_SERVER_PROVIDED;
+            break;
+        case GNSS_EPH_SOURCE_LOCAL:
+        case GNSS_EPH_SOURCE_UNKNOWN:
+        default:
+            out = GnssDebug::SatelliteEphemerisSource::OTHER;
+            break;
+    }
+}
+
+void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out)
+{
+    switch(in) {
+        case GNSS_EPH_HEALTH_GOOD:
+            out = GnssDebug::SatelliteEphemerisHealth::GOOD;
+            break;
+        case GNSS_EPH_HEALTH_BAD:
+            out = GnssDebug::SatelliteEphemerisHealth::BAD;
+            break;
+        case GNSS_EPH_HEALTH_UNKNOWN:
+        default:
+            out = GnssDebug::SatelliteEphemerisHealth::UNKNOWN;
+            break;
+    }
+}
+
+void convertSingleSatCorrections(const SingleSatCorrection& in, GnssSingleSatCorrection& out)
+{
+    out.flags = GNSS_MEAS_CORR_UNKNOWN_BIT;
+    if (in.singleSatCorrectionFlags & (GnssSingleSatCorrectionFlags::HAS_SAT_IS_LOS_PROBABILITY)) {
+        out.flags |= GNSS_MEAS_CORR_HAS_SAT_IS_LOS_PROBABILITY_BIT;
+    }
+    if (in.singleSatCorrectionFlags & (GnssSingleSatCorrectionFlags::HAS_EXCESS_PATH_LENGTH)) {
+        out.flags |= GNSS_MEAS_CORR_HAS_EXCESS_PATH_LENGTH_BIT;
+    }
+    if (in.singleSatCorrectionFlags & (GnssSingleSatCorrectionFlags::HAS_EXCESS_PATH_LENGTH_UNC)) {
+        out.flags |= GNSS_MEAS_CORR_HAS_EXCESS_PATH_LENGTH_UNC_BIT;
+    }
+    if (in.singleSatCorrectionFlags & (GnssSingleSatCorrectionFlags::HAS_REFLECTING_PLANE)) {
+        out.flags |= GNSS_MEAS_CORR_HAS_REFLECTING_PLANE_BIT;
+    }
+    switch (in.constellation) {
+    case (::android::hardware::gnss::V1_0::GnssConstellationType::GPS):
+        out.svType = GNSS_SV_TYPE_GPS;
+        break;
+    case (::android::hardware::gnss::V1_0::GnssConstellationType::SBAS):
+        out.svType = GNSS_SV_TYPE_SBAS;
+        break;
+    case (::android::hardware::gnss::V1_0::GnssConstellationType::GLONASS):
+        out.svType = GNSS_SV_TYPE_GLONASS;
+        break;
+    case (::android::hardware::gnss::V1_0::GnssConstellationType::QZSS):
+        out.svType = GNSS_SV_TYPE_QZSS;
+        break;
+    case (::android::hardware::gnss::V1_0::GnssConstellationType::BEIDOU):
+        out.svType = GNSS_SV_TYPE_BEIDOU;
+        break;
+    case (::android::hardware::gnss::V1_0::GnssConstellationType::GALILEO):
+        out.svType = GNSS_SV_TYPE_GALILEO;
+        break;
+    case (::android::hardware::gnss::V1_0::GnssConstellationType::UNKNOWN):
+    default:
+        out.svType = GNSS_SV_TYPE_UNKNOWN;
+        break;
+    }
+    out.svId = in.svid;
+    out.carrierFrequencyHz = in.carrierFrequencyHz;
+    out.probSatIsLos = in.probSatIsLos;
+    out.excessPathLengthMeters = in.excessPathLengthMeters;
+    out.excessPathLengthUncertaintyMeters = in.excessPathLengthUncertaintyMeters;
+
+    out.reflectingPlane.latitudeDegrees = in.reflectingPlane.latitudeDegrees;
+    out.reflectingPlane.longitudeDegrees = in.reflectingPlane.longitudeDegrees;
+    out.reflectingPlane.altitudeMeters = in.reflectingPlane.altitudeMeters;
+    out.reflectingPlane.azimuthDegrees = in.reflectingPlane.azimuthDegrees;
+}
+
+void convertMeasurementCorrections(const MeasurementCorrectionsV1_0& in,
+                                   GnssMeasurementCorrections& out)
+{
+    memset(&out, 0, sizeof(GnssMeasurementCorrections));
+    out.latitudeDegrees = in.latitudeDegrees;
+    out.longitudeDegrees = in.longitudeDegrees;
+    out.altitudeMeters = in.altitudeMeters;
+    out.horizontalPositionUncertaintyMeters = in.horizontalPositionUncertaintyMeters;
+    out.verticalPositionUncertaintyMeters = in.verticalPositionUncertaintyMeters;
+    out.toaGpsNanosecondsOfWeek = in.toaGpsNanosecondsOfWeek;
+
+    for (int i = 0; i < in.satCorrections.size(); i++) {
+        GnssSingleSatCorrection gnssSingleSatCorrection = {};
+
+        convertSingleSatCorrections(in.satCorrections[i], gnssSingleSatCorrection);
+        out.satCorrections.push_back(gnssSingleSatCorrection);
+    }
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/android/2.1/location_api/LocationUtil.h b/android/2.1/location_api/LocationUtil.h
new file mode 100644
index 0000000..2d95a2d
--- /dev/null
+++ b/android/2.1/location_api/LocationUtil.h
@@ -0,0 +1,68 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation, nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef LOCATION_UTIL_H
+#define LOCATION_UTIL_H
+
+#include <android/hardware/gnss/2.0/types.h>
+#include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrections.h>
+#include <LocationAPI.h>
+#include <GnssDebug.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using MeasurementCorrectionsV1_0 =
+        ::android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections;
+using ::android::hardware::gnss::measurement_corrections::V1_0::SingleSatCorrection;
+
+void convertGnssLocation(Location& in, V1_0::GnssLocation& out);
+void convertGnssLocation(Location& in, V2_0::GnssLocation& out);
+void convertGnssLocation(const V1_0::GnssLocation& in, Location& out);
+void convertGnssLocation(const V2_0::GnssLocation& in, Location& out);
+void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out);
+void convertGnssConstellationType(GnssSvType& in, V2_0::GnssConstellationType& out);
+void convertGnssSvid(GnssSv& in, int16_t& out);
+void convertGnssSvid(GnssMeasurementsData& in, int16_t& out);
+void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out);
+void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out);
+void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out);
+void convertSingleSatCorrections(const SingleSatCorrection& in, GnssSingleSatCorrection& out);
+void convertMeasurementCorrections(const MeasurementCorrectionsV1_0& in,
+                                   GnssMeasurementCorrections& out);
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+#endif // LOCATION_UTIL_H
diff --git a/android/2.1/location_api/MeasurementAPIClient.cpp b/android/2.1/location_api/MeasurementAPIClient.cpp
new file mode 100644
index 0000000..0028074
--- /dev/null
+++ b/android/2.1/location_api/MeasurementAPIClient.cpp
@@ -0,0 +1,642 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation, nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_MeasurementAPIClient"
+
+#include <log_util.h>
+#include <loc_cfg.h>
+#include <inttypes.h>
+
+#include "LocationUtil.h"
+#include "MeasurementAPIClient.h"
+#include <loc_misc_utils.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssMeasurement;
+using ::android::hardware::gnss::V2_0::IGnssMeasurementCallback;
+
+static void convertGnssData(GnssMeasurementsNotification& in,
+        V1_0::IGnssMeasurementCallback::GnssData& out);
+static void convertGnssData_1_1(GnssMeasurementsNotification& in,
+        V1_1::IGnssMeasurementCallback::GnssData& out);
+static void convertGnssData_2_0(GnssMeasurementsNotification& in,
+        V2_0::IGnssMeasurementCallback::GnssData& out);
+static void convertGnssData_2_1(GnssMeasurementsNotification& in,
+        V2_1::IGnssMeasurementCallback::GnssData& out);
+static void convertGnssMeasurement(GnssMeasurementsData& in,
+        V1_0::IGnssMeasurementCallback::GnssMeasurement& out);
+static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out);
+static void convertGnssClock_2_1(GnssMeasurementsClock& in,
+        V2_1::IGnssMeasurementCallback::GnssClock& out);
+static void convertGnssMeasurementsCodeType(GnssMeasurementsCodeType& inCodeType,
+        char* inOtherCodeTypeName,
+        ::android::hardware::hidl_string& out);
+static void convertGnssMeasurementsAccumulatedDeltaRangeState(GnssMeasurementsAdrStateMask& in,
+        ::android::hardware::hidl_bitfield
+                <V1_1::IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState>& out);
+static void convertGnssMeasurementsState(GnssMeasurementsStateMask& in,
+        ::android::hardware::hidl_bitfield
+                <V2_0::IGnssMeasurementCallback::GnssMeasurementState>& out);
+static void convertElapsedRealtimeNanos(GnssMeasurementsNotification& in,
+        ::android::hardware::gnss::V2_0::ElapsedRealtime& elapsedRealtimeNanos);
+
+MeasurementAPIClient::MeasurementAPIClient() :
+    mGnssMeasurementCbIface(nullptr),
+    mGnssMeasurementCbIface_1_1(nullptr),
+    mGnssMeasurementCbIface_2_0(nullptr),
+    mGnssMeasurementCbIface_2_1(nullptr),
+    mTracking(false)
+{
+    LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+MeasurementAPIClient::~MeasurementAPIClient()
+{
+    LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+void MeasurementAPIClient::clearInterfaces()
+{
+    mGnssMeasurementCbIface = nullptr;
+    mGnssMeasurementCbIface_1_1 = nullptr;
+    mGnssMeasurementCbIface_2_0 = nullptr;
+    mGnssMeasurementCbIface_2_1 = nullptr;
+}
+
+// for GpsInterface
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::measurementSetCallback(const sp<V1_0::IGnssMeasurementCallback>& callback)
+{
+    LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+    mMutex.lock();
+    clearInterfaces();
+    mGnssMeasurementCbIface = callback;
+    mMutex.unlock();
+
+    return startTracking();
+}
+
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::measurementSetCallback_1_1(
+        const sp<V1_1::IGnssMeasurementCallback>& callback,
+        GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
+{
+    LOC_LOGD("%s]: (%p) (powermode: %d) (tbm: %d)",
+            __FUNCTION__, &callback, (int)powerMode, timeBetweenMeasurement);
+
+    mMutex.lock();
+    clearInterfaces();
+    mGnssMeasurementCbIface_1_1 = callback;
+    mMutex.unlock();
+
+    return startTracking(powerMode, timeBetweenMeasurement);
+}
+
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::measurementSetCallback_2_0(
+    const sp<V2_0::IGnssMeasurementCallback>& callback,
+    GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
+{
+    LOC_LOGD("%s]: (%p) (powermode: %d) (tbm: %d)",
+        __FUNCTION__, &callback, (int)powerMode, timeBetweenMeasurement);
+
+    mMutex.lock();
+    clearInterfaces();
+    mGnssMeasurementCbIface_2_0 = callback;
+    mMutex.unlock();
+
+    return startTracking(powerMode, timeBetweenMeasurement);
+}
+
+Return<IGnssMeasurement::GnssMeasurementStatus> MeasurementAPIClient::measurementSetCallback_2_1(
+        const sp<V2_1::IGnssMeasurementCallback>& callback,
+        GnssPowerMode powerMode, uint32_t timeBetweenMeasurement) {
+    LOC_LOGD("%s]: (%p) (powermode: %d) (tbm: %d)",
+        __FUNCTION__, &callback, (int)powerMode, timeBetweenMeasurement);
+
+    mMutex.lock();
+    clearInterfaces();
+    mGnssMeasurementCbIface_2_1 = callback;
+    mMutex.unlock();
+
+    return startTracking(powerMode, timeBetweenMeasurement);
+}
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::startTracking(
+        GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
+{
+    LocationCallbacks locationCallbacks;
+    memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+    locationCallbacks.size = sizeof(LocationCallbacks);
+
+    locationCallbacks.trackingCb = nullptr;
+    locationCallbacks.batchingCb = nullptr;
+    locationCallbacks.geofenceBreachCb = nullptr;
+    locationCallbacks.geofenceStatusCb = nullptr;
+    locationCallbacks.gnssLocationInfoCb = nullptr;
+    locationCallbacks.gnssNiCb = nullptr;
+    locationCallbacks.gnssSvCb = nullptr;
+    locationCallbacks.gnssNmeaCb = nullptr;
+
+    locationCallbacks.gnssMeasurementsCb = nullptr;
+    if (mGnssMeasurementCbIface_2_1 != nullptr ||
+        mGnssMeasurementCbIface_2_0 != nullptr ||
+        mGnssMeasurementCbIface_1_1 != nullptr ||
+        mGnssMeasurementCbIface != nullptr) {
+        locationCallbacks.gnssMeasurementsCb =
+            [this](GnssMeasurementsNotification gnssMeasurementsNotification) {
+                onGnssMeasurementsCb(gnssMeasurementsNotification);
+            };
+    }
+
+    locAPISetCallbacks(locationCallbacks);
+
+    TrackingOptions options = {};
+    memset(&options, 0, sizeof(TrackingOptions));
+    options.size = sizeof(TrackingOptions);
+    options.minInterval = 1000;
+    options.mode = GNSS_SUPL_MODE_STANDALONE;
+    if (GNSS_POWER_MODE_INVALID != powerMode) {
+        options.powerMode = powerMode;
+        options.tbm = timeBetweenMeasurement;
+    }
+
+    mTracking = true;
+    LOC_LOGD("%s]: start tracking session", __FUNCTION__);
+    locAPIStartTracking(options);
+    return IGnssMeasurement::GnssMeasurementStatus::SUCCESS;
+}
+
+// for GpsMeasurementInterface
+void MeasurementAPIClient::measurementClose() {
+    LOC_LOGD("%s]: ()", __FUNCTION__);
+    mTracking = false;
+    locAPIStopTracking();
+}
+
+// callbacks
+void MeasurementAPIClient::onGnssMeasurementsCb(
+        GnssMeasurementsNotification gnssMeasurementsNotification)
+{
+    LOC_LOGD("%s]: (count: %u active: %d)",
+            __FUNCTION__, gnssMeasurementsNotification.count, mTracking);
+    if (mTracking) {
+        mMutex.lock();
+        sp<V1_0::IGnssMeasurementCallback> gnssMeasurementCbIface = nullptr;
+        sp<V1_1::IGnssMeasurementCallback> gnssMeasurementCbIface_1_1 = nullptr;
+        sp<V2_0::IGnssMeasurementCallback> gnssMeasurementCbIface_2_0 = nullptr;
+        sp<V2_1::IGnssMeasurementCallback> gnssMeasurementCbIface_2_1 = nullptr;
+        if (mGnssMeasurementCbIface_2_1 != nullptr) {
+            gnssMeasurementCbIface_2_1 = mGnssMeasurementCbIface_2_1;
+        } else if (mGnssMeasurementCbIface_2_0 != nullptr) {
+            gnssMeasurementCbIface_2_0 = mGnssMeasurementCbIface_2_0;
+        } else if (mGnssMeasurementCbIface_1_1 != nullptr) {
+            gnssMeasurementCbIface_1_1 = mGnssMeasurementCbIface_1_1;
+        } else if (mGnssMeasurementCbIface != nullptr) {
+            gnssMeasurementCbIface = mGnssMeasurementCbIface;
+        }
+        mMutex.unlock();
+
+        if (gnssMeasurementCbIface_2_1 != nullptr) {
+            V2_1::IGnssMeasurementCallback::GnssData gnssData;
+            convertGnssData_2_1(gnssMeasurementsNotification, gnssData);
+            auto r = gnssMeasurementCbIface_2_1->gnssMeasurementCb_2_1(gnssData);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssMeasurementCb description=%s",
+                    __func__, r.description().c_str());
+            }
+        } else if (gnssMeasurementCbIface_2_0 != nullptr) {
+            V2_0::IGnssMeasurementCallback::GnssData gnssData;
+            convertGnssData_2_0(gnssMeasurementsNotification, gnssData);
+            auto r = gnssMeasurementCbIface_2_0->gnssMeasurementCb_2_0(gnssData);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssMeasurementCb description=%s",
+                    __func__, r.description().c_str());
+            }
+        } else if (gnssMeasurementCbIface_1_1 != nullptr) {
+            V1_1::IGnssMeasurementCallback::GnssData gnssData;
+            convertGnssData_1_1(gnssMeasurementsNotification, gnssData);
+            auto r = gnssMeasurementCbIface_1_1->gnssMeasurementCb(gnssData);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssMeasurementCb description=%s",
+                    __func__, r.description().c_str());
+            }
+        } else if (gnssMeasurementCbIface != nullptr) {
+            V1_0::IGnssMeasurementCallback::GnssData gnssData;
+            convertGnssData(gnssMeasurementsNotification, gnssData);
+            auto r = gnssMeasurementCbIface->GnssMeasurementCb(gnssData);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from GnssMeasurementCb description=%s",
+                    __func__, r.description().c_str());
+            }
+        }
+    }
+}
+
+static void convertGnssMeasurement(GnssMeasurementsData& in,
+        V1_0::IGnssMeasurementCallback::GnssMeasurement& out)
+{
+    memset(&out, 0, sizeof(out));
+    if (in.flags & GNSS_MEASUREMENTS_DATA_SIGNAL_TO_NOISE_RATIO_BIT)
+        out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_SNR;
+    if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_FREQUENCY_BIT)
+        out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_FREQUENCY;
+    if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_CYCLES_BIT)
+        out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_CYCLES;
+    if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_BIT)
+        out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE;
+    if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_UNCERTAINTY_BIT)
+        out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE_UNCERTAINTY;
+    if (in.flags & GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT)
+        out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_AUTOMATIC_GAIN_CONTROL;
+    convertGnssSvid(in, out.svid);
+    convertGnssConstellationType(in.svType, out.constellation);
+    out.timeOffsetNs = in.timeOffsetNs;
+    if (in.stateMask & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT)
+        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_CODE_LOCK;
+    if (in.stateMask & GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT)
+        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BIT_SYNC;
+    if (in.stateMask & GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT)
+        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SUBFRAME_SYNC;
+    if (in.stateMask & GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT)
+        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED;
+    if (in.stateMask & GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT)
+        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_MSEC_AMBIGUOUS;
+    if (in.stateMask & GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT)
+        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SYMBOL_SYNC;
+    if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT)
+        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_STRING_SYNC;
+    if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT)
+        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED;
+    if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT)
+        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_BIT_SYNC;
+    if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT)
+        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_SUBFRAME_SYNC;
+    if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT)
+        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1BC_CODE_LOCK;
+    if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT)
+        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1C_2ND_CODE_LOCK;
+    if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT)
+        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1B_PAGE_SYNC;
+    if (in.stateMask &  GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT)
+        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SBAS_SYNC;
+    out.receivedSvTimeInNs = in.receivedSvTimeNs;
+    out.receivedSvTimeUncertaintyInNs = in.receivedSvTimeUncertaintyNs;
+    out.cN0DbHz = in.carrierToNoiseDbHz;
+    out.pseudorangeRateMps = in.pseudorangeRateMps;
+    out.pseudorangeRateUncertaintyMps = in.pseudorangeRateUncertaintyMps;
+    if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT)
+        out.accumulatedDeltaRangeState |=
+            IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID;
+    if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT)
+        out.accumulatedDeltaRangeState |=
+            IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET;
+    if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT)
+        out.accumulatedDeltaRangeState |=
+            IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP;
+    out.accumulatedDeltaRangeM = in.adrMeters;
+    out.accumulatedDeltaRangeUncertaintyM = in.adrUncertaintyMeters;
+    out.carrierFrequencyHz = in.carrierFrequencyHz;
+    out.carrierCycles = in.carrierCycles;
+    out.carrierPhase = in.carrierPhase;
+    out.carrierPhaseUncertainty = in.carrierPhaseUncertainty;
+    uint8_t indicator =
+        static_cast<uint8_t>(IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN);
+    if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_PRESENT)
+        indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_PRESENT;
+    if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_NOT_PRESENT)
+        indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATIOR_NOT_PRESENT;
+    out.multipathIndicator =
+        static_cast<IGnssMeasurementCallback::GnssMultipathIndicator>(indicator);
+    out.snrDb = in.signalToNoiseRatioDb;
+    out.agcLevelDb = in.agcLevelDb;
+}
+
+static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out)
+{
+    memset(&out, 0, sizeof(out));
+    if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT)
+        out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_LEAP_SECOND;
+    if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_TIME_UNCERTAINTY_BIT)
+        out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_TIME_UNCERTAINTY;
+    if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_FULL_BIAS_BIT)
+        out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_FULL_BIAS;
+    if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_BIT)
+        out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS;
+    if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_UNCERTAINTY_BIT)
+        out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS_UNCERTAINTY;
+    if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_BIT)
+        out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT;
+    if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_UNCERTAINTY_BIT)
+        out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT_UNCERTAINTY;
+    out.leapSecond = in.leapSecond;
+    out.timeNs = in.timeNs;
+    out.timeUncertaintyNs = in.timeUncertaintyNs;
+    out.fullBiasNs = in.fullBiasNs;
+    out.biasNs = in.biasNs;
+    out.biasUncertaintyNs = in.biasUncertaintyNs;
+    out.driftNsps = in.driftNsps;
+    out.driftUncertaintyNsps = in.driftUncertaintyNsps;
+    out.hwClockDiscontinuityCount = in.hwClockDiscontinuityCount;
+}
+
+static void convertGnssClock_2_1(GnssMeasurementsClock& in,
+        V2_1::IGnssMeasurementCallback::GnssClock& out)
+{
+    memset(&out, 0, sizeof(out));
+    convertGnssClock(in, out.v1_0);
+    convertGnssConstellationType(in.referenceSignalTypeForIsb.svType,
+            out.referenceSignalTypeForIsb.constellation);
+    out.referenceSignalTypeForIsb.carrierFrequencyHz =
+            in.referenceSignalTypeForIsb.carrierFrequencyHz;
+    convertGnssMeasurementsCodeType(in.referenceSignalTypeForIsb.codeType,
+            in.referenceSignalTypeForIsb.otherCodeTypeName,
+            out.referenceSignalTypeForIsb.codeType);
+}
+
+static void convertGnssData(GnssMeasurementsNotification& in,
+        V1_0::IGnssMeasurementCallback::GnssData& out)
+{
+    memset(&out, 0, sizeof(out));
+    out.measurementCount = in.count;
+    if (out.measurementCount > static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT)) {
+        LOC_LOGW("%s]: Too many measurement %u. Clamps to %d.",
+                __FUNCTION__,  out.measurementCount, V1_0::GnssMax::SVS_COUNT);
+        out.measurementCount = static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT);
+    }
+    for (size_t i = 0; i < out.measurementCount; i++) {
+        convertGnssMeasurement(in.measurements[i], out.measurements[i]);
+    }
+    convertGnssClock(in.clock, out.clock);
+}
+
+static void convertGnssData_1_1(GnssMeasurementsNotification& in,
+        V1_1::IGnssMeasurementCallback::GnssData& out)
+{
+    memset(&out, 0, sizeof(out));
+    out.measurements.resize(in.count);
+    for (size_t i = 0; i < in.count; i++) {
+        convertGnssMeasurement(in.measurements[i], out.measurements[i].v1_0);
+        convertGnssMeasurementsAccumulatedDeltaRangeState(in.measurements[i].adrStateMask,
+                out.measurements[i].accumulatedDeltaRangeState);
+    }
+    convertGnssClock(in.clock, out.clock);
+}
+
+static void convertGnssData_2_0(GnssMeasurementsNotification& in,
+        V2_0::IGnssMeasurementCallback::GnssData& out)
+{
+    memset(&out, 0, sizeof(out));
+    out.measurements.resize(in.count);
+    for (size_t i = 0; i < in.count; i++) {
+        convertGnssMeasurement(in.measurements[i], out.measurements[i].v1_1.v1_0);
+        convertGnssConstellationType(in.measurements[i].svType, out.measurements[i].constellation);
+        convertGnssMeasurementsCodeType(in.measurements[i].codeType,
+            in.measurements[i].otherCodeTypeName,
+            out.measurements[i].codeType);
+        convertGnssMeasurementsAccumulatedDeltaRangeState(in.measurements[i].adrStateMask,
+                out.measurements[i].v1_1.accumulatedDeltaRangeState);
+        convertGnssMeasurementsState(in.measurements[i].stateMask, out.measurements[i].state);
+    }
+    convertGnssClock(in.clock, out.clock);
+    convertElapsedRealtimeNanos(in, out.elapsedRealtime);
+}
+
+static void convertGnssMeasurementsCodeType(GnssMeasurementsCodeType& inCodeType,
+        char* inOtherCodeTypeName, ::android::hardware::hidl_string& out)
+{
+    memset(&out, 0, sizeof(out));
+    switch(inCodeType) {
+        case GNSS_MEASUREMENTS_CODE_TYPE_A:
+            out = "A";
+            break;
+        case GNSS_MEASUREMENTS_CODE_TYPE_B:
+            out = "B";
+            break;
+        case GNSS_MEASUREMENTS_CODE_TYPE_C:
+            out = "C";
+            break;
+        case GNSS_MEASUREMENTS_CODE_TYPE_I:
+            out = "I";
+            break;
+        case GNSS_MEASUREMENTS_CODE_TYPE_L:
+            out = "L";
+            break;
+        case GNSS_MEASUREMENTS_CODE_TYPE_M:
+            out = "M";
+            break;
+        case GNSS_MEASUREMENTS_CODE_TYPE_P:
+            out = "P";
+            break;
+        case GNSS_MEASUREMENTS_CODE_TYPE_Q:
+            out = "Q";
+            break;
+        case GNSS_MEASUREMENTS_CODE_TYPE_S:
+            out = "S";
+            break;
+        case GNSS_MEASUREMENTS_CODE_TYPE_W:
+            out = "W";
+            break;
+        case GNSS_MEASUREMENTS_CODE_TYPE_X:
+            out = "X";
+            break;
+        case GNSS_MEASUREMENTS_CODE_TYPE_Y:
+            out = "Y";
+            break;
+        case GNSS_MEASUREMENTS_CODE_TYPE_Z:
+            out = "Z";
+            break;
+        case GNSS_MEASUREMENTS_CODE_TYPE_N:
+            out = "N";
+            break;
+        case GNSS_MEASUREMENTS_CODE_TYPE_OTHER:
+        default:
+            out = inOtherCodeTypeName;
+            break;
+    }
+}
+
+static void convertGnssMeasurementsAccumulatedDeltaRangeState(GnssMeasurementsAdrStateMask& in,
+        ::android::hardware::hidl_bitfield
+                <V1_1::IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState>& out)
+{
+    memset(&out, 0, sizeof(out));
+    if (in & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT)
+        out |= IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID;
+    if (in & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT)
+        out |= IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET;
+    if (in & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT)
+        out |= IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP;
+    if (in & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_HALF_CYCLE_RESOLVED_BIT)
+        out |= IGnssMeasurementCallback::
+                GnssAccumulatedDeltaRangeState::ADR_STATE_HALF_CYCLE_RESOLVED;
+}
+
+static void convertGnssMeasurementsState(GnssMeasurementsStateMask& in,
+        ::android::hardware::hidl_bitfield
+                <V2_0::IGnssMeasurementCallback::GnssMeasurementState>& out)
+{
+    memset(&out, 0, sizeof(out));
+    if (in & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT)
+        out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_CODE_LOCK;
+    if (in & GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT)
+        out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BIT_SYNC;
+    if (in & GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT)
+        out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SUBFRAME_SYNC;
+    if (in & GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT)
+        out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED;
+    if (in & GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT)
+        out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_MSEC_AMBIGUOUS;
+    if (in & GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT)
+        out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SYMBOL_SYNC;
+    if (in & GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT)
+        out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_STRING_SYNC;
+    if (in & GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT)
+        out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED;
+    if (in & GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT)
+        out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_BIT_SYNC;
+    if (in & GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT)
+        out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_SUBFRAME_SYNC;
+    if (in & GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT)
+        out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1BC_CODE_LOCK;
+    if (in & GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT)
+        out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1C_2ND_CODE_LOCK;
+    if (in & GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT)
+        out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1B_PAGE_SYNC;
+    if (in & GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT)
+        out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SBAS_SYNC;
+    if (in & GNSS_MEASUREMENTS_STATE_TOW_KNOWN_BIT)
+        out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_KNOWN;
+    if (in & GNSS_MEASUREMENTS_STATE_GLO_TOD_KNOWN_BIT)
+        out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_KNOWN;
+    if (in & GNSS_MEASUREMENTS_STATE_2ND_CODE_LOCK_BIT)
+        out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_2ND_CODE_LOCK;
+}
+
+static void convertGnssData_2_1(GnssMeasurementsNotification& in,
+        V2_1::IGnssMeasurementCallback::GnssData& out)
+{
+    memset(&out, 0, sizeof(out));
+    out.measurements.resize(in.count);
+    for (size_t i = 0; i < in.count; i++) {
+        out.measurements[i].flags = 0;
+        convertGnssMeasurement(in.measurements[i], out.measurements[i].v2_0.v1_1.v1_0);
+        convertGnssConstellationType(in.measurements[i].svType,
+                out.measurements[i].v2_0.constellation);
+        convertGnssMeasurementsCodeType(in.measurements[i].codeType,
+                in.measurements[i].otherCodeTypeName,
+                out.measurements[i].v2_0.codeType);
+        convertGnssMeasurementsAccumulatedDeltaRangeState(in.measurements[i].adrStateMask,
+                out.measurements[i].v2_0.v1_1.accumulatedDeltaRangeState);
+        convertGnssMeasurementsState(in.measurements[i].stateMask,
+                out.measurements[i].v2_0.state);
+        out.measurements[i].basebandCN0DbHz = in.measurements[i].basebandCarrierToNoiseDbHz;
+
+        if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_SIGNAL_TO_NOISE_RATIO_BIT) {
+            out.measurements[i].flags |=
+                V2_1::IGnssMeasurementCallback::GnssMeasurementFlags::HAS_SNR;
+        }
+        if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_CARRIER_FREQUENCY_BIT) {
+            out.measurements[i].flags |=
+                V2_1::IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_FREQUENCY;
+        }
+        if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_CARRIER_CYCLES_BIT) {
+            out.measurements[i].flags |=
+                V2_1::IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_CYCLES;
+        }
+        if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_BIT) {
+            out.measurements[i].flags |=
+                V2_1::IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE;
+        }
+        if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_UNCERTAINTY_BIT) {
+            out.measurements[i].flags |=
+                V2_1::IGnssMeasurementCallback::
+                        GnssMeasurementFlags::HAS_CARRIER_PHASE_UNCERTAINTY;
+        }
+        if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT) {
+            out.measurements[i].flags |=
+                V2_1::IGnssMeasurementCallback::GnssMeasurementFlags::HAS_AUTOMATIC_GAIN_CONTROL;
+        }
+        if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_FULL_ISB_BIT) {
+            out.measurements[i].fullInterSignalBiasNs = in.measurements[i].fullInterSignalBiasNs;
+            out.measurements[i].flags |=
+                    V2_1::IGnssMeasurementCallback::GnssMeasurementFlags::HAS_FULL_ISB;
+        }
+        if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_FULL_ISB_UNCERTAINTY_BIT) {
+            out.measurements[i].fullInterSignalBiasUncertaintyNs =
+                    in.measurements[i].fullInterSignalBiasUncertaintyNs;
+            out.measurements[i].flags |=
+                    V2_1::IGnssMeasurementCallback::
+                            GnssMeasurementFlags::HAS_FULL_ISB_UNCERTAINTY;
+        }
+        if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_SATELLITE_ISB_BIT) {
+            out.measurements[i].satelliteInterSignalBiasNs =
+                    in.measurements[i].satelliteInterSignalBiasNs;
+            out.measurements[i].flags |=
+                    V2_1::IGnssMeasurementCallback::GnssMeasurementFlags::HAS_SATELLITE_ISB;
+        }
+        if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_SATELLITE_ISB_UNCERTAINTY_BIT) {
+            out.measurements[i].satelliteInterSignalBiasUncertaintyNs =
+                    in.measurements[i].satelliteInterSignalBiasUncertaintyNs;
+            out.measurements[i].flags |=
+                    V2_1::IGnssMeasurementCallback::
+                            GnssMeasurementFlags::HAS_SATELLITE_ISB_UNCERTAINTY;
+        }
+    }
+    convertGnssClock_2_1(in.clock, out.clock);
+    convertElapsedRealtimeNanos(in, out.elapsedRealtime);
+}
+
+static void convertElapsedRealtimeNanos(GnssMeasurementsNotification& in,
+        ::android::hardware::gnss::V2_0::ElapsedRealtime& elapsedRealtime)
+{
+    if (in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_ELAPSED_REAL_TIME_BIT) {
+        elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS;
+        elapsedRealtime.timestampNs = in.clock.elapsedRealTime;
+        elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS;
+        elapsedRealtime.timeUncertaintyNs = in.clock.elapsedRealTimeUnc;
+        LOC_LOGd("elapsedRealtime.timestampNs=%" PRIi64 ""
+                 " elapsedRealtime.timeUncertaintyNs=%" PRIi64 " elapsedRealtime.flags=0x%X",
+                 elapsedRealtime.timestampNs,
+                 elapsedRealtime.timeUncertaintyNs, elapsedRealtime.flags);
+    }
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/android/2.1/location_api/MeasurementAPIClient.h b/android/2.1/location_api/MeasurementAPIClient.h
new file mode 100644
index 0000000..3e8805b
--- /dev/null
+++ b/android/2.1/location_api/MeasurementAPIClient.h
@@ -0,0 +1,96 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation, nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MEASUREMENT_API_CLINET_H
+#define MEASUREMENT_API_CLINET_H
+
+#include <mutex>
+#include <android/hardware/gnss/2.1/IGnssMeasurement.h>
+//#include <android/hardware/gnss/1.1/IGnssMeasurementCallback.h>
+#include <android/hardware/gnss/2.1/IGnssMeasurementCallback.h>
+#include <LocationAPIClientBase.h>
+#include <hidl/Status.h>
+#include <gps_extended_c.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::sp;
+
+class MeasurementAPIClient : public LocationAPIClientBase
+{
+public:
+    MeasurementAPIClient();
+    MeasurementAPIClient(const MeasurementAPIClient&) = delete;
+    MeasurementAPIClient& operator=(const MeasurementAPIClient&) = delete;
+
+    // for GpsMeasurementInterface
+    Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback(
+            const sp<V1_0::IGnssMeasurementCallback>& callback);
+    Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback_1_1(
+            const sp<V1_1::IGnssMeasurementCallback>& callback,
+            GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+            uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS);
+    Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback_2_0(
+            const sp<V2_0::IGnssMeasurementCallback>& callback,
+            GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+            uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS);
+    Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback_2_1(
+            const sp<V2_1::IGnssMeasurementCallback>& callback,
+            GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+            uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS);
+    void measurementClose();
+    Return<IGnssMeasurement::GnssMeasurementStatus> startTracking(
+            GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+            uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS);
+
+    // callbacks we are interested in
+    void onGnssMeasurementsCb(GnssMeasurementsNotification gnssMeasurementsNotification) final;
+
+private:
+    virtual ~MeasurementAPIClient();
+
+    std::mutex mMutex;
+    sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface;
+    sp<V1_1::IGnssMeasurementCallback> mGnssMeasurementCbIface_1_1;
+    sp<V2_0::IGnssMeasurementCallback> mGnssMeasurementCbIface_2_0;
+    sp<V2_1::IGnssMeasurementCallback> mGnssMeasurementCbIface_2_1;
+    bool mTracking;
+    void clearInterfaces();
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+#endif // MEASUREMENT_API_CLINET_H
diff --git a/android/2.1/service.cpp b/android/2.1/service.cpp
new file mode 100755
index 0000000..2788484
--- /dev/null
+++ b/android/2.1/service.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2_0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2_0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.gnss@2.1-service-qti"
+
+#include <android/hardware/gnss/2.1/IGnss.h>
+#include <hidl/LegacySupport.h>
+#include "loc_cfg.h"
+#include "loc_misc_utils.h"
+
+extern "C" {
+#include "vndfwk-detect.h"
+}
+
+#ifdef ARCH_ARM_32
+#define DEFAULT_HW_BINDER_MEM_SIZE 65536
+#endif
+
+using android::hardware::gnss::V2_1::IGnss;
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::registerPassthroughServiceImplementation;
+using android::hardware::joinRpcThreadpool;
+
+using android::status_t;
+using android::OK;
+
+typedef int vendorEnhancedServiceMain(int /* argc */, char* /* argv */ []);
+
+int main() {
+
+    ALOGI("%s", __FUNCTION__);
+
+    int vendorInfo = getVendorEnhancedInfo();
+    bool vendorEnhanced = ( 1 == vendorInfo || 3 == vendorInfo );
+    setVendorEnhanced(vendorEnhanced);
+
+#ifdef ARCH_ARM_32
+    android::hardware::ProcessState::initWithMmapSize((size_t)(DEFAULT_HW_BINDER_MEM_SIZE));
+#endif
+    configureRpcThreadpool(1, true);
+    status_t status;
+
+    status = registerPassthroughServiceImplementation<IGnss>();
+    if (status == OK) {
+    #ifdef LOC_HIDL_VERSION
+        #define VENDOR_ENHANCED_LIB "vendor.qti.gnss@" LOC_HIDL_VERSION "-service.so"
+
+        void* libHandle = NULL;
+        vendorEnhancedServiceMain* vendorEnhancedMainMethod = (vendorEnhancedServiceMain*)
+                dlGetSymFromLib(libHandle, VENDOR_ENHANCED_LIB, "main");
+        if (NULL != vendorEnhancedMainMethod) {
+            (*vendorEnhancedMainMethod)(0, NULL);
+        }
+    #else
+        ALOGI("LOC_HIDL_VERSION not defined.");
+    #endif
+
+        joinRpcThreadpool();
+
+    } else {
+        ALOGE("Error while registering IGnss 2.1 service: %d", status);
+    }
+
+    return 0;
+}
diff --git a/android/Android.mk b/android/Android.mk
index 3b5c01f..aa2f4b5 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -1,15 +1,2 @@
 LOCAL_PATH := $(call my-dir)
-ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),)
-include $(CLEAR_VARS)
-DIR_LIST := $(LOCAL_PATH)
-include $(DIR_LIST)/utils/Android.mk
-ifeq ($(GNSS_HIDL_VERSION),2.0)
-include $(DIR_LIST)/2.0/Android.mk
-else
-ifeq ($(GNSS_HIDL_VERSION),1.1)
-include $(DIR_LIST)/1.1/Android.mk
-else
-include $(DIR_LIST)/1.0/Android.mk
-endif #GNSS HIDL 1.1
-endif #GNSS HIDL 2.0
-endif #BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE
+include $(call all-subdir-makefiles)
diff --git a/android/utils/Android.bp b/android/utils/Android.bp
new file mode 100644
index 0000000..dcbff22
--- /dev/null
+++ b/android/utils/Android.bp
@@ -0,0 +1,46 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_qcom_sm7250_gps_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-BSD
+    default_applicable_licenses: ["hardware_qcom_sm7250_gps_license"],
+}
+
+cc_library_static {
+
+    name: "liblocbatterylistener",
+    vendor: true,
+
+
+
+    cflags: GNSS_CFLAGS + ["-DBATTERY_LISTENER_ENABLED"],
+    local_include_dirs: ["."],
+
+    srcs: ["battery_listener.cpp"],
+
+    shared_libs: [
+        "liblog",
+        "libhidlbase",
+        "libcutils",
+        "libutils",
+        "android.hardware.health@1.0",
+        "android.hardware.health@2.0",
+        "android.hardware.health@2.1",
+        "android.hardware.power@1.2",
+        "libbase",
+    ],
+
+    static_libs: ["libhealthhalutils"],
+
+    header_libs: [
+        "libgps.utils_headers",
+        "libloc_pla_headers",
+    ],
+}
+
+cc_library_headers {
+
+    name: "liblocbatterylistener_headers",
+    export_include_dirs: ["."],
+}
diff --git a/android/utils/Android.mk b/android/utils/Android.mk
deleted file mode 100644
index 9cb6f7b..0000000
--- a/android/utils/Android.mk
+++ /dev/null
@@ -1,41 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := liblocbatterylistener
-LOCAL_SANITIZE += $(GNSS_SANITIZE)
-# activate the following line for debug purposes only, comment out for production
-#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
-LOCAL_VENDOR_MODULE := true
-
-LOCAL_CFLAGS += $(GNSS_CFLAGS)
-
-LOCAL_C_INCLUDES += \
-    $(LOCAL_PATH) \
-
-LOCAL_SRC_FILES:= \
-    battery_listener.cpp
-LOCAL_SHARED_LIBRARIES := \
-    liblog \
-    libhidlbase \
-    libcutils \
-    libutils \
-    android.hardware.health@1.0 \
-    android.hardware.health@2.0 \
-    android.hardware.power@1.2 \
-    libbase
-
-LOCAL_HEADER_LIBRARIES := \
-    libgps.utils_headers \
-
-LOCAL_STATIC_LIBRARIES := libhealthhalutils
-LOCAL_CFLAGS += -DBATTERY_LISTENER_ENABLED
-
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := liblocbatterylistener_headers
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-
-include $(BUILD_HEADER_LIBRARY)
-
-
diff --git a/android/utils/battery_listener.cpp b/android/utils/battery_listener.cpp
index 8547e41..9cbfabd 100644
--- a/android/utils/battery_listener.cpp
+++ b/android/utils/battery_listener.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2019, The Linux Foundation. All rights reserved.
+* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -34,7 +34,8 @@
 #define LOG_NDEBUG 0
 
 #include <android/hidl/manager/1.0/IServiceManager.h>
-#include <android/hardware/health/2.0/IHealth.h>
+#include <android/hardware/health/2.1/IHealth.h>
+#include <android/hardware/health/2.1/IHealthInfoCallback.h>
 #include <healthhalutils/HealthHalUtils.h>
 #include <hidl/HidlTransportSupport.h>
 #include <thread>
@@ -44,10 +45,9 @@
 using android::hardware::Return;
 using android::hardware::Void;
 using android::hardware::health::V1_0::BatteryStatus;
-using android::hardware::health::V1_0::toString;
-using android::hardware::health::V2_0::get_health_service;
-using android::hardware::health::V2_0::HealthInfo;
-using android::hardware::health::V2_0::IHealth;
+using android::hardware::health::V2_1::HealthInfo;
+using android::hardware::health::V2_1::IHealthInfoCallback;
+using android::hardware::health::V2_1::IHealth;
 using android::hardware::health::V2_0::Result;
 using android::hidl::manager::V1_0::IServiceManager;
 using namespace std::literals::chrono_literals;
@@ -58,13 +58,15 @@
 #define GET_HEALTH_SVC_RETRY_CNT 5
 #define GET_HEALTH_SVC_WAIT_TIME_MS 500
 
-struct BatteryListenerImpl : public hardware::health::V2_0::IHealthInfoCallback,
+struct BatteryListenerImpl : public hardware::health::V2_1::IHealthInfoCallback,
                              public hardware::hidl_death_recipient {
     typedef std::function<void(bool)> cb_fn_t;
     BatteryListenerImpl(cb_fn_t cb);
     virtual ~BatteryListenerImpl ();
     virtual hardware::Return<void> healthInfoChanged(
-        const hardware::health::V2_0::HealthInfo& info);
+            const hardware::health::V2_0::HealthInfo& info);
+    virtual hardware::Return<void> healthInfoChanged_2_1(
+            const hardware::health::V2_1::HealthInfo& info);
     virtual void serviceDied(uint64_t cookie,
                              const wp<hidl::base::V1_0::IBase>& who);
     bool isCharging() {
@@ -72,7 +74,7 @@
         return statusToBool(mStatus);
     }
   private:
-    sp<hardware::health::V2_0::IHealth> mHealth;
+    sp<hardware::health::V2_1::IHealth> mHealth;
     status_t init();
     BatteryStatus mStatus;
     cb_fn_t mCb;
@@ -94,7 +96,7 @@
         return INVALID_OPERATION;
 
     do {
-        mHealth = hardware::health::V2_0::get_health_service();
+        mHealth = IHealth::getService();
         if (mHealth != NULL)
             break;
         usleep(GET_HEALTH_SVC_WAIT_TIME_MS * 1000);
@@ -183,7 +185,7 @@
     {
         std::lock_guard<std::mutex> _l(mLock);
         if (mHealth != NULL)
-            mHealth->unlinkToDeath(this);
+            mHealth->unregisterCallback(this);
             auto r = mHealth->unlinkToDeath(this);
             if (!r.isOk() || r == false) {
                 LOC_LOGe("Transaction error in unregister to HealthHAL death: %s",
@@ -206,6 +208,8 @@
         LOC_LOGi("health service died, reinit");
         mDone = true;
     }
+    mHealth = NULL;
+    mCond.notify_one();
     mThread->join();
     std::lock_guard<std::mutex> _l(mLock);
     init();
@@ -227,6 +231,13 @@
     return Void();
 }
 
+Return<void> BatteryListenerImpl::healthInfoChanged_2_1(
+        const hardware::health::V2_1::HealthInfo& info) {
+    LOC_LOGv("healthInfoChanged_2_1: %d", info.legacy.legacy.batteryStatus);
+    healthInfoChanged(info.legacy);
+    return Void();
+}
+
 static sp<BatteryListenerImpl> batteryListener;
 
 bool batteryPropertiesListenerIsCharging() {
@@ -251,6 +262,7 @@
 } // namespace android
 
 void loc_extn_battery_properties_listener_init(battery_status_change_fn_t fn) {
+    LOC_LOGv("loc_extn_battery_properties_listener_init entry");
     if (!sIsBatteryListened) {
         std::thread t1(android::batteryPropertiesListenerInit,
                 [=](bool charging) { fn(charging); });
diff --git a/batching/Android.bp b/batching/Android.bp
new file mode 100644
index 0000000..7b1f8ba
--- /dev/null
+++ b/batching/Android.bp
@@ -0,0 +1,40 @@
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_qcom_sm7250_gps_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-BSD
+    default_applicable_licenses: ["hardware_qcom_sm7250_gps_license"],
+}
+
+cc_library_shared {
+
+    name: "libbatching",
+    vendor: true,
+
+
+
+    shared_libs: [
+        "libutils",
+        "libcutils",
+        "liblog",
+        "libloc_core",
+        "libgps.utils",
+        "libdl",
+    ],
+
+    srcs: [
+        "location_batching.cpp",
+        "BatchingAdapter.cpp",
+    ],
+
+    header_libs: [
+        "libgps.utils_headers",
+        "libloc_core_headers",
+        "libloc_pla_headers",
+        "liblocation_api_headers",
+    ],
+
+    cflags: GNSS_CFLAGS,
+}
diff --git a/batching/Android.mk b/batching/Android.mk
deleted file mode 100644
index f3e8fe4..0000000
--- a/batching/Android.mk
+++ /dev/null
@@ -1,39 +0,0 @@
-ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),)
-ifneq ($(BUILD_TINY_ANDROID),true)
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libbatching
-LOCAL_SANITIZE += $(GNSS_SANITIZE)
-# activate the following line for debug purposes only, comment out for production
-#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SHARED_LIBRARIES := \
-    libutils \
-    libcutils \
-    liblog \
-    libloc_core \
-    libgps.utils \
-    libdl
-
-LOCAL_SRC_FILES += \
-    location_batching.cpp \
-    BatchingAdapter.cpp
-
-LOCAL_HEADER_LIBRARIES := \
-    libgps.utils_headers \
-    libloc_core_headers \
-    libloc_pla_headers \
-    liblocation_api_headers
-
-LOCAL_PRELINK_MODULE := false
-
-LOCAL_CFLAGS += $(GNSS_CFLAGS)
-include $(BUILD_SHARED_LIBRARY)
-
-endif # not BUILD_TINY_ANDROID
-endif # BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE
diff --git a/batching/BatchingAdapter.cpp b/batching/BatchingAdapter.cpp
index 135f0ed..4f1a43c 100644
--- a/batching/BatchingAdapter.cpp
+++ b/batching/BatchingAdapter.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -38,11 +38,8 @@
 
 BatchingAdapter::BatchingAdapter() :
     LocAdapterBase(0,
-                    LocContext::getLocContext(
-                        NULL,
-                        NULL,
-                        LocContext::mLocationHalName,
-                        false)),
+                   LocContext::getLocContext(LocContext::mLocationHalName),
+                   false, nullptr, true),
     mOngoingTripDistance(0),
     mOngoingTripTBFInterval(0),
     mTripWithOngoingTBFDropped(false),
@@ -55,6 +52,10 @@
     LOC_LOGD("%s]: Constructor", __func__);
     readConfigCommand();
     setConfigCommand();
+
+    // at last step, let us inform adapater base that we are done
+    // with initialization, e.g.: ready to process handleEngineUpEvent
+    doneInit();
 }
 
 void
diff --git a/batching/Makefile.am b/batching/Makefile.am
index ef8011e..d5cba39 100644
--- a/batching/Makefile.am
+++ b/batching/Makefile.am
@@ -22,8 +22,7 @@
 
 if USE_GLIB
 libbatching_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@
-#libbatching_la_LDFLAGS = -lstdc++ -g -Wl,-z,defs -lpthread $(requiredlibs) @GLIB_LIBS@ -shared -avoid-version
-libbatching_la_LDFLAGS = -lstdc++ -g -Wl,-z,defs -lpthread $(requiredlibs) @GLIB_LIBS@ -avoid-version
+libbatching_la_LDFLAGS = -lstdc++ -g -Wl,-z,defs -lpthread $(requiredlibs) @GLIB_LIBS@ -shared -version-info 1:0:0
 libbatching_la_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@
 else
 libbatching_la_CFLAGS = $(AM_CFLAGS)
diff --git a/batching/configure.ac b/batching/configure.ac
index 27435c6..4ca4998 100644
--- a/batching/configure.ac
+++ b/batching/configure.ac
@@ -7,7 +7,7 @@
 # Initialize the gps location-batching package version 1.0.0
 AC_INIT([location-batching],1.0.0)
 # Does not strictly follow GNU Coding standards
-AM_INIT_AUTOMAKE([foreign])
+AM_INIT_AUTOMAKE([foreign subdir-objects])
 # Disables auto rebuilding of configure, Makefile.ins
 AM_MAINTAINER_MODE
 # Verifies the --srcdir is correct by checking for the path
@@ -37,10 +37,6 @@
 AC_SUBST([LOCCORE_CFLAGS])
 AC_SUBST([LOCCORE_LIBS])
 
-PKG_CHECK_MODULES([GEOFENCE], [location-geofence])
-AC_SUBST([GEOFENCE_CFLAGS])
-AC_SUBST([GEOFENCE_LIBS])
-
 AC_ARG_WITH([locpla_includes],
       AC_HELP_STRING([--with-locpla-includes=@<:@dir@:>@],
          [specify the path to locpla-includes in loc-pla_git.bb]),
diff --git a/build/target_specific_features.mk b/build/target_specific_features.mk
deleted file mode 100644
index bdccbbf..0000000
--- a/build/target_specific_features.mk
+++ /dev/null
@@ -1,73 +0,0 @@
-GNSS_CFLAGS := \
-    -Werror \
-    -Wno-error=unused-parameter \
-    -Wno-error=macro-redefined \
-    -Wno-error=reorder \
-    -Wno-error=missing-braces \
-    -Wno-error=self-assign \
-    -Wno-error=enum-conversion \
-    -Wno-error=logical-op-parentheses \
-    -Wno-error=null-arithmetic \
-    -Wno-error=null-conversion \
-    -Wno-error=parentheses-equality \
-    -Wno-error=undefined-bool-conversion \
-    -Wno-error=tautological-compare \
-    -Wno-error=switch \
-    -Wno-error=date-time
-
-# GPS-HIDL
-GNSS_HIDL_1_0_TARGET_LIST := msm8960
-GNSS_HIDL_1_0_TARGET_LIST += msm8974
-GNSS_HIDL_1_0_TARGET_LIST += msm8226
-GNSS_HIDL_1_0_TARGET_LIST += msm8610
-GNSS_HIDL_1_0_TARGET_LIST += apq8084
-GNSS_HIDL_1_0_TARGET_LIST += msm8916
-GNSS_HIDL_1_0_TARGET_LIST += msm8994
-GNSS_HIDL_1_0_TARGET_LIST += msm8909
-GNSS_HIDL_1_0_TARGET_LIST += msm8952
-GNSS_HIDL_1_0_TARGET_LIST += msm8992
-GNSS_HIDL_1_0_TARGET_LIST += msm8996
-GNSS_HIDL_2_0_TARGET_LIST := msm8937
-GNSS_HIDL_2_0_TARGET_LIST += msm8953
-GNSS_HIDL_2_0_TARGET_LIST += msm8998
-GNSS_HIDL_2_0_TARGET_LIST += apq8098_latv
-GNSS_HIDL_2_0_TARGET_LIST += sdm710
-GNSS_HIDL_2_0_TARGET_LIST += qcs605
-GNSS_HIDL_2_0_TARGET_LIST += sdm845
-GNSS_HIDL_2_0_TARGET_LIST += sdm660
-GNSS_HIDL_2_0_TARGET_LIST += msmnile
-GNSS_HIDL_2_0_TARGET_LIST += sdmshrike
-GNSS_HIDL_2_0_TARGET_LIST += $(MSMSTEPPE)
-GNSS_HIDL_2_0_TARGET_LIST += $(TRINKET)
-GNSS_HIDL_2_0_TARGET_LIST += kona
-GNSS_HIDL_2_0_TARGET_LIST += atoll
-GNSS_HIDL_2_0_TARGET_LIST += lito
-GNSS_HIDL_2_0_TARGET_LIST += bengal
-GNSS_HIDL_2_0_TARGET_LIST += lahaina
-
-ifneq (,$(filter $(GNSS_HIDL_2_0_TARGET_LIST),$(TARGET_BOARD_PLATFORM)))
-GNSS_HIDL_VERSION = 2.0
-else ifneq (,$(filter $(GNSS_HIDL_1_0_TARGET_LIST),$(TARGET_BOARD_PLATFORM)))
-GNSS_HIDL_VERSION = 1.0
-else ifneq (,$(filter $(GNSS_HIDL_1_1_TARGET_LIST),$(TARGET_BOARD_PLATFORM)))
-GNSS_HIDL_VERSION = 1.1
-else # default to 2.0
-GNSS_HIDL_VERSION = 2.0
-endif
-
-GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST := msm8937
-GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += msm8953
-GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += msm8998
-GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += apq8098_latv
-GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += sdm710
-GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += qcs605
-GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += sdm845
-GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += sdm660
-
-ifneq (,$(filter $(GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST),$(TARGET_BOARD_PLATFORM)))
-GNSS_HIDL_LEGACY_MEASURMENTS = true
-endif
-
-# Activate the following two lines for regression testing
-#GNSS_SANITIZE := address cfi alignment bounds null unreachable integer
-#GNSS_SANITIZE_DIAG := address cfi alignment bounds null unreachable integer
diff --git a/core/Android.bp b/core/Android.bp
new file mode 100644
index 0000000..2d9a804
--- /dev/null
+++ b/core/Android.bp
@@ -0,0 +1,65 @@
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_qcom_sm7250_gps_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-BSD
+    default_applicable_licenses: ["hardware_qcom_sm7250_gps_license"],
+}
+
+cc_library_shared {
+
+    name: "libloc_core",
+    vendor: true,
+
+
+
+    shared_libs: [
+        "liblog",
+        "libutils",
+        "libcutils",
+        "libgps.utils",
+        "libdl",
+        "liblog",
+    ],
+
+    srcs: [
+        "LocApiBase.cpp",
+        "LocAdapterBase.cpp",
+        "ContextBase.cpp",
+        "LocContext.cpp",
+        "loc_core_log.cpp",
+        "data-items/DataItemsFactoryProxy.cpp",
+        "SystemStatusOsObserver.cpp",
+        "SystemStatus.cpp",
+    ],
+
+    cflags: [
+        "-fno-short-enums",
+        "-D_ANDROID_",
+    ] + GNSS_CFLAGS,
+
+    local_include_dirs: [
+        "data-items",
+        "observer",
+    ],
+
+    header_libs: [
+        "libutils_headers",
+        "libgps.utils_headers",
+        "libloc_pla_headers",
+        "liblocation_api_headers",
+    ],
+
+}
+
+cc_library_headers {
+
+    name: "libloc_core_headers",
+    vendor: true,
+    export_include_dirs: ["."] + [
+        "data-items",
+        "observer",
+    ],
+}
diff --git a/core/Android.mk b/core/Android.mk
deleted file mode 100644
index ce5d6a8..0000000
--- a/core/Android.mk
+++ /dev/null
@@ -1,62 +0,0 @@
-ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),)
-ifneq ($(BUILD_TINY_ANDROID),true)
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libloc_core
-LOCAL_SANITIZE += $(GNSS_SANITIZE)
-# activate the following line for debug purposes only, comment out for production
-#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SHARED_LIBRARIES := \
-    liblog \
-    libutils \
-    libcutils \
-    libgps.utils \
-    libdl \
-    liblog
-
-LOCAL_SRC_FILES += \
-    LocApiBase.cpp \
-    LocAdapterBase.cpp \
-    ContextBase.cpp \
-    LocContext.cpp \
-    loc_core_log.cpp \
-    data-items/DataItemsFactoryProxy.cpp \
-    SystemStatusOsObserver.cpp \
-    SystemStatus.cpp
-
-LOCAL_CFLAGS += \
-     -fno-short-enums \
-     -D_ANDROID_
-
-LOCAL_C_INCLUDES:= \
-    $(LOCAL_PATH)/data-items \
-    $(LOCAL_PATH)/data-items/common \
-    $(LOCAL_PATH)/observer \
-
-LOCAL_HEADER_LIBRARIES := \
-    libutils_headers \
-    libgps.utils_headers \
-    libloc_pla_headers \
-    liblocation_api_headers
-
-LOCAL_CFLAGS += $(GNSS_CFLAGS)
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libloc_core_headers
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
-    $(LOCAL_PATH) \
-    $(LOCAL_PATH)/data-items \
-    $(LOCAL_PATH)/data-items/common \
-    $(LOCAL_PATH)/observer
-include $(BUILD_HEADER_LIBRARY)
-
-endif # not BUILD_TINY_ANDROID
-endif # BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE
diff --git a/core/ContextBase.cpp b/core/ContextBase.cpp
index 3eb4973..87e98dc 100644
--- a/core/ContextBase.cpp
+++ b/core/ContextBase.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2014,2016-2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014,2016-2017,2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -30,7 +30,6 @@
 #define LOG_TAG "LocSvc_CtxBase"
 
 #include <dlfcn.h>
-#include <cutils/sched_policy.h>
 #include <unistd.h>
 #include <ContextBase.h>
 #include <msg_q.h>
@@ -50,6 +49,8 @@
 uint64_t ContextBase::sSupportedMsgMask = 0;
 bool ContextBase::sGnssMeasurementSupported = false;
 uint8_t ContextBase::sFeaturesSupported[MAX_FEATURE_LENGTH];
+GnssNMEARptRate ContextBase::sNmeaReportRate = GNSS_NMEA_REPORT_RATE_NHZ;
+LocationCapabilitiesMask ContextBase::sQwesFeatureMask = 0;
 
 const loc_param_s_type ContextBase::mGps_conf_table[] =
 {
@@ -65,8 +66,8 @@
   {"INTERMEDIATE_POS",               &mGps_conf.INTERMEDIATE_POS,               NULL, 'n'},
   {"ACCURACY_THRES",                 &mGps_conf.ACCURACY_THRES,                 NULL, 'n'},
   {"NMEA_PROVIDER",                  &mGps_conf.NMEA_PROVIDER,                  NULL, 'n'},
+  {"NMEA_REPORT_RATE",               &mGps_conf.NMEA_REPORT_RATE,               NULL, 's'},
   {"CAPABILITIES",                   &mGps_conf.CAPABILITIES,                   NULL, 'n'},
-  {"XTRA_VERSION_CHECK",             &mGps_conf.XTRA_VERSION_CHECK,             NULL, 'n'},
   {"XTRA_SERVER_1",                  &mGps_conf.XTRA_SERVER_1,                  NULL, 's'},
   {"XTRA_SERVER_2",                  &mGps_conf.XTRA_SERVER_2,                  NULL, 's'},
   {"XTRA_SERVER_3",                  &mGps_conf.XTRA_SERVER_3,                  NULL, 's'},
@@ -92,7 +93,9 @@
   {"GNSS_DEPLOYMENT",  &mGps_conf.GNSS_DEPLOYMENT, NULL, 'n'},
   {"CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED",
            &mGps_conf.CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED, NULL, 'n'},
+  {"NMEA_TAG_BLOCK_GROUPING_ENABLED", &mGps_conf.NMEA_TAG_BLOCK_GROUPING_ENABLED, NULL, 'n'},
   {"NI_SUPL_DENY_ON_NFW_LOCKED",  &mGps_conf.NI_SUPL_DENY_ON_NFW_LOCKED, NULL, 'n'},
+  {"ENABLE_NMEA_PRINT",  &mGps_conf.ENABLE_NMEA_PRINT, NULL, 'n'}
 };
 
 const loc_param_s_type ContextBase::mSap_conf_table[] =
@@ -135,8 +138,6 @@
         mGps_conf.LPP_PROFILE = 0;
         /*By default no positioning protocol is selected on A-GLONASS system*/
         mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT = 0;
-        /*XTRA version check is disabled by default*/
-        mGps_conf.XTRA_VERSION_CHECK=0;
         /*Use emergency PDN by default*/
         mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL = 1;
         /* By default no LPPe CP technology is enabled*/
@@ -192,12 +193,22 @@
         /* default configuration QTI GNSS H/W */
         mGps_conf.GNSS_DEPLOYMENT = 0;
         mGps_conf.CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED = 0;
+        /* default NMEA Tag Block Grouping is disabled */
+        mGps_conf.NMEA_TAG_BLOCK_GROUPING_ENABLED = 0;
         /* default configuration for NI_SUPL_DENY_ON_NFW_LOCKED */
         mGps_conf.NI_SUPL_DENY_ON_NFW_LOCKED = 1;
+        /* By default NMEA Printing is disabled */
+        mGps_conf.ENABLE_NMEA_PRINT = 0;
 
         UTIL_READ_CONF(LOC_PATH_GPS_CONF, mGps_conf_table);
         UTIL_READ_CONF(LOC_PATH_SAP_CONF, mSap_conf_table);
 
+        if (strncmp(mGps_conf.NMEA_REPORT_RATE, "1HZ", sizeof(mGps_conf.NMEA_REPORT_RATE)) == 0) {
+            /* NMEA reporting is configured at 1Hz*/
+            sNmeaReportRate = GNSS_NMEA_REPORT_RATE_1HZ;
+        } else {
+            sNmeaReportRate = GNSS_NMEA_REPORT_RATE_NHZ;
+        }
         LOC_LOGI("%s] GNSS Deployment: %s", __FUNCTION__,
                 ((mGps_conf.GNSS_DEPLOYMENT == 1) ? "SS5" :
                 ((mGps_conf.GNSS_DEPLOYMENT == 2) ? "QFUSION" : "QGNSS")));
@@ -326,6 +337,32 @@
                     (void *)featureList, sizeof(ContextBase::sFeaturesSupported));
         }
 
+        /* */
+        if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_MEASUREMENTS_CORRECTION)) {
+            static uint8_t isSapModeKnown = 0;
+
+            if (!isSapModeKnown) {
+                /* Check if SAP is PREMIUM_ENV_AIDING in izat.conf */
+                char conf_feature_sap[LOC_MAX_PARAM_STRING];
+                loc_param_s_type izat_conf_feature_table[] =
+                {
+                    { "SAP",           &conf_feature_sap,           &isSapModeKnown, 's' }
+                };
+                UTIL_READ_CONF(LOC_PATH_IZAT_CONF, izat_conf_feature_table);
+
+                /* Disable this feature if SAP is not PREMIUM_ENV_AIDING in izat.conf */
+                if (strcmp(conf_feature_sap, "PREMIUM_ENV_AIDING") != 0) {
+                    uint8_t arrayIndex = LOC_SUPPORTED_FEATURE_MEASUREMENTS_CORRECTION >> 3;
+                    uint8_t bitPos = LOC_SUPPORTED_FEATURE_MEASUREMENTS_CORRECTION & 7;
+
+                    if (arrayIndex < MAX_FEATURE_LENGTH) {
+                        /* To disable the feature we need to reset the bit on the "bitPos"
+                           position, so shift a "1" to the left by "bitPos" */
+                        ContextBase::sFeaturesSupported[arrayIndex] &= ~(1 << bitPos);
+                    }
+                }
+            }
+        }
         ContextBase::sIsEngineCapabilitiesKnown = true;
     }
 }
diff --git a/core/ContextBase.h b/core/ContextBase.h
index e63450f..34cad60 100644
--- a/core/ContextBase.h
+++ b/core/ContextBase.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2017, 2020, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -35,6 +35,11 @@
 #include <LocApiBase.h>
 #include <LBSProxyBase.h>
 #include <loc_cfg.h>
+#ifdef NO_UNORDERED_SET_OR_MAP
+    #include <map>
+#else
+    #include <unordered_map>
+#endif
 
 /* GPS.conf support */
 /* NOTE: the implementaiton of the parser casts number
@@ -49,12 +54,12 @@
     uint32_t       SUPL_ES;
     uint32_t       CAPABILITIES;
     uint32_t       LPP_PROFILE;
-    uint32_t       XTRA_VERSION_CHECK;
     char           XTRA_SERVER_1[LOC_MAX_PARAM_STRING];
     char           XTRA_SERVER_2[LOC_MAX_PARAM_STRING];
     char           XTRA_SERVER_3[LOC_MAX_PARAM_STRING];
     uint32_t       USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL;
     uint32_t       NMEA_PROVIDER;
+    char           NMEA_REPORT_RATE[LOC_MAX_PARAM_NAME];
     GnssConfigGpsLock   GPS_LOCK;
     uint32_t       A_GLONASS_POS_PROTOCOL_SELECT;
     uint32_t       AGPS_CERT_WRITABLE_MASK;
@@ -76,15 +81,17 @@
     uint32_t       GNSS_DEPLOYMENT;
     uint32_t       CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED;
     uint32_t       NI_SUPL_DENY_ON_NFW_LOCKED;
+    uint32_t       ENABLE_NMEA_PRINT;
+    uint32_t       NMEA_TAG_BLOCK_GROUPING_ENABLED;
 } loc_gps_cfg_s_type;
 
-/* NOTE: the implementaiton of the parser casts number
+/* NOTE: the implementation of the parser casts number
    fields to 32 bit. To ensure all 'n' fields working,
    they must all be 32 bit fields. */
 /* Meanwhile, *_valid fields are 8 bit fields, and 'f'
    fields are double. Rigid as they are, it is the
    the status quo, until the parsing mechanism is
-   change, that is. */
+   changed, that is. */
 typedef struct
 {
     uint8_t        GYRO_BIAS_RANDOM_WALK_VALID;
@@ -109,6 +116,8 @@
     double         VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY;
 } loc_sap_cfg_s_type;
 
+using namespace loc_util;
+
 namespace loc_core {
 
 class LocAdapterBase;
@@ -156,6 +165,8 @@
     static uint64_t sSupportedMsgMask;
     static uint8_t sFeaturesSupported[MAX_FEATURE_LENGTH];
     static bool sGnssMeasurementSupported;
+    static GnssNMEARptRate sNmeaReportRate;
+    static LocationCapabilitiesMask sQwesFeatureMask;
 
     void readConfig();
     static uint32_t getCarrierCapabilities();
@@ -188,6 +199,118 @@
     */
     static bool gnssConstellationConfig();
 
+    /*
+        set QWES feature status info
+    */
+    static inline void setQwesFeatureStatus(
+            const std::unordered_map<LocationQwesFeatureType, bool> &featureMap) {
+       std::unordered_map<LocationQwesFeatureType, bool>::const_iterator itr;
+       static LocationQwesFeatureType locQwesFeatType[LOCATION_QWES_FEATURE_TYPE_MAX];
+       for (itr = featureMap.begin(); itr != featureMap.end(); ++itr) {
+           LOC_LOGi("Feature : %d isValid: %d", itr->first, itr->second);
+           locQwesFeatType[itr->first] = itr->second;
+           switch (itr->first) {
+               case LOCATION_QWES_FEATURE_TYPE_CARRIER_PHASE:
+                   if (itr->second) {
+                       sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_CARRIER_PHASE_BIT;
+                   } else {
+                       sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_CARRIER_PHASE_BIT;
+                   }
+               break;
+               case LOCATION_QWES_FEATURE_TYPE_SV_POLYNOMIAL:
+                   if (itr->second) {
+                       sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_SV_POLYNOMIAL_BIT;
+                   } else {
+                       sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_SV_POLYNOMIAL_BIT;
+                   }
+               break;
+               case LOCATION_QWES_FEATURE_TYPE_GNSS_SINGLE_FREQUENCY:
+                   if (itr->second) {
+                       sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_GNSS_SINGLE_FREQUENCY;
+                   } else {
+                       sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_GNSS_SINGLE_FREQUENCY;
+                   }
+               break;
+               case LOCATION_QWES_FEATURE_TYPE_SV_EPH:
+                   if (itr->second) {
+                       sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_SV_EPHEMERIS_BIT;
+                   } else {
+                       sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_SV_EPHEMERIS_BIT;
+                   }
+               break;
+               case LOCATION_QWES_FEATURE_TYPE_GNSS_MULTI_FREQUENCY:
+                   if (itr->second) {
+                       sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_GNSS_MULTI_FREQUENCY;
+                   } else {
+                       sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_GNSS_MULTI_FREQUENCY;
+                   }
+               break;
+               case LOCATION_QWES_FEATURE_TYPE_PPE:
+                   if (itr->second) {
+                       sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_PPE;
+                   } else {
+                       sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_PPE;
+                   }
+               break;
+               case LOCATION_QWES_FEATURE_TYPE_QDR2:
+                   if (itr->second) {
+                       sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_QDR2;
+                   } else {
+                       sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_QDR2;
+                   }
+               break;
+               case LOCATION_QWES_FEATURE_TYPE_QDR3:
+                   if (itr->second) {
+                       sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_QDR3;
+                   } else {
+                       sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_QDR3;
+                   }
+               break;
+               case LOCATION_QWES_FEATURE_TYPE_VPE:
+                   if (itr->second) {
+                       sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_VPE;
+                   } else {
+                       sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_VPE;
+                   }
+               break;
+           }
+       }
+
+       // Set CV2X basic when time freq and tunc is set
+       // CV2X_BASIC  = LOCATION_QWES_FEATURE_TYPE_TIME_FREQUENCY &
+       //       LOCATION_QWES_FEATURE_TYPE_TIME_UNCERTAINTY
+
+       // Set CV2X premium when time freq and tunc is set
+       // CV2X_PREMIUM = CV2X_BASIC & LOCATION_QWES_FEATURE_TYPE_QDR3 &
+       //       LOCATION_QWES_FEATURE_TYPE_CLOCK_ESTIMATE
+
+       bool cv2xBasicEnabled = (1 == locQwesFeatType[LOCATION_QWES_FEATURE_TYPE_TIME_FREQUENCY]) &&
+            (1 == locQwesFeatType[LOCATION_QWES_FEATURE_TYPE_TIME_UNCERTAINTY]);
+       bool cv2xPremiumEnabled = cv2xBasicEnabled &&
+            (1 == locQwesFeatType[LOCATION_QWES_FEATURE_TYPE_QDR3]) &&
+            (1 == locQwesFeatType[LOCATION_QWES_FEATURE_TYPE_CLOCK_ESTIMATE]);
+
+       LOC_LOGd("CV2X_BASIC:%d, CV2X_PREMIUM:%d", cv2xBasicEnabled, cv2xPremiumEnabled);
+       if (cv2xBasicEnabled) {
+            sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_CV2X_LOCATION_BASIC;
+       } else {
+            sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_CV2X_LOCATION_BASIC;
+       }
+       if (cv2xPremiumEnabled) {
+            sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_CV2X_LOCATION_PREMIUM;
+       } else {
+            sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_CV2X_LOCATION_PREMIUM;
+       }
+    }
+
+    /*
+        get QWES feature status info
+    */
+    static inline LocationCapabilitiesMask getQwesFeatureStatus() {
+        return (ContextBase::sQwesFeatureMask);
+    }
+
+
 };
 
 struct LocApiResponse: LocMsg {
diff --git a/core/EngineHubProxyBase.h b/core/EngineHubProxyBase.h
index d46bca2..468a8f0 100644
--- a/core/EngineHubProxyBase.h
+++ b/core/EngineHubProxyBase.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -28,9 +28,16 @@
  */
 #ifndef ENGINE_HUB_PROXY_BASE_H
 #define ENGINE_HUB_PROXY_BASE_H
+#ifdef NO_UNORDERED_SET_OR_MAP
+    #include <map>
+#else
+    #include <unordered_map>
+#endif
 
 namespace loc_core {
 
+using namespace loc_util;
+
 class EngineHubProxyBase {
 public:
     inline EngineHubProxyBase() {
@@ -106,6 +113,19 @@
         (void) configInfo;
         return false;
     }
+
+    inline virtual bool configDeadReckoningEngineParams(
+            const DeadReckoningEngineConfig& dreConfig) {
+        (void) dreConfig;
+        return false;
+    }
+
+    inline virtual bool configEngineRunState(
+            PositioningEngineMask engType, LocEngineRunState engState) {
+        (void) engType;
+        (void) engState;
+        return false;
+    }
 };
 
 typedef std::function<void(int count, EngineLocationInfo* locationArr)>
@@ -121,6 +141,9 @@
 typedef std::function<void(bool nHzNeeded, bool nHzMeasNeeded)>
         GnssAdapterUpdateNHzRequirementCb;
 
+typedef std::function<void(const std::unordered_map<LocationQwesFeatureType, bool> &featureMap)>
+        GnssAdapterUpdateQwesFeatureStatusCb;
+
 // potential parameters: message queue: MsgTask * msgTask;
 // callback function to report back dr and ppe position and sv report
 typedef EngineHubProxyBase* (getEngHubProxyFn)(
@@ -129,7 +152,8 @@
         GnssAdapterReportEnginePositionsEventCb positionEventCb,
         GnssAdapterReportSvEventCb svEventCb,
         GnssAdapterReqAidingDataCb reqAidingDataCb,
-        GnssAdapterUpdateNHzRequirementCb updateNHzRequirementCb);
+        GnssAdapterUpdateNHzRequirementCb updateNHzRequirementCb,
+        GnssAdapterUpdateQwesFeatureStatusCb updateQwesFeatureStatusCb);
 
 } // namespace loc_core
 
diff --git a/core/LocAdapterBase.cpp b/core/LocAdapterBase.cpp
index 1e91cf8..95f2728 100644
--- a/core/LocAdapterBase.cpp
+++ b/core/LocAdapterBase.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2014, 2016-2019 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 2016-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -185,6 +185,10 @@
 void LocAdapterBase::reportGnssSvTypeConfigEvent(const GnssSvTypeConfig& /*config*/)
 DEFAULT_IMPL()
 
+void LocAdapterBase::reportGnssConfigEvent(uint32_t,  /* session id*/
+            const GnssConfig& /*gnssConfig*/)
+DEFAULT_IMPL()
+
 bool LocAdapterBase::
     requestOdcpiEvent(OdcpiRequestInfo& /*request*/)
 DEFAULT_IMPL(false)
@@ -309,6 +313,15 @@
         if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_LOCATION_PRIVACY)) {
             mask |= LOCATION_CAPABILITIES_PRIVACY_BIT;
         }
+        if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_MEASUREMENTS_CORRECTION)) {
+            mask |= LOCATION_CAPABILITIES_MEASUREMENTS_CORRECTION_BIT;
+        }
+        if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_ROBUST_LOCATION)) {
+            mask |= LOCATION_CAPABILITIES_CONFORMITY_INDEX_BIT;
+        }
+        if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_EDGNSS)) {
+            mask |= LOCATION_CAPABILITIES_EDGNSS_BIT;
+        }
     } else {
         LOC_LOGE("%s]: attempt to get capabilities before they are known.", __func__);
     }
@@ -415,4 +428,12 @@
     sendMsg(new MsgRequestCapabilities(*this, client));
 }
 
+void
+LocAdapterBase::reportLatencyInfoEvent(const GnssLatencyInfo& /*gnssLatencyInfo*/)
+DEFAULT_IMPL()
+
+bool LocAdapterBase::
+    reportQwesCapabilities(const std::unordered_map<LocationQwesFeatureType, bool> &featureMap)
+DEFAULT_IMPL(false)
+
 } // namespace loc_core
diff --git a/core/LocAdapterBase.h b/core/LocAdapterBase.h
index 7ca3ecd..51b2306 100644
--- a/core/LocAdapterBase.h
+++ b/core/LocAdapterBase.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2014, 2016-2019 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 2016-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -156,7 +156,7 @@
         return ContextBase::isFeatureSupported(featureVal);
     }
 
-    uint32_t generateSessionId();
+    static uint32_t generateSessionId();
 
     inline bool isAdapterMaster() {
         return mIsMaster;
@@ -206,6 +206,7 @@
             GpsLocationExtended &location_extended, LocPosTechMask tech_mask);
     virtual void reportGnssSvIdConfigEvent(const GnssSvIdConfig& config);
     virtual void reportGnssSvTypeConfigEvent(const GnssSvTypeConfig& config);
+    virtual void reportGnssConfigEvent(uint32_t sessionId, const GnssConfig& gnssConfig);
     virtual bool requestOdcpiEvent(OdcpiRequestInfo& request);
     virtual bool reportGnssEngEnergyConsumedEvent(uint64_t energyConsumedSinceFirstBoot);
     virtual bool reportDeleteAidingDataEvent(GnssAidingData &aidingData);
@@ -235,6 +236,9 @@
                              removeClientCompleteCallback rmClientCb);
     void requestCapabilitiesCommand(LocationAPI* client);
 
+    virtual void reportLatencyInfoEvent(const GnssLatencyInfo& gnssLatencyInfo);
+    virtual bool reportQwesCapabilities(
+            const std::unordered_map<LocationQwesFeatureType, bool> &featureMap);
 };
 
 } // namespace loc_core
diff --git a/core/LocApiBase.cpp b/core/LocApiBase.cpp
index 71abdf9..860da2e 100644
--- a/core/LocApiBase.cpp
+++ b/core/LocApiBase.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2014, 2016-2019 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 2016-2021 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -36,6 +36,7 @@
 #include <LocAdapterBase.h>
 #include <log_util.h>
 #include <LocContext.h>
+#include <loc_misc_utils.h>
 
 namespace loc_core {
 
@@ -160,7 +161,7 @@
 
     android_atomic_inc(&mMsgTaskRefCount);
     if (nullptr == mMsgTask) {
-        mMsgTask = new MsgTask("LocApiMsgTask", false);
+        mMsgTask = new MsgTask("LocApiMsgTask");
     }
 }
 
@@ -330,7 +331,7 @@
              "timestamp: %" PRId64 "\n"
              "Session status: %d\n Technology mask: %u\n "
              "SV used in fix (gps/glo/bds/gal/qzss) : \
-             (0x%" PRIx64 "/0x%" PRIx64 "/0x%" PRIx64 "/0x%" PRIx64 "/0x%" PRIx64 ")",
+             (0x%" PRIx64 "/0x%" PRIx64 "/0x%" PRIx64 "/0x%" PRIx64 "/0x%" PRIx64 "/0x%" PRIx64 ")",
              location.gpsLocation.flags, location.position_source,
              location.gpsLocation.latitude, location.gpsLocation.longitude,
              location.gpsLocation.altitude, location.gpsLocation.speed,
@@ -340,7 +341,8 @@
              locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask,
              locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask,
              locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask,
-             locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask);
+             locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask,
+             locationExtended.gnss_sv_used_ids.navic_sv_used_ids_mask);
     // loop through adapters, and deliver to all adapters.
     TO_ALL_LOCADAPTERS(
         mLocAdapters[i]->reportPositionEvent(location, locationExtended,
@@ -406,28 +408,27 @@
 
     // print the SV info before delivering
     LOC_LOGV("num sv: %u\n"
-        "      sv: constellation svid         cN0"
+        "      sv: constellation svid         cN0  basebandCN0"
         "    elevation    azimuth    flags",
         svNotify.count);
-    for (size_t i = 0; i < svNotify.count && i < LOC_GNSS_MAX_SVS; i++) {
+    for (size_t i = 0; i < svNotify.count && i < GNSS_SV_MAX; i++) {
         if (svNotify.gnssSvs[i].type >
             sizeof(constellationString) / sizeof(constellationString[0]) - 1) {
             svNotify.gnssSvs[i].type = GNSS_SV_TYPE_UNKNOWN;
         }
         // Display what we report to clients
-        uint16_t displaySvId = GNSS_SV_TYPE_QZSS == svNotify.gnssSvs[i].type ?
-                               svNotify.gnssSvs[i].svId + QZSS_SV_PRN_MIN - 1 :
-                               svNotify.gnssSvs[i].svId;
-        LOC_LOGV("   %03zu: %*s  %02d    %f    %f    %f    %f    0x%02X",
+        LOC_LOGV("   %03zu: %*s  %02d    %f    %f    %f    %f    %f    0x%02X 0x%2X",
             i,
             13,
             constellationString[svNotify.gnssSvs[i].type],
-            displaySvId,
+            svNotify.gnssSvs[i].svId,
             svNotify.gnssSvs[i].cN0Dbhz,
+            svNotify.gnssSvs[i].basebandCarrierToNoiseDbHz,
             svNotify.gnssSvs[i].elevation,
             svNotify.gnssSvs[i].azimuth,
             svNotify.gnssSvs[i].carrierFrequencyHz,
-            svNotify.gnssSvs[i].gnssSvOptionsMask);
+            svNotify.gnssSvs[i].gnssSvOptionsMask,
+            svNotify.gnssSvs[i].gnssSignalTypeMask);
     }
     // loop through adapters, and deliver to all adapters.
     TO_ALL_LOCADAPTERS(
@@ -483,6 +484,14 @@
     TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportLocationSystemInfoEvent(locationSystemInfo));
 }
 
+void LocApiBase::reportQwesCapabilities
+(
+    const std::unordered_map<LocationQwesFeatureType, bool> &featureMap
+)
+{
+    // loop through adapters, and deliver to all adapters.
+    TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportQwesCapabilities(featureMap));
+}
 void LocApiBase::requestXtraData()
 {
     // loop through adapters, and deliver to the first handling adapter.
@@ -541,9 +550,10 @@
 {
     // Print the config
     LOC_LOGv("gloBlacklistSvMask: %" PRIu64 ", bdsBlacklistSvMask: %" PRIu64 ",\n"
-             "qzssBlacklistSvMask: %" PRIu64 ", galBlacklistSvMask: %" PRIu64,
+             "qzssBlacklistSvMask: %" PRIu64 ", galBlacklistSvMask: %" PRIu64 ",\n"
+              "navicBlacklistSvMask: %" PRIu64,
              config.gloBlacklistSvMask, config.bdsBlacklistSvMask,
-             config.qzssBlacklistSvMask, config.galBlacklistSvMask);
+             config.qzssBlacklistSvMask, config.galBlacklistSvMask, config.navicBlacklistSvMask);
 
     // Loop through adapters, and deliver to all adapters.
     TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGnssSvIdConfigEvent(config));
@@ -593,6 +603,17 @@
     TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportBatchStatusChangeEvent(batchStatus));
 }
 
+void LocApiBase::reportGnssConfig(uint32_t sessionId, const GnssConfig& gnssConfig)
+{
+    // loop through adapters, and deliver to the first handling adapter.
+    TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGnssConfigEvent(sessionId, gnssConfig));
+}
+
+void LocApiBase::reportLatencyInfo(GnssLatencyInfo& gnssLatencyInfo)
+{
+    // loop through adapters, and deliver to the first handling adapter.
+    TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportLatencyInfoEvent(gnssLatencyInfo));
+}
 
 enum loc_api_adapter_err LocApiBase::
    open(LOC_API_ADAPTER_EVENT_MASK_T /*mask*/)
@@ -613,7 +634,8 @@
 DEFAULT_IMPL()
 
 void LocApiBase::
-    injectPosition(double /*latitude*/, double /*longitude*/, float /*accuracy*/)
+    injectPosition(double /*latitude*/, double /*longitude*/, float /*accuracy*/,
+                   bool /*onDemandCpi*/)
 DEFAULT_IMPL()
 
 void LocApiBase::
@@ -628,10 +650,6 @@
     setTime(LocGpsUtcTime /*time*/, int64_t /*timeReference*/, int /*uncertainty*/)
 DEFAULT_IMPL()
 
-enum loc_api_adapter_err LocApiBase::
-    setXtraData(char* /*data*/, int /*length*/)
-DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS)
-
 void LocApiBase::
    atlOpenStatus(int /*handle*/, int /*is_succ*/, char* /*apn*/, uint32_t /*apnLen*/,
                  AGpsBearerType /*bear*/, LocAGpsType /*agpsType*/,
@@ -663,7 +681,7 @@
 DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS)
 
 LocationError LocApiBase::
-    setLPPConfigSync(GnssConfigLppProfile /*profile*/)
+    setLPPConfigSync(GnssConfigLppProfileMask /*profileMask*/)
 DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)
 
 
@@ -708,9 +726,6 @@
 GnssConfigSuplVersion LocApiBase::convertSuplVersion(const uint32_t /*suplVersion*/)
 DEFAULT_IMPL(GNSS_CONFIG_SUPL_VERSION_1_0_0)
 
-GnssConfigLppProfile LocApiBase::convertLppProfile(const uint32_t /*lppProfile*/)
-DEFAULT_IMPL(GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE)
-
 GnssConfigLppeControlPlaneMask LocApiBase::convertLppeCp(const uint32_t /*lppeControlPlaneMask*/)
 DEFAULT_IMPL(0)
 
@@ -721,6 +736,10 @@
         const uint32_t /*emergencyExtensionSeconds*/)
 DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)
 
+void LocApiBase::setMeasurementCorrections(
+        const GnssMeasurementCorrections& /*gnssMeasurementCorrections*/)
+DEFAULT_IMPL()
+
 void LocApiBase::
    getWwanZppFix()
 DEFAULT_IMPL()
@@ -737,12 +756,6 @@
     requestForAidingData(GnssAidingDataSvMask /*svDataMask*/)
 DEFAULT_IMPL()
 
-void LocApiBase::
-    installAGpsCert(const LocDerEncodedCertificate* /*pData*/,
-                    size_t /*length*/,
-                    uint32_t /*slotBitMask*/)
-DEFAULT_IMPL()
-
 LocationError LocApiBase::
     setXtraVersionCheckSync(uint32_t /*check*/)
 DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)
@@ -750,7 +763,8 @@
 LocationError LocApiBase::setBlacklistSvSync(const GnssSvIdConfig& /*config*/)
 DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)
 
-void LocApiBase::setBlacklistSv(const GnssSvIdConfig& /*config*/)
+void LocApiBase::setBlacklistSv(const GnssSvIdConfig& /*config*/,
+                                LocApiResponse* /*adapterResponse*/)
 DEFAULT_IMPL()
 
 void LocApiBase::getBlacklistSv()
@@ -778,8 +792,8 @@
                                           LocApiResponse* /*adapterResponse*/)
 DEFAULT_IMPL()
 
-LocationError LocApiBase::getGnssEnergyConsumed()
-DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)
+void LocApiBase::getGnssEnergyConsumed()
+DEFAULT_IMPL()
 
 
 void LocApiBase::addGeofence(uint32_t /*clientId*/, const GeofenceOption& /*options*/,
@@ -879,4 +893,177 @@
 void LocApiBase::updateSystemPowerState(PowerStateType /*powerState*/)
 DEFAULT_IMPL()
 
+void LocApiBase::
+    configRobustLocation(bool /*enabled*/,
+                         bool /*enableForE911*/,
+                         LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::
+    getRobustLocationConfig(uint32_t sessionId, LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::
+    configMinGpsWeek(uint16_t minGpsWeek,
+                     LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::
+    getMinGpsWeek(uint32_t sessionId, LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+LocationError LocApiBase::
+    setParameterSync(const GnssConfig& gnssConfig)
+DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)
+
+void LocApiBase::
+    getParameter(uint32_t sessionId, GnssConfigFlagsMask flags, LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::
+    configConstellationMultiBand(const GnssSvTypeConfig& secondaryBandConfig,
+                                 LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::
+    getConstellationMultiBandConfig(uint32_t sessionId, LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+int64_t ElapsedRealtimeEstimator::getElapsedRealtimeEstimateNanos(int64_t curDataTimeNanos,
+            bool isCurDataTimeTrustable, int64_t tbf) {
+    //The algorithm works follow below steps:
+    //When isCurDataTimeTrustable is meet (means Modem timestamp is already stable),
+    //1, Wait for mFixTimeStablizationThreshold fixes; While waiting for modem time
+    //   stable, we set the traveltime to a default value;
+    //2, When the mFixTimeStablizationThreshold fix comes, we think now the mode time
+    //   is already stable, calculate the initial AP-Modem clock diff(mCurrentClockDiff)
+    //   using formula:
+    //   mCurrentClockDiff = currentTimeNanos - locationTimeNanos - currentTravelTimeNanos
+    //3, since then, when the nth fix comes,
+    //   3.1 First update mCurrentClockDiff using below formula:
+    //        mCurrentClockDiff = mCurrentClockDiff + (currentTimeNanos - sinceBootTimeNanos)
+    //                - (mPrevUtcTimeNanos - mPrevBootTimeNanos)
+    //   3.2 Calculate currentTravelTimeNanos:
+    //        currentTravelTimeNanos = currentTimeNanos - locationTimeNanos - mCurrentClockDiff
+    //4, It is possible that locationTimeNanos will jump,
+    //   reset mFixTimeStablizationThreshold to default value, jump to step 2 to continue.
+
+    int64_t currentTravelTimeNanos = mInitialTravelTime;
+    struct timespec currentTime;
+    int64_t sinceBootTimeNanos;
+    if (getCurrentTime(currentTime, sinceBootTimeNanos)) {
+        if (isCurDataTimeTrustable) {
+            if (tbf > 0 && tbf != curDataTimeNanos - mPrevDataTimeNanos) {
+                mFixTimeStablizationThreshold = 5;
+            }
+            int64_t currentTimeNanos = (int64_t)currentTime.tv_sec*1000000000 + currentTime.tv_nsec;
+            LOC_LOGd("sinceBootTimeNanos:%" PRIi64 " currentTimeNanos:%" PRIi64 ""
+                     " locationTimeNanos:%" PRIi64 "",
+                     sinceBootTimeNanos, currentTimeNanos, curDataTimeNanos);
+            if (mFixTimeStablizationThreshold == 0) {
+                currentTravelTimeNanos = mInitialTravelTime;
+                mCurrentClockDiff = currentTimeNanos - curDataTimeNanos - currentTravelTimeNanos;
+            } else if (mFixTimeStablizationThreshold < 0) {
+                mCurrentClockDiff = mCurrentClockDiff + (currentTimeNanos - sinceBootTimeNanos)
+                        - (mPrevUtcTimeNanos - mPrevBootTimeNanos);
+                currentTravelTimeNanos = currentTimeNanos - curDataTimeNanos - mCurrentClockDiff;
+            }
+
+            mPrevUtcTimeNanos = currentTimeNanos;
+            mPrevBootTimeNanos = sinceBootTimeNanos;
+            mPrevDataTimeNanos = curDataTimeNanos;
+            mFixTimeStablizationThreshold--;
+        }
+    } else {
+        return -1;
+    }
+    LOC_LOGd("Estimated travel time: %" PRIi64 "", currentTravelTimeNanos);
+    return (sinceBootTimeNanos - currentTravelTimeNanos);
+}
+
+void ElapsedRealtimeEstimator::reset() {
+    mCurrentClockDiff = 0;
+    mPrevDataTimeNanos = 0;
+    mPrevUtcTimeNanos = 0;
+    mPrevBootTimeNanos = 0;
+    mFixTimeStablizationThreshold = 5;
+}
+
+int64_t ElapsedRealtimeEstimator::getElapsedRealtimeQtimer(int64_t qtimerTicksAtOrigin) {
+    struct timespec currentTime;
+    int64_t sinceBootTimeNanos;
+    int64_t elapsedRealTimeNanos;
+
+    if (getCurrentTime(currentTime, sinceBootTimeNanos)) {
+       uint64_t qtimerDiff = 0;
+       uint64_t qTimerTickCount = getQTimerTickCount();
+       if (qTimerTickCount >= qtimerTicksAtOrigin) {
+           qtimerDiff = qTimerTickCount - qtimerTicksAtOrigin;
+       }
+       LOC_LOGd("sinceBootTimeNanos:%" PRIi64 " qtimerTicksAtOrigin=%" PRIi64 ""
+                " qTimerTickCount=%" PRIi64 " qtimerDiff=%" PRIi64 "",
+                sinceBootTimeNanos, qtimerTicksAtOrigin, qTimerTickCount, qtimerDiff);
+       uint64_t qTimerDiffNanos = qTimerTicksToNanos(double(qtimerDiff));
+
+       /* If the time difference between Qtimer on modem side and Qtimer on AP side
+          is greater than one second we assume this is a dual-SoC device such as
+          Kona and will try to get Qtimer on modem side and on AP side and
+          will adjust our difference accordingly */
+       if (qTimerDiffNanos > 1000000000) {
+           uint64_t qtimerDelta = getQTimerDeltaNanos();
+           if (qTimerDiffNanos >= qtimerDelta) {
+               qTimerDiffNanos -= qtimerDelta;
+           }
+       }
+
+       LOC_LOGd("Qtimer travel time: %" PRIi64 "", qTimerDiffNanos);
+       if (sinceBootTimeNanos >= qTimerDiffNanos) {
+           elapsedRealTimeNanos = sinceBootTimeNanos - qTimerDiffNanos;
+       } else {
+           elapsedRealTimeNanos = -1;
+       }
+    } else {
+        elapsedRealTimeNanos = -1;
+    }
+    return elapsedRealTimeNanos;
+}
+
+bool ElapsedRealtimeEstimator::getCurrentTime(
+        struct timespec& currentTime, int64_t& sinceBootTimeNanos)
+{
+    struct timespec sinceBootTime;
+    struct timespec sinceBootTimeTest;
+    bool clockGetTimeSuccess = false;
+    const uint32_t MAX_TIME_DELTA_VALUE_NANOS = 15000;
+    const uint32_t MAX_GET_TIME_COUNT = 20;
+    /* Attempt to get CLOCK_REALTIME and CLOCK_BOOTIME in succession without an interruption
+    or context switch (for up to MAX_GET_TIME_COUNT times) to avoid errors in the calculation */
+    for (uint32_t i = 0; i < MAX_GET_TIME_COUNT; i++) {
+        if (clock_gettime(CLOCK_BOOTTIME, &sinceBootTime) != 0) {
+            break;
+        };
+        if (clock_gettime(CLOCK_REALTIME, &currentTime) != 0) {
+            break;
+        }
+        if (clock_gettime(CLOCK_BOOTTIME, &sinceBootTimeTest) != 0) {
+            break;
+        };
+        sinceBootTimeNanos = (int64_t)sinceBootTime.tv_sec * 1000000000 + sinceBootTime.tv_nsec;
+        int64_t sinceBootTimeTestNanos =
+            (int64_t)sinceBootTimeTest.tv_sec * 1000000000 + sinceBootTimeTest.tv_nsec;
+        int64_t sinceBootTimeDeltaNanos = sinceBootTimeTestNanos - sinceBootTimeNanos;
+
+        /* sinceBootTime and sinceBootTimeTest should have a close value if there was no
+        interruption or context switch between clock_gettime for CLOCK_BOOTIME and
+        clock_gettime for CLOCK_REALTIME */
+        if (sinceBootTimeDeltaNanos < MAX_TIME_DELTA_VALUE_NANOS) {
+            clockGetTimeSuccess = true;
+            break;
+        } else {
+            LOC_LOGd("Delta:%" PRIi64 "ns time too large, retry number #%u...",
+                     sinceBootTimeDeltaNanos, i + 1);
+        }
+    }
+    return clockGetTimeSuccess;
+}
 } // namespace loc_core
diff --git a/core/LocApiBase.h b/core/LocApiBase.h
index 9c76bab..cbe5f9f 100644
--- a/core/LocApiBase.h
+++ b/core/LocApiBase.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2014, 2016-2019 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 2016-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -36,6 +36,15 @@
 #include <MsgTask.h>
 #include <LocSharedLock.h>
 #include <log_util.h>
+#ifdef NO_UNORDERED_SET_OR_MAP
+    #include <map>
+#else
+    #include <unordered_map>
+#endif
+#include <inttypes.h>
+#include <functional>
+
+using namespace loc_util;
 
 namespace loc_core {
 
@@ -59,13 +68,6 @@
 #define TO_1ST_HANDLING_ADAPTER(adapters, call)                              \
     for (int i = 0; i <MAX_ADAPTERS && NULL != (adapters)[i] && !(call); i++);
 
-enum xtra_version_check {
-    DISABLED,
-    AUTO,
-    XTRA2,
-    XTRA3
-};
-
 class LocAdapterBase;
 struct LocSsrMsg;
 struct LocOpenMsg;
@@ -97,6 +99,9 @@
     inline LocApiProxyBase() {}
     inline virtual ~LocApiProxyBase() {}
     inline virtual void* getSibling2() { return NULL; }
+    inline virtual double getGloRfLoss(uint32_t left,
+            uint32_t center, uint32_t right, uint8_t gloFrequency) { return 0.0; }
+    inline virtual float getGeoidalSeparation(double latitude, double longitude) { return 0.0; }
 };
 
 class LocApiBase {
@@ -125,7 +130,7 @@
     inline virtual ~LocApiBase() {
         android_atomic_dec(&mMsgTaskRefCount);
         if (nullptr != mMsgTask && 0 == mMsgTaskRefCount) {
-            mMsgTask->destroy();
+            delete mMsgTask;
             mMsgTask = nullptr;
         }
     }
@@ -196,6 +201,12 @@
     void reportKlobucharIonoModel(GnssKlobucharIonoModel& ionoModel);
     void reportGnssAdditionalSystemInfo(GnssAdditionalSystemInfo& additionalSystemInfo);
     void sendNfwNotification(GnssNfwNotification& notification);
+    void reportGnssConfig(uint32_t sessionId, const GnssConfig& gnssConfig);
+    void reportLatencyInfo(GnssLatencyInfo& gnssLatencyInfo);
+    void reportQwesCapabilities
+    (
+        const std::unordered_map<LocationQwesFeatureType, bool> &featureMap
+    );
 
     void geofenceBreach(size_t count, uint32_t* hwIds, Location& location,
             GeofenceBreachType breachType, uint64_t timestamp);
@@ -214,12 +225,12 @@
     virtual void startFix(const LocPosMode& fixCriteria, LocApiResponse* adapterResponse);
     virtual void stopFix(LocApiResponse* adapterResponse);
     virtual void deleteAidingData(const GnssAidingData& data, LocApiResponse* adapterResponse);
-    virtual void injectPosition(double latitude, double longitude, float accuracy);
+    virtual void injectPosition(double latitude, double longitude, float accuracy,
+            bool onDemandCpi);
     virtual void injectPosition(const GnssLocationInfoNotification &locationInfo,
             bool onDemandCpi=false);
     virtual void injectPosition(const Location& location, bool onDemandCpi);
     virtual void setTime(LocGpsUtcTime time, int64_t timeReference, int uncertainty);
-    virtual enum loc_api_adapter_err setXtraData(char* data, int length);
     virtual void atlOpenStatus(int handle, int is_succ, char* apn, uint32_t apnLen,
             AGpsBearerType bear, LocAGpsType agpsType, LocApnTypeMask mask);
     virtual void atlCloseStatus(int handle, int is_succ);
@@ -228,7 +239,7 @@
     virtual void informNiResponse(GnssNiResponse userResponse, const void* passThroughData);
     virtual LocationError setSUPLVersionSync(GnssConfigSuplVersion version);
     virtual enum loc_api_adapter_err setNMEATypesSync(uint32_t typesMask);
-    virtual LocationError setLPPConfigSync(GnssConfigLppProfile profile);
+    virtual LocationError setLPPConfigSync(GnssConfigLppProfileMask profileMask);
     virtual enum loc_api_adapter_err setSensorPropertiesSync(
             bool gyroBiasVarianceRandomWalk_valid, float gyroBiasVarianceRandomWalk,
             bool accelBiasVarianceRandomWalk_valid, float accelBiasVarianceRandomWalk,
@@ -244,21 +255,21 @@
     virtual LocationError setLPPeProtocolCpSync(GnssConfigLppeControlPlaneMask lppeCP);
     virtual LocationError setLPPeProtocolUpSync(GnssConfigLppeUserPlaneMask lppeUP);
     virtual GnssConfigSuplVersion convertSuplVersion(const uint32_t suplVersion);
-    virtual GnssConfigLppProfile convertLppProfile(const uint32_t lppProfile);
     virtual GnssConfigLppeControlPlaneMask convertLppeCp(const uint32_t lppeControlPlaneMask);
     virtual GnssConfigLppeUserPlaneMask convertLppeUp(const uint32_t lppeUserPlaneMask);
     virtual LocationError setEmergencyExtensionWindowSync(const uint32_t emergencyExtensionSeconds);
+    virtual void setMeasurementCorrections(
+            const GnssMeasurementCorrections& gnssMeasurementCorrections);
 
     virtual void getWwanZppFix();
     virtual void getBestAvailableZppFix();
-    virtual void installAGpsCert(const LocDerEncodedCertificate* pData, size_t length,
-            uint32_t slotBitMask);
     virtual LocationError setGpsLockSync(GnssConfigGpsLock lock);
     virtual void requestForAidingData(GnssAidingDataSvMask svDataMask);
     virtual LocationError setXtraVersionCheckSync(uint32_t check);
     /* Requests for SV/Constellation Control */
     virtual LocationError setBlacklistSvSync(const GnssSvIdConfig& config);
-    virtual void setBlacklistSv(const GnssSvIdConfig& config);
+    virtual void setBlacklistSv(const GnssSvIdConfig& config,
+                                LocApiResponse *adapterResponse=nullptr);
     virtual void getBlacklistSv();
     virtual void setConstellationControl(const GnssSvTypeConfig& config,
                                          LocApiResponse *adapterResponse=nullptr);
@@ -271,7 +282,7 @@
                                         LocApiResponse* adapterResponse=nullptr);
     virtual void setPositionAssistedClockEstimatorMode(bool enabled,
                                                        LocApiResponse* adapterResponse=nullptr);
-    virtual LocationError getGnssEnergyConsumed();
+    virtual void getGnssEnergyConsumed();
 
     virtual void addGeofence(uint32_t clientId, const GeofenceOption& options,
             const GeofenceInfo& info, LocApiResponseData<LocApiGeofenceData>* adapterResponseData);
@@ -318,6 +329,43 @@
     void updateNmeaMask(uint32_t mask);
 
     virtual void updateSystemPowerState(PowerStateType systemPowerState);
+
+    virtual void configRobustLocation(bool enable, bool enableForE911,
+                                      LocApiResponse* adapterResponse=nullptr);
+    virtual void getRobustLocationConfig(uint32_t sessionId, LocApiResponse* adapterResponse);
+    virtual void configMinGpsWeek(uint16_t minGpsWeek,
+                                  LocApiResponse* adapterResponse=nullptr);
+    virtual void getMinGpsWeek(uint32_t sessionId, LocApiResponse* adapterResponse);
+
+    virtual LocationError setParameterSync(const GnssConfig & gnssConfig);
+    virtual void getParameter(uint32_t sessionId, GnssConfigFlagsMask flags,
+                              LocApiResponse* adapterResponse=nullptr);
+
+    virtual void configConstellationMultiBand(const GnssSvTypeConfig& secondaryBandConfig,
+                                              LocApiResponse* adapterResponse=nullptr);
+    virtual void getConstellationMultiBandConfig(uint32_t sessionId,
+                                        LocApiResponse* adapterResponse=nullptr);
+};
+
+class ElapsedRealtimeEstimator {
+private:
+    int64_t mCurrentClockDiff;
+    int64_t mPrevUtcTimeNanos;
+    int64_t mPrevBootTimeNanos;
+    int64_t mFixTimeStablizationThreshold;
+    int64_t mInitialTravelTime;
+    int64_t mPrevDataTimeNanos;
+public:
+
+    ElapsedRealtimeEstimator(int64_t travelTimeNanosEstimate):
+            mInitialTravelTime(travelTimeNanosEstimate) {reset();}
+    int64_t getElapsedRealtimeEstimateNanos(int64_t curDataTimeNanos,
+            bool isCurDataTimeTrustable, int64_t tbf);
+    inline int64_t getElapsedRealtimeUncNanos() { return 5000000;}
+    void reset();
+
+    static int64_t getElapsedRealtimeQtimer(int64_t qtimerTicksAtOrigin);
+    static bool getCurrentTime(struct timespec& currentTime, int64_t& sinceBootTimeNanos);
 };
 
 typedef LocApiBase* (getLocApi_t)(LOC_API_ADAPTER_EVENT_MASK_T exMask,
diff --git a/core/LocContext.cpp b/core/LocContext.cpp
index 18d3f2d..272c08c 100644
--- a/core/LocContext.cpp
+++ b/core/LocContext.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2014, 2016-2019 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 2016-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -50,36 +50,25 @@
 
 pthread_mutex_t LocContext::mGetLocContextMutex = PTHREAD_MUTEX_INITIALIZER;
 
-const MsgTask* LocContext::getMsgTask(LocThread::tCreate tCreator,
-                                          const char* name, bool joinable)
+const MsgTask* LocContext::getMsgTask(const char* name)
 {
     if (NULL == mMsgTask) {
-        mMsgTask = new MsgTask(tCreator, name, joinable);
+        mMsgTask = new MsgTask(name);
     }
     return mMsgTask;
 }
 
-inline
-const MsgTask* LocContext::getMsgTask(const char* name, bool joinable) {
-    return getMsgTask((LocThread::tCreate)NULL, name, joinable);
-}
-
-ContextBase* LocContext::getLocContext(LocThread::tCreate tCreator,
-            LocMsg* firstMsg, const char* name, bool joinable)
+ContextBase* LocContext::getLocContext(const char* name)
 {
     pthread_mutex_lock(&LocContext::mGetLocContextMutex);
     LOC_LOGD("%s:%d]: querying ContextBase with tCreator", __func__, __LINE__);
     if (NULL == mContext) {
         LOC_LOGD("%s:%d]: creating msgTask with tCreator", __func__, __LINE__);
-        const MsgTask* msgTask = getMsgTask(tCreator, name, joinable);
+        const MsgTask* msgTask = getMsgTask(name);
         mContext = new LocContext(msgTask);
     }
     pthread_mutex_unlock(&LocContext::mGetLocContextMutex);
 
-    if (firstMsg) {
-        mContext->sendMsg(firstMsg);
-    }
-
     return mContext;
 }
 
diff --git a/core/LocContext.h b/core/LocContext.h
index fb7d009..628ed93 100644
--- a/core/LocContext.h
+++ b/core/LocContext.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2014, 2017-2019 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 2017-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -39,9 +39,7 @@
 class LocContext : public ContextBase {
     static const MsgTask* mMsgTask;
     static ContextBase* mContext;
-    static const MsgTask* getMsgTask(LocThread::tCreate tCreator,
-                                     const char* name, bool joinable = true);
-    static const MsgTask* getMsgTask(const char* name, bool joinable = true);
+    static const MsgTask* getMsgTask(const char* name);
     static pthread_mutex_t mGetLocContextMutex;
 
 protected:
@@ -52,11 +50,7 @@
     static const char* mLBSLibName;
     static const char* mLocationHalName;
 
-    static ContextBase* getLocContext(LocThread::tCreate tCreator, LocMsg* firstMsg,
-                                        const char* name, bool joinable = true);
-    inline static ContextBase* getLocContext(const char* name, bool joinable = true) {
-        return getLocContext(NULL, NULL, name, joinable);
-    }
+    static ContextBase* getLocContext(const char* name);
 
     static void injectFeatureConfig(ContextBase *context);
 };
diff --git a/core/Makefile.am b/core/Makefile.am
index 1199a52..291dbb5 100644
--- a/core/Makefile.am
+++ b/core/Makefile.am
@@ -40,6 +40,10 @@
            SystemStatusOsObserver.cpp \
            SystemStatus.cpp
 
+if USE_EXTERNAL_AP
+AM_CFLAGS += -DFEATURE_EXTERNAL_AP
+endif
+
 library_includedir = $(pkgincludedir)
 
 library_include_HEADERS = $(libloc_core_la_h_sources)
diff --git a/core/SystemStatus.cpp b/core/SystemStatus.cpp
index 393eead..fe11de0 100644
--- a/core/SystemStatus.cpp
+++ b/core/SystemStatus.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, 2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -1287,6 +1287,14 @@
     mInstance = NULL;
 }
 
+void SystemStatus::resetNetworkInfo() {
+    for (int i=0; i<mCache.mNetworkInfo.size(); ++i) {
+        // Reset all the cached NetworkInfo Items as disconnected
+        eventConnectionStatus(false, mCache.mNetworkInfo[i].mType, mCache.mNetworkInfo[i].mRoaming,
+                mCache.mNetworkInfo[i].mNetworkHandle, mCache.mNetworkInfo[i].mApn);
+    }
+}
+
 IOsObserver* SystemStatus::getOsObserver()
 {
     return &mSysStatusObsvr;
@@ -1578,6 +1586,7 @@
             break;
     }
     pthread_mutex_unlock(&mMutexSystemStatus);
+    LOC_LOGv("DataItemId: %d, whether to record dateitem in cache: %d", dataitem->getId(), ret);
     return ret;
 }
 
@@ -1724,11 +1733,12 @@
 @return     true when successfully done
 ******************************************************************************/
 bool SystemStatus::eventConnectionStatus(bool connected, int8_t type,
-                                         bool roaming, NetworkHandle networkHandle)
+                                         bool roaming, NetworkHandle networkHandle,
+                                         string& apn)
 {
     // send networkinof dataitem to systemstatus observer clients
     SystemStatusNetworkInfo s(type, "", "", connected, roaming,
-                              (uint64_t) networkHandle);
+                              (uint64_t) networkHandle, apn);
     mSysStatusObsvr.notify({&s});
 
     return true;
diff --git a/core/SystemStatus.h b/core/SystemStatus.h
index 8ec85fa..21036cd 100644
--- a/core/SystemStatus.h
+++ b/core/SystemStatus.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -482,12 +482,13 @@
     NetworkInfoDataItemBase* mSrcObjPtr;
 public:
     inline SystemStatusNetworkInfo(
-            int32_t type=0,
-            std::string typeName="",
-            string subTypeName="",
-            bool connected=false,
-            bool roaming=false,
-            uint64_t networkHandle=NETWORK_HANDLE_UNKNOWN) :
+            int32_t type = 0,
+            std::string typeName = "",
+            string subTypeName = "",
+            bool connected = false,
+            bool roaming = false,
+            uint64_t networkHandle = NETWORK_HANDLE_UNKNOWN,
+            string apn = "") :
             NetworkInfoDataItemBase(
                     (NetworkType)type,
                     type,
@@ -496,33 +497,39 @@
                     connected && (!roaming),
                     connected,
                     roaming,
-                    networkHandle),
+                    networkHandle, apn),
             mSrcObjPtr(nullptr) {}
     inline SystemStatusNetworkInfo(const NetworkInfoDataItemBase& itemBase) :
             NetworkInfoDataItemBase(itemBase),
             mSrcObjPtr((NetworkInfoDataItemBase*)&itemBase) {
-        mType = itemBase.getType();
+        mType = (int32_t)itemBase.getType();
     }
     inline bool equals(const SystemStatusNetworkInfo& peer) {
-        for (uint8_t i = 0; i < MAX_NETWORK_HANDLES; ++i) {
-             if (!(mAllNetworkHandles[i] == peer.mAllNetworkHandles[i])) {
-                 return false;
-             }
-         }
-        return true;
+        bool rtv = (peer.mConnected == mConnected);
+        for (uint8_t i = 0; rtv && i < MAX_NETWORK_HANDLES; ++i) {
+            rtv &= (mAllNetworkHandles[i] == peer.mAllNetworkHandles[i]);
+        }
+        return rtv && !peer.mApn.compare(mApn);
     }
     inline virtual SystemStatusItemBase& collate(SystemStatusItemBase& curInfo) {
+        LOC_LOGv("NetworkInfo: mAllTypes=%" PRIx64 " connected=%u mType=%x mApn=%s",
+                 mAllTypes, mConnected, mType, mApn.c_str());
         uint64_t allTypes = (static_cast<SystemStatusNetworkInfo&>(curInfo)).mAllTypes;
-        uint64_t networkHandle =
-                (static_cast<SystemStatusNetworkInfo&>(curInfo)).mNetworkHandle;
-        int32_t type = (static_cast<SystemStatusNetworkInfo&>(curInfo)).mType;
+        string& apn = (static_cast<SystemStatusNetworkInfo&>(curInfo)).mApn;
         // Replace current with cached table for now and then update
         memcpy(mAllNetworkHandles,
                (static_cast<SystemStatusNetworkInfo&>(curInfo)).getNetworkHandle(),
                sizeof(mAllNetworkHandles));
+        LOC_LOGd("NetworkInfo: allTypes=%" PRIx64 " mType=%x mConnected=%u mNetworkHandle=%" PRIx64 , allTypes, mType, mConnected, mNetworkHandle);
+        // Update the apn for non-mobile type connections.
+        if (TYPE_MOBILE != mType && apn.compare("") != 0) {
+            mApn = apn;
+        }
         if (mConnected) {
             mAllTypes |= allTypes;
             for (uint8_t i = 0; i < MAX_NETWORK_HANDLES; ++i) {
+            LOC_LOGd("NetworkInfo: mNetworkHandle[%u]: networkHandle %" PRIx64 ",  networkType %x", i, mAllNetworkHandles[i].networkHandle,
+                    mAllNetworkHandles[i].networkType);
                 if (mNetworkHandle == mAllNetworkHandles[i].networkHandle) {
                     LOC_LOGD("collate duplicate detected, not updating");
                     break;
@@ -542,18 +549,21 @@
                  ++lastValidIndex) {
                 // Maintain count for number of network handles still
                 // connected for given type
-                if (mType == mAllNetworkHandles[lastValidIndex].networkType) {
-                    typeCount++;
+                if (mType == (int32_t)mAllNetworkHandles[lastValidIndex].networkType) {
+                    if (mNetworkHandle == mAllNetworkHandles[lastValidIndex].networkHandle) {
+                        deletedIndex = lastValidIndex;
+                    } else {
+                        typeCount++;
+                    }
                 }
 
-                if (mNetworkHandle == mAllNetworkHandles[lastValidIndex].networkHandle) {
-                    deletedIndex = lastValidIndex;
-                    typeCount--;
-                }
+            }
+            if (lastValidIndex > 0) {
+                --lastValidIndex;
             }
 
             if (MAX_NETWORK_HANDLES != deletedIndex) {
-                LOC_LOGD("deletedIndex:%u, lastValidIndex:%u, typeCount:%u",
+                LOC_LOGd("deletedIndex:%u, lastValidIndex:%u, typeCount:%u",
                         deletedIndex, lastValidIndex, typeCount);
                 mAllNetworkHandles[deletedIndex] = mAllNetworkHandles[lastValidIndex];
                 mAllNetworkHandles[lastValidIndex].networkHandle = NETWORK_HANDLE_UNKNOWN;
@@ -578,8 +588,8 @@
         return *this;
     }
     inline void dump(void) override {
-        LOC_LOGD("NetworkInfo: mAllTypes=%" PRIx64 " connected=%u mType=%x",
-                 mAllTypes, mConnected, mType);
+        LOC_LOGD("NetworkInfo: mAllTypes=%" PRIx64 " connected=%u mType=%x mApn=%s",
+                 mAllTypes, mConnected, mType, mApn.c_str());
     }
 };
 
@@ -908,8 +918,9 @@
     bool getReport(SystemStatusReports& reports, bool isLatestonly = false) const;
     bool setDefaultGnssEngineStates(void);
     bool eventConnectionStatus(bool connected, int8_t type,
-                               bool roaming, NetworkHandle networkHandle);
+                               bool roaming, NetworkHandle networkHandle, string& apn);
     bool updatePowerConnectState(bool charging);
+    void resetNetworkInfo();
 };
 
 } // namespace loc_core
diff --git a/core/SystemStatusOsObserver.cpp b/core/SystemStatusOsObserver.cpp
index 0427380..8fd9564 100644
--- a/core/SystemStatusOsObserver.cpp
+++ b/core/SystemStatusOsObserver.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -38,7 +38,7 @@
 {
 template <typename CINT, typename COUT>
 COUT SystemStatusOsObserver::containerTransfer(CINT& inContainer) {
-    COUT outContainer(0);
+    COUT outContainer = {};
     for (auto item : inContainer) {
         outContainer.insert(outContainer.begin(), item);
     }
@@ -67,6 +67,7 @@
         inline SetSubsObj(ObserverContext& context, IDataItemSubscription* subscriptionObj) :
                 mContext(context), mSubsObj(subscriptionObj) {}
         void proc() const {
+            LOC_LOGi("SetSubsObj::enter");
             mContext.mSubscriptionObj = mSubsObj;
 
             if (!mContext.mSSObserver->mDataItemToClients.empty()) {
@@ -76,6 +77,7 @@
                 mContext.mSubscriptionObj->subscribe(dis, mContext.mSSObserver);
                 mContext.mSubscriptionObj->requestData(dis, mContext.mSSObserver);
             }
+            LOC_LOGi("SetSubsObj::exit");
         }
     };
 
@@ -101,7 +103,7 @@
                 mToRequestData(requestData) {}
 
         void proc() const {
-            unordered_set<DataItemId> dataItemsToSubscribe(0);
+            unordered_set<DataItemId> dataItemsToSubscribe = {};
             mParent->mDataItemToClients.add(mDataItemSet, {mClient}, &dataItemsToSubscribe);
             mParent->mClientToDataItems.add(mClient, mDataItemSet);
 
@@ -147,8 +149,8 @@
                 mDataItemSet(containerTransfer<list<DataItemId>, unordered_set<DataItemId>>(l)) {}
 
         void proc() const {
-            unordered_set<DataItemId> dataItemsToSubscribe(0);
-            unordered_set<DataItemId> dataItemsToUnsubscribe(0);
+            unordered_set<DataItemId> dataItemsToSubscribe = {};
+            unordered_set<DataItemId> dataItemsToUnsubscribe = {};
             unordered_set<IDataItemObserver*> clients({mClient});
             // below removes clients from all entries keyed with the return of the
             // mClientToDataItems.update() call. If leaving an empty set of clients as the
@@ -219,11 +221,11 @@
                 mDataItemSet(containerTransfer<list<DataItemId>, unordered_set<DataItemId>>(l)) {}
 
         void proc() const {
-            unordered_set<DataItemId> dataItemsUnusedByClient(0);
-            unordered_set<IDataItemObserver*> clientToRemove(0);
+            unordered_set<DataItemId> dataItemsUnusedByClient = {};
+            unordered_set<IDataItemObserver*> clientToRemove = {};
+            unordered_set<DataItemId> dataItemsToUnsubscribe = {};
             mParent->mClientToDataItems.trimOrRemove({mClient}, mDataItemSet,  &clientToRemove,
                                                      &dataItemsUnusedByClient);
-            unordered_set<DataItemId> dataItemsToUnsubscribe(0);
             mParent->mDataItemToClients.trimOrRemove(dataItemsUnusedByClient, {mClient},
                                                      &dataItemsToUnsubscribe, nullptr);
 
@@ -259,6 +261,7 @@
 
         void proc() const {
             unordered_set<DataItemId> diByClient = mParent->mClientToDataItems.getValSet(mClient);
+
             if (!diByClient.empty()) {
                 unordered_set<DataItemId> dataItemsToUnsubscribe;
                 mParent->mClientToDataItems.remove(mClient);
@@ -308,7 +311,7 @@
         void proc() const {
             // Update Cache with received data items and prepare
             // list of data items to be sent.
-            unordered_set<DataItemId> dataItemIdsToBeSent(0);
+            unordered_set<DataItemId> dataItemIdsToBeSent = {};
             for (auto item : mDiVec) {
                 if (mParent->updateCache(item)) {
                     dataItemIdsToBeSent.insert(item->getId());
@@ -316,7 +319,7 @@
             }
 
             // Send data item to all subscribed clients
-            unordered_set<IDataItemObserver*> clientSet(0);
+            unordered_set<IDataItemObserver*> clientSet = {};
             for (auto each : dataItemIdsToBeSent) {
                 auto clients = mParent->mDataItemToClients.getValSetPtr(each);
                 if (nullptr != clients) {
@@ -347,11 +350,6 @@
         vector<IDataItemCore*> dataItemVec(dlist.size());
 
         for (auto each : dlist) {
-            IF_LOC_LOGD {
-                string dv;
-                each->stringify(dv);
-                LOC_LOGD("notify: DataItem In Value:%s", dv.c_str());
-            }
 
             IDataItemCore* di = DataItemsFactoryProxy::createNewDataItem(each->getId());
             if (nullptr == di) {
@@ -364,6 +362,11 @@
 
             // add this dataitem if updated from last one
             dataItemVec.push_back(di);
+            IF_LOC_LOGD {
+                string dv;
+                di->stringify(dv);
+                LOC_LOGd("notify: DataItem In Value:%s", dv.c_str());
+            }
         }
 
         if (!dataItemVec.empty()) {
@@ -449,59 +452,73 @@
 }
 
 #ifdef USE_GLIB
-bool SystemStatusOsObserver::connectBackhaul()
+bool SystemStatusOsObserver::connectBackhaul(const string& clientName)
 {
     bool result = false;
 
     if (mContext.mFrameworkActionReqObj != NULL) {
         struct HandleConnectBackhaul : public LocMsg {
-            HandleConnectBackhaul(IFrameworkActionReq* fwkActReq) :
-                    mFwkActionReqObj(fwkActReq) {}
+            HandleConnectBackhaul(IFrameworkActionReq* fwkActReq, const string& clientName) :
+                    mClientName(clientName), mFwkActionReqObj(fwkActReq) {}
             virtual ~HandleConnectBackhaul() {}
             void proc() const {
-                LOC_LOGD("HandleConnectBackhaul");
-                mFwkActionReqObj->connectBackhaul();
+                LOC_LOGi("HandleConnectBackhaul::enter");
+                mFwkActionReqObj->connectBackhaul(mClientName);
+                LOC_LOGi("HandleConnectBackhaul::exit");
             }
             IFrameworkActionReq* mFwkActionReqObj;
+            string mClientName;
         };
         mContext.mMsgTask->sendMsg(
-                new (nothrow) HandleConnectBackhaul(mContext.mFrameworkActionReqObj));
+                new (nothrow) HandleConnectBackhaul(mContext.mFrameworkActionReqObj, clientName));
         result = true;
     }
     else {
-        ++mBackHaulConnectReqCount;
-        LOC_LOGE("Framework action request object is NULL.Caching connect request: %d",
-                        mBackHaulConnectReqCount);
+        LOC_LOGe("Framework action request object is NULL.Caching connect request: %s",
+                clientName.c_str());
+        ClientBackhaulReqCache::const_iterator iter = mBackHaulConnReqCache.find(clientName);
+        if (iter == mBackHaulConnReqCache.end()) {
+            // not found in set. first time receiving from request from client
+            LOC_LOGe("Adding client to BackHaulConnReqCache list");
+            mBackHaulConnReqCache.insert(clientName);
+        }
         result = false;
     }
     return result;
 
 }
 
-bool SystemStatusOsObserver::disconnectBackhaul()
+bool SystemStatusOsObserver::disconnectBackhaul(const string& clientName)
 {
     bool result = false;
 
     if (mContext.mFrameworkActionReqObj != NULL) {
         struct HandleDisconnectBackhaul : public LocMsg {
-            HandleDisconnectBackhaul(IFrameworkActionReq* fwkActReq) :
-                    mFwkActionReqObj(fwkActReq) {}
+            HandleDisconnectBackhaul(IFrameworkActionReq* fwkActReq, const string& clientName) :
+                    mClientName(clientName), mFwkActionReqObj(fwkActReq) {}
             virtual ~HandleDisconnectBackhaul() {}
             void proc() const {
-                LOC_LOGD("HandleDisconnectBackhaul");
-                mFwkActionReqObj->disconnectBackhaul();
+                LOC_LOGi("HandleDisconnectBackhaul::enter");
+                mFwkActionReqObj->disconnectBackhaul(mClientName);
+                LOC_LOGi("HandleDisconnectBackhaul::exit");
             }
             IFrameworkActionReq* mFwkActionReqObj;
+            string mClientName;
         };
         mContext.mMsgTask->sendMsg(
-                new (nothrow) HandleDisconnectBackhaul(mContext.mFrameworkActionReqObj));
+                new (nothrow) HandleDisconnectBackhaul(mContext.mFrameworkActionReqObj,
+                        clientName));
     }
     else {
-        if (mBackHaulConnectReqCount > 0) {
-            --mBackHaulConnectReqCount;
+        LOC_LOGe("Framework action request object is NULL.Caching disconnect request: %s",
+                clientName.c_str());
+        // Check if client has requested for backhaul connection.
+        ClientBackhaulReqCache::const_iterator iter = mBackHaulConnReqCache.find(clientName);
+        if (iter != mBackHaulConnReqCache.end()) {
+            // client found, remove from set.
+            LOC_LOGd("Removing client from BackHaulConnReqCache list");
+            mBackHaulConnReqCache.erase(iter);
         }
-        LOC_LOGE("Framework action request object is NULL.Caching disconnect request: %d",
-                        mBackHaulConnectReqCount);
         result = false;
     }
     return result;
@@ -518,7 +535,7 @@
     } else {
         string clientName;
         to->getName(clientName);
-        list<IDataItemCore*> dataItems(0);
+        list<IDataItemCore*> dataItems = {};
 
         for (auto each : s) {
             auto citer = mDataItemCache.find(each);
diff --git a/core/SystemStatusOsObserver.h b/core/SystemStatusOsObserver.h
index fd60606..c0f56d8 100644
--- a/core/SystemStatusOsObserver.h
+++ b/core/SystemStatusOsObserver.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -60,6 +60,10 @@
 typedef LocUnorderedSetMap<DataItemId, IDataItemObserver*> DataItemToClients;
 typedef unordered_map<DataItemId, IDataItemCore*> DataItemIdToCore;
 typedef unordered_map<DataItemId, int> DataItemIdToInt;
+#ifdef USE_GLIB
+// Cache details of backhaul client requests
+typedef unordered_set<string> ClientBackhaulReqCache;
+#endif
 
 struct ObserverContext {
     IDataItemSubscription* mSubscriptionObj;
@@ -83,12 +87,7 @@
     inline SystemStatusOsObserver(SystemStatus* systemstatus, const MsgTask* msgTask) :
             mSystemStatus(systemstatus), mContext(msgTask, this),
             mAddress("SystemStatusOsObserver"),
-            mClientToDataItems(MAX_DATA_ITEM_ID), mDataItemToClients(MAX_DATA_ITEM_ID)
-#ifdef USE_GLIB
-            , mBackHaulConnectReqCount(0)
-#endif
-    {
-    }
+            mClientToDataItems(MAX_DATA_ITEM_ID), mDataItemToClients(MAX_DATA_ITEM_ID) {}
 
     // dtor
     ~SystemStatusOsObserver();
@@ -107,9 +106,15 @@
     inline void setFrameworkActionReqObj(IFrameworkActionReq* frameworkActionReqObj) {
         mContext.mFrameworkActionReqObj = frameworkActionReqObj;
 #ifdef USE_GLIB
-        if (mBackHaulConnectReqCount > 0) {
-            connectBackhaul();
-            mBackHaulConnectReqCount = 0;
+        uint32_t numBackHaulClients = mBackHaulConnReqCache.size();
+        if (numBackHaulClients > 0) {
+            // For each client, invoke connectbackhaul.
+            for (auto clientName : mBackHaulConnReqCache) {
+                LOC_LOGd("Invoke connectBackhaul for client: %s", clientName.c_str());
+                connectBackhaul(clientName);
+            }
+            // Clear the set
+            mBackHaulConnReqCache.clear();
         }
 #endif
     }
@@ -135,8 +140,8 @@
     virtual void turnOn(DataItemId dit, int timeOut = 0) override;
     virtual void turnOff(DataItemId dit) override;
 #ifdef USE_GLIB
-    virtual bool connectBackhaul() override;
-    virtual bool disconnectBackhaul();
+    virtual bool connectBackhaul(const string& clientName) override;
+    virtual bool disconnectBackhaul(const string& clientName) override;
 #endif
 
 private:
@@ -153,7 +158,7 @@
             const list<DataItemId>& l, IDataItemObserver* client);
 #ifdef USE_GLIB
     // Cache the framework action request for connect/disconnect
-    int         mBackHaulConnectReqCount;
+    ClientBackhaulReqCache  mBackHaulConnReqCache;
 #endif
 
     void subscribe(const list<DataItemId>& l, IDataItemObserver* client, bool toRequestData);
diff --git a/core/configure.ac b/core/configure.ac
index 548c5e5..19db9cf 100644
--- a/core/configure.ac
+++ b/core/configure.ac
@@ -86,6 +86,19 @@
 
 AM_CONDITIONAL(USE_FEATURE_AUTOMOTIVE, test "x${with_auto_feature}" = "xyes")
 
+# External AP
+AC_ARG_WITH([external_ap],
+    AC_HELP_STRING([--with-external_ap=@<:@dir@:>@],
+        [Using External Application Processor]),
+    [],
+    with_external_ap=no)
+
+if test "x$with_external_ap" != "xno"; then
+    CPPFLAGS="${CPPFLAGS} -DFEATURE_EXTERNAL_AP"
+fi
+
+AM_CONDITIONAL(USE_EXTERNAL_AP, test "x${with_external_ap}" = "xyes")
+
 AC_CONFIG_FILES([ \
         Makefile \
         loc-core.pc \
diff --git a/core/data-items/DataItemConcreteTypesBase.h b/core/data-items/DataItemConcreteTypesBase.h
index c32d65d..11a3cce 100644
--- a/core/data-items/DataItemConcreteTypesBase.h
+++ b/core/data-items/DataItemConcreteTypesBase.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, 2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, 2020, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -284,7 +284,7 @@
 public:
     NetworkInfoDataItemBase(
     NetworkType initialType, int32_t type, string typeName, string subTypeName,
-    bool available, bool connected, bool roaming, uint64_t networkHandle ):
+    bool available, bool connected, bool roaming, uint64_t networkHandle, string apn):
             mAllTypes(typeToAllTypes(initialType)),
             mType(type),
             mTypeName(typeName),
@@ -293,7 +293,7 @@
             mConnected(connected),
             mRoaming(roaming),
             mNetworkHandle(networkHandle),
-            mId(NETWORKINFO_DATA_ITEM_ID) {
+            mId(NETWORKINFO_DATA_ITEM_ID), mApn(apn) {
                 mAllNetworkHandles[0].networkHandle = networkHandle;
                 mAllNetworkHandles[0].networkType = initialType;
             }
@@ -318,6 +318,7 @@
     bool mRoaming;
     NetworkInfoType mAllNetworkHandles[MAX_NETWORK_HANDLES];
     uint64_t mNetworkHandle;
+    string mApn;
 protected:
     DataItemId mId;
     inline uint64_t typeToAllTypes(NetworkType type) {
diff --git a/core/data-items/DataItemsFactoryProxy.cpp b/core/data-items/DataItemsFactoryProxy.cpp
index f8a5e03..10f73f4 100644
--- a/core/data-items/DataItemsFactoryProxy.cpp
+++ b/core/data-items/DataItemsFactoryProxy.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -34,6 +34,7 @@
 #include <DataItemsFactoryProxy.h>
 #include <loc_pla.h>
 #include <log_util.h>
+#include "loc_misc_utils.h"
 
 namespace loc_core
 {
@@ -48,40 +49,21 @@
         mydi = (*getConcreteDIFunc)(id);
     }
     else {
-        // first call to this function, symbol not yet loaded
-        if (NULL == dataItemLibHandle) {
-            LOC_LOGD("Loaded library %s",DATA_ITEMS_LIB_NAME);
-            dataItemLibHandle = dlopen(DATA_ITEMS_LIB_NAME, RTLD_NOW);
-            if (NULL == dataItemLibHandle) {
-                // dlopen failed.
-                const char * err = dlerror();
-                if (NULL == err)
-                {
-                    err = "Unknown";
-                }
-                LOC_LOGE("%s:%d]: failed to load library %s; error=%s",
-                     __func__, __LINE__, DATA_ITEMS_LIB_NAME, err);
-            }
-        }
+        getConcreteDIFunc = (get_concrete_data_item_fn * )
+                dlGetSymFromLib(dataItemLibHandle, DATA_ITEMS_LIB_NAME, DATA_ITEMS_GET_CONCRETE_DI);
 
-        // load sym - if dlopen handle is obtained and symbol is not yet obtained
-        if (NULL != dataItemLibHandle) {
-            getConcreteDIFunc = (get_concrete_data_item_fn * )
-                                    dlsym(dataItemLibHandle, DATA_ITEMS_GET_CONCRETE_DI);
-            if (NULL != getConcreteDIFunc) {
-                LOC_LOGD("Loaded function %s : %p",DATA_ITEMS_GET_CONCRETE_DI,getConcreteDIFunc);
-                mydi = (*getConcreteDIFunc)(id);
+        if (NULL != getConcreteDIFunc) {
+            LOC_LOGd("Loaded function %s : %p", DATA_ITEMS_GET_CONCRETE_DI, getConcreteDIFunc);
+            mydi = (*getConcreteDIFunc)(id);
+        }
+        else {
+            // dlysm failed.
+            const char * err = dlerror();
+            if (NULL == err)
+            {
+                err = "Unknown";
             }
-            else {
-                // dlysm failed.
-                const char * err = dlerror();
-                if (NULL == err)
-                {
-                    err = "Unknown";
-                }
-                LOC_LOGE("%s:%d]: failed to find symbol %s; error=%s",
-                         __func__, __LINE__, DATA_ITEMS_GET_CONCRETE_DI, err);
-            }
+            LOC_LOGe("failed to find symbol %s; error=%s", DATA_ITEMS_GET_CONCRETE_DI, err);
         }
     }
     return mydi;
diff --git a/core/loc_core_log.cpp b/core/loc_core_log.cpp
index ddf18ec..904f94b 100644
--- a/core/loc_core_log.cpp
+++ b/core/loc_core_log.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2015, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -53,7 +53,7 @@
 }
 
 /* GPS status names */
-static const loc_name_val_s_type gps_status_name[] =
+DECLARE_TBL(gps_status_name) =
 {
     NAME_VAL( LOC_GPS_STATUS_NONE ),
     NAME_VAL( LOC_GPS_STATUS_SESSION_BEGIN ),
@@ -61,18 +61,16 @@
     NAME_VAL( LOC_GPS_STATUS_ENGINE_ON ),
     NAME_VAL( LOC_GPS_STATUS_ENGINE_OFF ),
 };
-static const int gps_status_num = sizeof(gps_status_name) / sizeof(loc_name_val_s_type);
 
 /* Find Android GPS status name */
 const char* loc_get_gps_status_name(LocGpsStatusValue gps_status)
 {
-   return loc_get_name_from_val(gps_status_name, gps_status_num,
-         (long) gps_status);
+    return loc_get_name_from_val(gps_status_name_tbl, (int64_t) gps_status);
 }
 
 
 
-static const loc_name_val_s_type loc_eng_position_modes[] =
+DECLARE_TBL(loc_eng_position_modes) =
 {
     NAME_VAL( LOC_POSITION_MODE_STANDALONE ),
     NAME_VAL( LOC_POSITION_MODE_MS_BASED ),
@@ -83,25 +81,23 @@
     NAME_VAL( LOC_POSITION_MODE_RESERVED_4 ),
     NAME_VAL( LOC_POSITION_MODE_RESERVED_5 )
 };
-static const int loc_eng_position_mode_num = sizeof(loc_eng_position_modes) / sizeof(loc_name_val_s_type);
 
 const char* loc_get_position_mode_name(LocGpsPositionMode mode)
 {
-    return loc_get_name_from_val(loc_eng_position_modes, loc_eng_position_mode_num, (long) mode);
+    return loc_get_name_from_val(loc_eng_position_modes_tbl, (int64_t) mode);
 }
 
 
 
-static const loc_name_val_s_type loc_eng_position_recurrences[] =
+DECLARE_TBL(loc_eng_position_recurrences) =
 {
     NAME_VAL( LOC_GPS_POSITION_RECURRENCE_PERIODIC ),
     NAME_VAL( LOC_GPS_POSITION_RECURRENCE_SINGLE )
 };
-static const int loc_eng_position_recurrence_num = sizeof(loc_eng_position_recurrences) / sizeof(loc_name_val_s_type);
 
 const char* loc_get_position_recurrence_name(LocGpsPositionRecurrence recur)
 {
-    return loc_get_name_from_val(loc_eng_position_recurrences, loc_eng_position_recurrence_num, (long) recur);
+    return loc_get_name_from_val(loc_eng_position_recurrences_tbl, (int64_t) recur);
 }
 
 const char* loc_get_aiding_data_mask_names(LocGpsAidingData /*data*/)
@@ -110,7 +106,7 @@
 }
 
 
-static const loc_name_val_s_type loc_eng_agps_types[] =
+DECLARE_TBL(loc_eng_agps_types) =
 {
     NAME_VAL( LOC_AGPS_TYPE_INVALID ),
     NAME_VAL( LOC_AGPS_TYPE_ANY ),
@@ -118,44 +114,41 @@
     NAME_VAL( LOC_AGPS_TYPE_C2K ),
     NAME_VAL( LOC_AGPS_TYPE_WWAN_ANY )
 };
-static const int loc_eng_agps_type_num = sizeof(loc_eng_agps_types) / sizeof(loc_name_val_s_type);
 
 const char* loc_get_agps_type_name(LocAGpsType type)
 {
-    return loc_get_name_from_val(loc_eng_agps_types, loc_eng_agps_type_num, (long) type);
+    return loc_get_name_from_val(loc_eng_agps_types_tbl, (int64_t) type);
 }
 
 
-static const loc_name_val_s_type loc_eng_ni_types[] =
+DECLARE_TBL(loc_eng_ni_types) =
 {
     NAME_VAL( LOC_GPS_NI_TYPE_VOICE ),
     NAME_VAL( LOC_GPS_NI_TYPE_UMTS_SUPL ),
     NAME_VAL( LOC_GPS_NI_TYPE_UMTS_CTRL_PLANE ),
     NAME_VAL( LOC_GPS_NI_TYPE_EMERGENCY_SUPL )
 };
-static const int loc_eng_ni_type_num = sizeof(loc_eng_ni_types) / sizeof(loc_name_val_s_type);
 
 const char* loc_get_ni_type_name(LocGpsNiType type)
 {
-    return loc_get_name_from_val(loc_eng_ni_types, loc_eng_ni_type_num, (long) type);
+    return loc_get_name_from_val(loc_eng_ni_types_tbl, (int64_t) type);
 }
 
 
-static const loc_name_val_s_type loc_eng_ni_responses[] =
+DECLARE_TBL(loc_eng_ni_responses) =
 {
     NAME_VAL( LOC_GPS_NI_RESPONSE_ACCEPT ),
     NAME_VAL( LOC_GPS_NI_RESPONSE_DENY ),
     NAME_VAL( LOC_GPS_NI_RESPONSE_DENY )
 };
-static const int loc_eng_ni_reponse_num = sizeof(loc_eng_ni_responses) / sizeof(loc_name_val_s_type);
 
 const char* loc_get_ni_response_name(LocGpsUserResponseType response)
 {
-    return loc_get_name_from_val(loc_eng_ni_responses, loc_eng_ni_reponse_num, (long) response);
+    return loc_get_name_from_val(loc_eng_ni_responses_tbl, (int64_t) response);
 }
 
 
-static const loc_name_val_s_type loc_eng_ni_encodings[] =
+DECLARE_TBL(loc_eng_ni_encodings) =
 {
     NAME_VAL( LOC_GPS_ENC_NONE ),
     NAME_VAL( LOC_GPS_ENC_SUPL_GSM_DEFAULT ),
@@ -163,55 +156,51 @@
     NAME_VAL( LOC_GPS_ENC_SUPL_UCS2 ),
     NAME_VAL( LOC_GPS_ENC_UNKNOWN )
 };
-static const int loc_eng_ni_encoding_num = sizeof(loc_eng_ni_encodings) / sizeof(loc_name_val_s_type);
 
 const char* loc_get_ni_encoding_name(LocGpsNiEncodingType encoding)
 {
-    return loc_get_name_from_val(loc_eng_ni_encodings, loc_eng_ni_encoding_num, (long) encoding);
+    return loc_get_name_from_val(loc_eng_ni_encodings_tbl, (int64_t) encoding);
 }
 
-static const loc_name_val_s_type loc_eng_agps_bears[] =
+DECLARE_TBL(loc_eng_agps_bears) =
 {
     NAME_VAL( AGPS_APN_BEARER_INVALID ),
     NAME_VAL( AGPS_APN_BEARER_IPV4 ),
     NAME_VAL( AGPS_APN_BEARER_IPV6 ),
     NAME_VAL( AGPS_APN_BEARER_IPV4V6 )
 };
-static const int loc_eng_agps_bears_num = sizeof(loc_eng_agps_bears) / sizeof(loc_name_val_s_type);
 
 const char* loc_get_agps_bear_name(AGpsBearerType bearer)
 {
-    return loc_get_name_from_val(loc_eng_agps_bears, loc_eng_agps_bears_num, (long) bearer);
+    return loc_get_name_from_val(loc_eng_agps_bears_tbl, (int64_t) bearer);
 }
 
-static const loc_name_val_s_type loc_eng_server_types[] =
+DECLARE_TBL(loc_eng_server_types) =
 {
     NAME_VAL( LOC_AGPS_CDMA_PDE_SERVER ),
     NAME_VAL( LOC_AGPS_CUSTOM_PDE_SERVER ),
     NAME_VAL( LOC_AGPS_MPC_SERVER ),
     NAME_VAL( LOC_AGPS_SUPL_SERVER )
 };
-static const int loc_eng_server_types_num = sizeof(loc_eng_server_types) / sizeof(loc_name_val_s_type);
 
 const char* loc_get_server_type_name(LocServerType type)
 {
-    return loc_get_name_from_val(loc_eng_server_types, loc_eng_server_types_num, (long) type);
+    return loc_get_name_from_val(loc_eng_server_types_tbl, (int64_t) type);
 }
 
-static const loc_name_val_s_type loc_eng_position_sess_status_types[] =
+DECLARE_TBL(loc_eng_position_sess_status_types) =
 {
     NAME_VAL( LOC_SESS_SUCCESS ),
     NAME_VAL( LOC_SESS_INTERMEDIATE ),
     NAME_VAL( LOC_SESS_FAILURE )
 };
-static const int loc_eng_position_sess_status_num = sizeof(loc_eng_position_sess_status_types) / sizeof(loc_name_val_s_type);
 
 const char* loc_get_position_sess_status_name(enum loc_sess_status status)
 {
-    return loc_get_name_from_val(loc_eng_position_sess_status_types, loc_eng_position_sess_status_num, (long) status);
+    return loc_get_name_from_val(loc_eng_position_sess_status_types_tbl, (int64_t) status);
 }
 
-static const loc_name_val_s_type loc_eng_agps_status_names[] =
+DECLARE_TBL(loc_eng_agps_status_names) =
 {
     NAME_VAL( LOC_GPS_REQUEST_AGPS_DATA_CONN ),
     NAME_VAL( LOC_GPS_RELEASE_AGPS_DATA_CONN ),
@@ -219,9 +208,8 @@
     NAME_VAL( LOC_GPS_AGPS_DATA_CONN_DONE ),
     NAME_VAL( LOC_GPS_AGPS_DATA_CONN_FAILED )
 };
-static const int loc_eng_agps_status_num = sizeof(loc_eng_agps_status_names) / sizeof(loc_name_val_s_type);
 
 const char* loc_get_agps_status_name(LocAGpsStatusValue status)
 {
-    return loc_get_name_from_val(loc_eng_agps_status_names, loc_eng_agps_status_num, (long) status);
+    return loc_get_name_from_val(loc_eng_agps_status_names_tbl, (int64_t) status);
 }
diff --git a/core/observer/IFrameworkActionReq.h b/core/observer/IFrameworkActionReq.h
index 4be947f..138508c 100644
--- a/core/observer/IFrameworkActionReq.h
+++ b/core/observer/IFrameworkActionReq.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -30,8 +30,11 @@
 #ifndef __IFRAMEWORKACTIONREQ_H__
 #define __IFRAMEWORKACTIONREQ_H__
 
+#include <string>
 #include  <DataItemId.h>
 
+using namespace std;
+
 namespace loc_core
 {
 
@@ -77,7 +80,7 @@
      *
      * @param None
      */
-    virtual bool connectBackhaul() = 0;
+    virtual bool connectBackhaul(const string& clientName) = 0;
 
     /**
      * @brief Disconnects the WWANbackhaul
@@ -85,7 +88,7 @@
      *
      * @param None
      */
-    virtual bool disconnectBackhaul() = 0;
+    virtual bool disconnectBackhaul(const string& clientName) = 0;
 #endif
 
     /**
diff --git a/core/observer/IOsObserver.h b/core/observer/IOsObserver.h
index f661828..a25bb9f 100644
--- a/core/observer/IOsObserver.h
+++ b/core/observer/IOsObserver.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -91,8 +91,8 @@
     inline virtual void turnOn (DataItemId /*dit*/, int /*timeOut*/){}
     inline virtual void turnOff (DataItemId /*dit*/) {}
 #ifdef USE_GLIB
-    inline virtual bool connectBackhaul() { return false; }
-    inline virtual bool disconnectBackhaul() { return false; }
+    inline virtual bool connectBackhaul(const string& clientName) { return false; }
+    inline virtual bool disconnectBackhaul(const string& clientName) { return false; }
 #endif
 
     /**
diff --git a/etc/Android.bp b/etc/Android.bp
new file mode 100644
index 0000000..05ecd90
--- /dev/null
+++ b/etc/Android.bp
@@ -0,0 +1,58 @@
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_qcom_sm7250_gps_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-BSD
+    default_applicable_licenses: ["hardware_qcom_sm7250_gps_license"],
+}
+
+prebuilt_etc {
+
+    name: "gps.conf",
+    vendor: true,
+    src: "gps.conf",
+}
+
+prebuilt_etc {
+
+    name: "flp.conf",
+    vendor: true,
+    src: "flp.conf",
+}
+
+prebuilt_etc {
+
+    name: "gnss_antenna_info.conf",
+    vendor: true,
+    src: "gnss_antenna_info.conf",
+}
+
+prebuilt_etc {
+    name: "gnss@2.0-base.policy",
+    vendor: true,
+    sub_dir: "seccomp_policy",
+    src: "seccomp_policy/gnss@2.0-base.policy",
+}
+
+prebuilt_etc {
+    name: "gnss@2.0-xtra-daemon.policy",
+    vendor: true,
+    sub_dir: "seccomp_policy",
+    src: "seccomp_policy/gnss@2.0-xtra-daemon.policy",
+}
+
+prebuilt_etc {
+    name: "gnss@2.0-xtwifi-client.policy",
+    vendor: true,
+    sub_dir: "seccomp_policy",
+    src: "seccomp_policy/gnss@2.0-xtwifi-client.policy",
+}
+
+prebuilt_etc {
+    name: "gnss@2.0-xtwifi-inet-agent.policy",
+    vendor: true,
+    sub_dir: "seccomp_policy",
+    src: "seccomp_policy/gnss@2.0-xtwifi-inet-agent.policy",
+}
diff --git a/etc/Android.mk b/etc/Android.mk
deleted file mode 100644
index 6746876..0000000
--- a/etc/Android.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-ifneq ($(BOARD_VENDOR_QCOM_LOC_PDK_FEATURE_SET),true)
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := gps.conf
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_SRC_FILES := gps.conf
-LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := flp.conf
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_SRC_FILES := flp.conf
-LOCAL_MODULE_PATH  := $(TARGET_OUT_VENDOR_ETC)
-include $(BUILD_PREBUILT)
-endif
diff --git a/etc/gnss_antenna_info.conf b/etc/gnss_antenna_info.conf
new file mode 100644
index 0000000..e037daa
--- /dev/null
+++ b/etc/gnss_antenna_info.conf
@@ -0,0 +1,135 @@
+###################################
+#####   ANTENNA INFORMATION   #####
+###################################
+
+###################################
+# ANTENNA INFO VECTOR SIZE
+###################################
+# The number of antenna info
+# structures in the vector. Each
+# entry in this vector is a structure
+# with the following elements:
+#
+# - CARRIER_FREQUENCY
+# - PC_OFFSET
+# - PC_VARIATION_CORRECTION
+# - PC_VARIATION_CORRECTION_UNC
+# - SIGNAL_GAIN_CORRECTION
+# - SIGNAL_GAIN_CORRECTION_UNC
+#
+# Notes:
+# CARRIER_FREQUENCY
+#   The carrier frequency in MHz.
+#
+# PC = PHASE CENTER
+#   PC_OFFSET is a structure with six
+#   elements: x, y, z and their associated uncertainties
+#   Phase center offset (PCO) is defined with
+#   respect to the origin of the Android sensor coordinate system, e.g.,
+#   center of primary screen for mobiles
+#
+# PC_VARIATION_CORRECTION
+#   2D vectors representing the phase center variation (PCV) corrections,
+#   in millimeters, at regularly spaced azimuthal angle (theta) and zenith angle
+#   (phi). The PCV correction is added to the phase measurement to obtain the
+#   corrected value.
+#   The azimuthal angle, theta, is defined with respect to the X axis of the
+#   Android sensor coordinate system, increasing toward the Y axis. The zenith
+#   angle, phi, is defined with respect to the Z axis of the Android Sensor
+#   coordinate system, increasing toward the X-Y plane.
+#   Each row vector (outer vectors) represents a fixed theta. The first row
+#   corresponds to a theta angle of 0 degrees. The last row corresponds to a
+#   theta angle of (360 - deltaTheta) degrees, where deltaTheta is the regular
+#   spacing between azimuthal angles, i.e., deltaTheta = 360 / (number of rows).
+#   The columns (inner vectors) represent fixed zenith angles, beginning at 0
+#   degrees and ending at 180 degrees. They are separated by deltaPhi, the regular
+#   spacing between zenith angles, i.e., deltaPhi = 180 / (number of columns - 1).
+#
+# PC_VARIATION_CORRECTION_UNC
+#   2D vectors of 1-sigma uncertainty in millimeters associated with the PCV
+#   correction values.
+#
+# SIGNAL_GAIN_CORRECTION
+#   2D vectors representing the signal gain corrections at regularly spaced
+#   azimuthal angle (theta) and zenith angle (phi). The values are calculated or
+#   measured at the antenna feed point without considering the radio and receiver
+#   noise figure and path loss contribution, in dBi, i.e., decibel over isotropic
+#   antenna with the same total power. The signal gain correction is added the
+#   signal gain measurement to obtain the corrected value.
+#   The azimuthal angle, theta, is defined with respect to the X axis of the
+#   Android sensor coordinate system, increasing toward the Y axis. The zenith
+#   angle, phi, is defined with respect to the Z axis of the Android Sensor
+#   coordinate system, increasing toward the X-Y plane.
+#   Each row vector (outer vectors) represents a fixed theta. The first row
+#   corresponds to a theta angle of 0 degrees. The last row corresponds to a
+#   theta angle of (360 - deltaTheta) degrees, where deltaTheta is the regular
+#   spacing between azimuthal angles, i.e., deltaTheta = 360 / (number of rows).
+#   The columns (inner vectors) represent fixed zenith angles, beginning at 0
+#   degrees and ending at 180 degrees. They are separated by deltaPhi, the regular
+#   spacing between zenith angles, i.e., deltaPhi = 180 / (number of columns - 1).
+#
+# SIGNAL_GAIN_CORRECTION_UNC
+#   2D vectors of 1-sigma uncertainty in dBi associated with the signal
+#   gain correction values.
+#
+# The number of rows and columns could be the same for PC variation correction
+# and signal gain corrections, or could be different
+# If the former then NUMBER_OF_ROWS_ and NUMBER_OF_COLUMNS_ are specified once
+# only, if the latter then NUMBER_OF_ROWS_ and NUMBER_OF_COLUMNS_ represent
+# the number of rows/columns for PC variation correction and
+# NUMBER_OF_ROWS_SGC_ and NUMBER_OF_COLUMNS_SGC_ represent the number of
+# rows/columns for signal gain corrections
+
+# ANTENNA_INFO_VECTOR_SIZE must be non zero if antenna corrections are sent
+# ANTENNA_INFO_VECTOR_SIZE = 2
+
+CARRIER_FREQUENCY_0 = 1575.42
+
+PC_OFFSET_0 = 1.2 0.1 3.4 0.2 5.6 0.3
+
+NUMBER_OF_ROWS_0 = 3
+NUMBER_OF_COLUMNS_0 = 4
+
+PC_VARIATION_CORRECTION_0_ROW_0 = 11.22 33.44 55.66 77.88
+PC_VARIATION_CORRECTION_0_ROW_1 = 10.2 30.4 50.6 70.8
+PC_VARIATION_CORRECTION_0_ROW_2 = 12.2 34.4 56.6 78.8
+
+PC_VARIATION_CORRECTION_UNC_0_ROW_0 = 0.1 0.2 0.3 0.4
+PC_VARIATION_CORRECTION_UNC_0_ROW_1 = 1.1 1.2 1.3 1.4
+PC_VARIATION_CORRECTION_UNC_0_ROW_2 = 2.1 2.2 2.3 2.4
+
+SIGNAL_GAIN_CORRECTION_0_ROW_0 = 9.8 8.7 7.6 6.5
+SIGNAL_GAIN_CORRECTION_0_ROW_1 = 5.4 4.3 3.2 2.1
+SIGNAL_GAIN_CORRECTION_0_ROW_2 = 1.3 2.4 3.5 4.6
+
+SIGNAL_GAIN_CORRECTION_UNC_0_ROW_0 = 0.11 0.22 0.33 0.44
+SIGNAL_GAIN_CORRECTION_UNC_0_ROW_1 = 0.55 0.66 0.77 0.88
+SIGNAL_GAIN_CORRECTION_UNC_0_ROW_2 = 0.91 0.92 0.93 0.94
+
+
+CARRIER_FREQUENCY_1 = 1227.6
+
+PC_OFFSET_1 = 3.4 0.2 5.6 0.3 1.2 0.1
+
+NUMBER_OF_ROWS_1 = 4
+NUMBER_OF_COLUMNS_1 = 2
+NUMBER_OF_ROWS_SGC_1 = 3
+NUMBER_OF_COLUMNS_SGC_1 = 4
+
+PC_VARIATION_CORRECTION_1_ROW_0 = 55.66 77.88
+PC_VARIATION_CORRECTION_1_ROW_1 = 11.22 33.44
+PC_VARIATION_CORRECTION_1_ROW_2 = 56.6 78.8
+PC_VARIATION_CORRECTION_1_ROW_3 = 12.2 34.4
+
+PC_VARIATION_CORRECTION_UNC_1_ROW_0 = 0.3 0.4
+PC_VARIATION_CORRECTION_UNC_1_ROW_1 = 1.1 1.2
+PC_VARIATION_CORRECTION_UNC_1_ROW_2 = 2.1 2.2
+PC_VARIATION_CORRECTION_UNC_1_ROW_3 = 0.1 0.2
+
+SIGNAL_GAIN_CORRECTION_1_ROW_0 = 7.6 6.5 5.4 4.3
+SIGNAL_GAIN_CORRECTION_1_ROW_1 = 1.3 2.4 9.8 8.7
+SIGNAL_GAIN_CORRECTION_1_ROW_2 = 1.4 2.5 3.6 4.7
+
+SIGNAL_GAIN_CORRECTION_UNC_1_ROW_0 = 0.91 0.92 0.55 0.66
+SIGNAL_GAIN_CORRECTION_UNC_1_ROW_1 = 0.11 0.22 0.93 0.94
+SIGNAL_GAIN_CORRECTION_UNC_1_ROW_2 = 0.95 0.96 0.33 0.44
diff --git a/etc/gps.conf b/etc/gps.conf
index 1d4e233..75f12f2 100644
--- a/etc/gps.conf
+++ b/etc/gps.conf
@@ -1,17 +1,10 @@
-#Version check for XTRA
-#DISABLE = 0
-#AUTO    = 1
-#XTRA2   = 2
-#XTRA3   = 3
-XTRA_VERSION_CHECK=0
-
 # Error Estimate
 # _SET = 1
 # _CLEAR = 0
 ERR_ESTIMATE=0
 
 #NTP server
-NTP_SERVER=time.izatcloud.net
+NTP_SERVER=time.xtracloud.net
 
 #XTRA CA path
 XTRA_CA_PATH=/usr/lib/ssl-1.1/certs
@@ -81,10 +74,12 @@
 ####################################
 #  LTE Positioning Profile Settings
 ####################################
+# LPP_PROFILE is a bit mask
 # 0: Enable RRLP on LTE(Default)
-# 1: Enable LPP_User_Plane on LTE
-# 2: Enable LPP_Control_Plane
-# 3: Enable both LPP_User_Plane and LPP_Control_Plane
+# 0x1: LPP User Plane
+# 0x2: LPP Control Plane
+# 0x4: LPP User Plane for NR5G
+# 0x8: LPP Control Plane for NR5G
 LPP_PROFILE = 2
 
 ####################################
@@ -100,6 +95,15 @@
 # NMEA provider (1=Modem Processor, 0=Application Processor)
 NMEA_PROVIDER=0
 
+################################
+# NMEA TAG BLOCK GROUPING
+################################
+# NMEA tag block grouping is only applicable to GSA
+# Default is disabled
+# 0 - disabled
+# 1 - enabled
+NMEA_TAG_BLOCK_GROUPING_ENABLED = 0
+
 # Customized NMEA GGA fix quality that can be used to tell
 # whether SENSOR contributed to the fix.
 #
@@ -124,6 +128,15 @@
 # 1 - enabled
 CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED = 0
 
+################################
+# NMEA Reporting Rate Config, valid only when NMEA_PROVIDER is set to "0"
+################################
+# NMEA Reporting Rate
+# Set it to "1HZ" for 1Hz NMEA Reporting
+# Set it to "NHZ" for NHz NMEA Reporting
+#Default : NHZ (overridden by position update rate if set to lower rates)
+NMEA_REPORT_RATE=NHZ
+
 # Mark if it is a SGLTE target (1=SGLTE, 0=nonSGLTE)
 SGLTE_TARGET=0
 
@@ -184,16 +197,6 @@
 # is able to acquire better timing information
 AP_TIMESTAMP_UNCERTAINTY = 10
 
-##################################################
-# QDR engine availability status
-##################################################
-# 0 : NO QDR (default)
-# 1 : QDR enabled
-# This settings enables QDR Configuration for
-# automotive use case, if enabled then
-# DR_AP_Service needs to be enabled in izat.conf
-#EXTERNAL_DR_ENABLED = 0
-
 #####################################
 # DR_SYNC Pulse Availability
 #####################################
@@ -318,8 +321,9 @@
 ##################################################
 # 0 : Enable QTI GNSS (default)
 # 1 : Enable QCSR SS5
-# This setting use to select between QTI GNSS
-# and QCSR SS5 hardware receiver.
+# 2 : Enable PDS API
+# This setting use to select between QTI GNSS,
+# QCSR SS5 hardware receiver, and PDS API.
 # By default QTI GNSS receiver is enabled.
 # GNSS_DEPLOYMENT = 0
 
@@ -343,3 +347,45 @@
 V_LEVEL_TIME_DEPTH = 200
 V_LEVEL_MAX_CAPACITY = 400
 
+##################################################
+# Allow buffer diag log packets when diag memory allocation
+# fails during boot up time.
+##################################################
+BUFFER_DIAG_LOGGING = 1
+
+#######################################
+#  NTRIP CLIENT LIBRARY NAME
+#######################################
+# NTRIP_CLIENT_LIB_NAME =
+
+##################################################
+# Correction Data Framework settings
+# Default values:
+# CDFW_SOURCE_PRIORITY_1 = INTERNAL_1 RTCM
+# CDFW_INJECT_DATA_INTERVAL = 600000 //10 mins
+# CDFW_RTCM_MESSAGE_INTERVAL = 1000  //1 second
+#
+# If multiple sources coexist on a PL,
+# the prorioty sequence can be set by the integer number.
+# PRIORITY_1 is higher than PRIORITY_2, for example,
+# CDFW_SOURCE_PRIORITY_1 = INTERNAL_1 RTCM
+# CDFW_SOURCE_PRIORITY_2 = CV2X RTCM
+##################################################
+
+##################################################
+# RF LOSS
+# The loss in 0.1 dbHz from the C/N0 at the antenna port
+# These values must be configured by OEM if not
+# supported in QMI LOC message
+# There is one entry for each signal type
+##################################################
+RF_LOSS_GPS = 0
+RF_LOSS_GPS_L5 = 0
+RF_LOSS_GLO_LEFT = 0
+RF_LOSS_GLO_CENTER = 0
+RF_LOSS_GLO_RIGHT = 0
+RF_LOSS_BDS = 0
+RF_LOSS_BDS_B2A = 0
+RF_LOSS_GAL = 0
+RF_LOSS_GAL_E5 = 0
+RF_LOSS_NAVIC = 0
diff --git a/etc/seccomp_policy/gnss@2.0-base.policy b/etc/seccomp_policy/gnss@2.0-base.policy
new file mode 100644
index 0000000..0a2e17b
--- /dev/null
+++ b/etc/seccomp_policy/gnss@2.0-base.policy
@@ -0,0 +1,119 @@
+#*******************************************************************************
+#  Copyright (c) 2020 The Linux Foundation. All rights reserved.
+#
+#  Redistribution and use in source and binary forms, with or without
+#  modification, are permitted provided that the following conditions are
+#  met:
+#      * Redistributions of source code must retain the above copyright
+#        notice, this list of conditions and the following disclaimer.
+#      * Redistributions in binary form must reproduce the above
+#        copyright notice, this list of conditions and the following
+#        disclaimer in the documentation and/or other materials provided
+#        with the distribution.
+#      * Neither the name of The Linux Foundation, nor the names of its
+#        contributors may be used to endorse or promote products derived
+#        from this software without specific prior written permission.
+#
+#  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+#  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+#  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+#  ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+#  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+#  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+#  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+#  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+#  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#******************************************************************************
+
+clone: 1
+close: 1
+connect: 1
+execve: 1
+exit_group: 1
+exit: 1
+faccessat: 1
+fcntl: 1
+fstat: 1
+fstatfs: 1
+futex: 1
+getpid: 1
+getuid: 1
+getgid: 1
+getegid: 1
+getgroups: 1
+geteuid: 1
+umask: 1
+getrandom: 1
+mmap: arg2 in ~PROT_EXEC || arg2 in ~PROT_WRITE
+mprotect: arg2 in ~PROT_EXEC || arg2 in ~PROT_WRITE
+mremap: 1
+munmap: 1
+newfstatat: 1
+openat: 1
+#prctl: arg0 == PR_SET_VMA || arg0 == PR_SET_NO_NEW_PRIVS || arg0 == PR_GET_DUMPABLE || arg0 == PR_SET_SECCOMP || arg0 == 0x37 /* PR_??? */
+prctl: 1
+pread64: 1
+read: 1
+pwrite64: 1
+write: 1
+writev: 1
+readlinkat: 1
+restart_syscall: 1
+rt_sigaction: 1
+rt_sigprocmask: 1
+rt_sigreturn: 1
+sched_getscheduler: 1
+set_tid_address: 1
+sigaltstack: 1
+unlinkat: 1
+lseek: 1
+##ioctl: arg1 == _IOC(_IOC_NONE || arg1 == _IOC(_IOC_READ || arg1 == VSOC_MAYBE_SEND_INTERRUPT_TO_HOST
+ioctl: 1
+clock_gettime: 1
+
+
+socket: arg0 == AF_INET6 || arg0 == AF_UNIX || arg0 == AF_QIPCRTR
+connect: 1
+setsockopt: 1
+getsockname: 1
+socketpair: 1
+ppoll: 1
+pselect6: 1
+accept4: 1
+listen: 1
+bind: 1
+pipe2: 1
+
+recvmsg: 1
+sendmsg: 1
+
+sendto: 1
+recvfrom: 1
+
+getsockname: 1
+nanosleep: 1
+clone: 1
+setsockopt: 1
+getsockopt: 1
+madvise: 1
+
+getitimer: 1
+setitimer: 1
+getpid: 1
+bind: 1
+listen: 1
+getpeername: 1
+socketpair: 1
+wait4: 1
+chown: 1
+fchown: 1
+lchown: 1
+umask: 1
+mmap2: 1
+fstat64: 1
+fstatat64: 1
+_llseek: 1
+geteuid: 1
diff --git a/etc/seccomp_policy/gnss@2.0-xtra-daemon.policy b/etc/seccomp_policy/gnss@2.0-xtra-daemon.policy
new file mode 100644
index 0000000..19b67bb
--- /dev/null
+++ b/etc/seccomp_policy/gnss@2.0-xtra-daemon.policy
@@ -0,0 +1,48 @@
+#*******************************************************************************
+#  Copyright (c) 2020 The Linux Foundation. All rights reserved.
+#
+#  Redistribution and use in source and binary forms, with or without
+#  modification, are permitted provided that the following conditions are
+#  met:
+#      * Redistributions of source code must retain the above copyright
+#        notice, this list of conditions and the following disclaimer.
+#      * Redistributions in binary form must reproduce the above
+#        copyright notice, this list of conditions and the following
+#        disclaimer in the documentation and/or other materials provided
+#        with the distribution.
+#      * Neither the name of The Linux Foundation, nor the names of its
+#        contributors may be used to endorse or promote products derived
+#        from this software without specific prior written permission.
+#
+#  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+#  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+#  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+#  ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+#  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+#  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+#  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+#  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+#  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#******************************************************************************
+bind: 1
+getrlimit: 1
+
+pipe2: 1
+
+sched_getaffinity: 1
+timerfd_create: 1
+unlinkat: 1
+setpriority: 1
+
+epoll_create1: 1
+epoll_ctl: 1
+epoll_pwait: 1
+timerfd_settime: 1
+
+fdatasync: 1
+madvise: 1
+ftruncate: 1
+
diff --git a/etc/seccomp_policy/gnss@2.0-xtwifi-client.policy b/etc/seccomp_policy/gnss@2.0-xtwifi-client.policy
new file mode 100644
index 0000000..38a41f9
--- /dev/null
+++ b/etc/seccomp_policy/gnss@2.0-xtwifi-client.policy
@@ -0,0 +1,73 @@
+
+#*******************************************************************************
+#  Copyright (c) 2020 The Linux Foundation. All rights reserved.
+#
+#  Redistribution and use in source and binary forms, with or without
+#  modification, are permitted provided that the following conditions are
+#  met:
+#      * Redistributions of source code must retain the above copyright
+#        notice, this list of conditions and the following disclaimer.
+#      * Redistributions in binary form must reproduce the above
+#        copyright notice, this list of conditions and the following
+#        disclaimer in the documentation and/or other materials provided
+#        with the distribution.
+#      * Neither the name of The Linux Foundation, nor the names of its
+#        contributors may be used to endorse or promote products derived
+#        from this software without specific prior written permission.
+#
+#  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+#  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+#  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+#  ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+#  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+#  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+#  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+#  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+#  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#******************************************************************************
+
+fdatasync: 1
+getdents64: 1
+gettimeofday: 1
+ioctl: 1
+lseek: 1
+madvise: 1
+mkdirat: 1
+pwrite64: 1
+
+timerfd_create: 1
+timerfd_settime: 1
+epoll_create1: 1
+epoll_pwait: 1
+epoll_ctl: 1
+
+sched_getaffinity: 1
+gettid: 1
+fchown: 1
+fchmod: 1
+fchmodat: 1
+getsockopt: 1
+fchownat: 1
+fstat: 1
+fstatfs: 1
+newfstatat: 1
+sendmsg: 1
+recvmsg: 1
+gettimeofday: 1
+setsockopt: 1
+rt_tgsigqueueinfo: 1
+ioctl: 1
+mmap: 1
+getuid32: 1
+getuid: 1
+fstat64: 1
+fstatat64: 1
+mkdir: 1
+rmdir: 1
+creat: 1
+chmod: 1
+lseek: 1
+geteuid32: 1
diff --git a/etc/seccomp_policy/gnss@2.0-xtwifi-inet-agent.policy b/etc/seccomp_policy/gnss@2.0-xtwifi-inet-agent.policy
new file mode 100644
index 0000000..024600a
--- /dev/null
+++ b/etc/seccomp_policy/gnss@2.0-xtwifi-inet-agent.policy
@@ -0,0 +1,43 @@
+
+#*******************************************************************************
+#  Copyright (c) 2020 The Linux Foundation. All rights reserved.
+#
+#  Redistribution and use in source and binary forms, with or without
+#  modification, are permitted provided that the following conditions are
+#  met:
+#      * Redistributions of source code must retain the above copyright
+#        notice, this list of conditions and the following disclaimer.
+#      * Redistributions in binary form must reproduce the above
+#        copyright notice, this list of conditions and the following
+#        disclaimer in the documentation and/or other materials provided
+#        with the distribution.
+#      * Neither the name of The Linux Foundation, nor the names of its
+#        contributors may be used to endorse or promote products derived
+#        from this software without specific prior written permission.
+#
+#  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+#  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+#  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+#  ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+#  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+#  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+#  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+#  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+#  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#******************************************************************************
+
+unlinkat: 1
+sched_getaffinity: 1
+newfstatat: 1
+fchmodat: 1
+madvise: 1
+mmap: 1
+getuid: 1
+getuid32: 1
+fstat64: 1
+fstatat64: 1
+gettimeofday: 1
+getdents64: 1
diff --git a/geofence/Android.bp b/geofence/Android.bp
new file mode 100644
index 0000000..1c57f24
--- /dev/null
+++ b/geofence/Android.bp
@@ -0,0 +1,40 @@
+
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_qcom_sm7250_gps_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-BSD
+    default_applicable_licenses: ["hardware_qcom_sm7250_gps_license"],
+}
+
+cc_library_shared {
+
+    name: "libgeofencing",
+    vendor: true,
+
+
+
+    srcs: [
+        "GeofenceAdapter.cpp",
+        "location_geofence.cpp",
+    ],
+
+    shared_libs: [
+        "libutils",
+        "libcutils",
+        "libgps.utils",
+        "liblog",
+        "libloc_core",
+    ],
+
+    header_libs: [
+        "libgps.utils_headers",
+        "libloc_core_headers",
+        "libloc_pla_headers",
+        "liblocation_api_headers",
+    ],
+
+    cflags: GNSS_CFLAGS,
+}
diff --git a/geofence/Android.mk b/geofence/Android.mk
deleted file mode 100644
index 133d408..0000000
--- a/geofence/Android.mk
+++ /dev/null
@@ -1,38 +0,0 @@
-ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),)
-ifneq ($(BUILD_TINY_ANDROID),true)
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libgeofencing
-LOCAL_SANITIZE += $(GNSS_SANITIZE)
-# activate the following line for debug purposes only, comment out for production
-#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES:= \
-    GeofenceAdapter.cpp \
-    location_geofence.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-        libutils \
-        libcutils \
-        libgps.utils \
-        liblog \
-        libloc_core
-
-LOCAL_HEADER_LIBRARIES := \
-    libgps.utils_headers \
-    libloc_core_headers \
-    libloc_pla_headers \
-    liblocation_api_headers
-
-LOCAL_PRELINK_MODULE := false
-LOCAL_CFLAGS += $(GNSS_CFLAGS)
-include $(BUILD_SHARED_LIBRARY)
-
-endif # not BUILD_TINY_ANDROID
-endif # BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE
-
diff --git a/geofence/GeofenceAdapter.cpp b/geofence/GeofenceAdapter.cpp
index e299589..1aeea0a 100644
--- a/geofence/GeofenceAdapter.cpp
+++ b/geofence/GeofenceAdapter.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2021, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -37,14 +37,14 @@
 
 GeofenceAdapter::GeofenceAdapter() :
     LocAdapterBase(0,
-                    LocContext::getLocContext(
-                        NULL,
-                        NULL,
-                        LocContext::mLocationHalName,
-                        false),
-                    true /*isMaster*/)
+                   LocContext::getLocContext(LocContext::mLocationHalName),
+                   true /*isMaster*/, nullptr, true)
 {
     LOC_LOGD("%s]: Constructor", __func__);
+
+    // at last step, let us inform adapater base that we are done
+    // with initialization, e.g.: ready to process handleEngineUpEvent
+    doneInit();
 }
 
 void
diff --git a/geofence/configure.ac b/geofence/configure.ac
index 8e3cd81..74eae7a 100644
--- a/geofence/configure.ac
+++ b/geofence/configure.ac
@@ -1,6 +1,6 @@
 AC_PREREQ(2.61)
 AC_INIT([location-geofence], 1.0.0)
-AM_INIT_AUTOMAKE([foreign])
+AM_INIT_AUTOMAKE([foreign subdir-objects])
 AC_CONFIG_SRCDIR([Makefile.am])
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_MACRO_DIR([m4])
diff --git a/gnss/Agps.cpp b/gnss/Agps.cpp
index 9255f88..0b95f99 100644
--- a/gnss/Agps.cpp
+++ b/gnss/Agps.cpp
@@ -448,7 +448,7 @@
         mAPN  = NULL;
     }
 
-    if (NULL == apn || len <= 0 || len > MAX_APN_LEN || strlen(apn) != len) {
+    if (NULL == apn || len > MAX_APN_LEN || strlen(apn) != len) {
         LOC_LOGD("Invalid apn len (%d) or null apn", len);
         mAPN = NULL;
         mAPNLen = 0;
@@ -590,7 +590,7 @@
     sm->setApnTypeMask(apnTypeMask);
 
     /* Invoke AGPS SM processing */
-    AgpsSubscriber subscriber(connHandle, false, false, apnTypeMask);
+    AgpsSubscriber subscriber(connHandle, true, false, apnTypeMask);
     sm->setCurrentSubscriber(&subscriber);
     /* Send subscriber event */
     sm->processAgpsEvent(AGPS_EVENT_SUBSCRIBE);
diff --git a/gnss/Agps.h b/gnss/Agps.h
index d559377..8a27cd9 100644
--- a/gnss/Agps.h
+++ b/gnss/Agps.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -37,6 +37,8 @@
 #include <loc_pla.h>
 #include <log_util.h>
 
+using namespace loc_util;
+
 /* ATL callback function pointers
  * Passed in by Adapter to AgpsManager */
 typedef std::function<void(
@@ -165,7 +167,7 @@
 
     /* Getter/Setter methods */
     void setAPN(char* apn, unsigned int len);
-    inline char* getAPN() const { return (char*)mAPN; }
+    inline char* getAPN() const { return mAPN; }
     inline uint32_t getAPNLen() const { return mAPNLen; }
     inline void setBearer(AGpsBearerType bearer) { mBearer = bearer; }
     inline LocApnTypeMask getApnTypeMask() const { return mApnTypeMask; }
diff --git a/gnss/Android.bp b/gnss/Android.bp
new file mode 100644
index 0000000..97c0efe
--- /dev/null
+++ b/gnss/Android.bp
@@ -0,0 +1,44 @@
+
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_qcom_sm7250_gps_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-BSD
+    default_applicable_licenses: ["hardware_qcom_sm7250_gps_license"],
+}
+
+cc_library_shared {
+
+    name: "libgnss",
+    vendor: true,
+
+
+
+    shared_libs: [
+        "libutils",
+        "libcutils",
+        "libdl",
+        "liblog",
+        "libloc_core",
+        "libgps.utils",
+    ],
+
+    srcs: [
+        "location_gnss.cpp",
+        "GnssAdapter.cpp",
+        "Agps.cpp",
+        "XtraSystemStatusObserver.cpp",
+        "NativeAgpsHandler.cpp",
+    ],
+
+    cflags: ["-fno-short-enums"] + GNSS_CFLAGS,
+    header_libs: [
+        "libgps.utils_headers",
+        "libloc_core_headers",
+        "libloc_pla_headers",
+        "liblocation_api_headers",
+    ],
+
+}
diff --git a/gnss/Android.mk b/gnss/Android.mk
deleted file mode 100644
index c1b5944..0000000
--- a/gnss/Android.mk
+++ /dev/null
@@ -1,49 +0,0 @@
-ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),)
-ifneq ($(BUILD_TINY_ANDROID),true)
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libgnss
-LOCAL_SANITIZE += $(GNSS_SANITIZE)
-# activate the following line for debug purposes only, comment out for production
-#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SHARED_LIBRARIES := \
-    libutils \
-    libcutils \
-    libdl \
-    liblog \
-    libloc_core \
-    libgps.utils
-
-LOCAL_SRC_FILES += \
-    location_gnss.cpp \
-    GnssAdapter.cpp \
-    Agps.cpp \
-    XtraSystemStatusObserver.cpp
-
-LOCAL_CFLAGS += \
-     -fno-short-enums \
-
-ifeq ($(TARGET_BUILD_VARIANT),user)
-   LOCAL_CFLAGS += -DTARGET_BUILD_VARIANT_USER
-endif
-
-LOCAL_HEADER_LIBRARIES := \
-    libgps.utils_headers \
-    libloc_core_headers \
-    libloc_pla_headers \
-    liblocation_api_headers
-
-LOCAL_CFLAGS += $(GNSS_CFLAGS)
-
-LOCAL_PRELINK_MODULE := false
-
-include $(BUILD_SHARED_LIBRARY)
-
-endif # not BUILD_TINY_ANDROID
-endif # BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE
diff --git a/gnss/GnssAdapter.cpp b/gnss/GnssAdapter.cpp
index f954488..c9ea7ca 100644
--- a/gnss/GnssAdapter.cpp
+++ b/gnss/GnssAdapter.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -46,13 +46,27 @@
 #include <Agps.h>
 #include <SystemStatus.h>
 #include <vector>
+#include <loc_misc_utils.h>
+#include <gps_extended_c.h>
 
 #define RAD2DEG    (180.0 / M_PI)
+#define DEG2RAD    (M_PI / 180.0)
 #define PROCESS_NAME_ENGINE_SERVICE "engine-service"
 #define MIN_TRACKING_INTERVAL (100) // 100 msec
 
+#define BILLION_NSEC (1000000000ULL)
+#define NMEA_MIN_THRESHOLD_MSEC (99)
+#define NMEA_MAX_THRESHOLD_MSEC (975)
+
+#define DGNSS_RANGE_UPDATE_TIME_10MIN_IN_MILLI  600000
+
 using namespace loc_core;
 
+static int loadEngHubForExternalEngine = 0;
+static loc_param_s_type izatConfParamTable[] = {
+    {"LOAD_ENGHUB_FOR_EXTERNAL_ENGINE", &loadEngHubForExternalEngine, nullptr,'n'}
+};
+
 /* Method to fetch status cb from loc_net_iface library */
 typedef AgpsCbInfo& (*LocAgpsGetAgpsCbInfo)(LocAgpsOpenResultCb openResultCb,
         LocAgpsCloseResultCb closeResultCb, void* userDataPtr);
@@ -61,14 +75,29 @@
         AGpsBearerType bearerType, void* userDataPtr);
 static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userDataPtr);
 
+typedef const CdfwInterface* (*getCdfwInterface)();
+
+typedef void getPdnTypeFromWds(const std::string& apnName, std::function<void(int)> pdnCb);
+
+inline bool GnssReportLoggerUtil::isLogEnabled() {
+    return (mLogLatency != nullptr);
+}
+
+inline void GnssReportLoggerUtil::log(const GnssLatencyInfo& gnssLatencyMeasInfo) {
+    if (mLogLatency != nullptr) {
+        mLogLatency(gnssLatencyMeasInfo);
+    }
+}
+
 GnssAdapter::GnssAdapter() :
     LocAdapterBase(0,
-                   LocContext::getLocContext(NULL,
-                                             NULL,
-                                             LocContext::mLocationHalName,
-                                             false),
+                   LocContext::getLocContext(LocContext::mLocationHalName),
                    true, nullptr, true),
     mEngHubProxy(new EngineHubProxyBase()),
+    mQDgnssListenerHDL(nullptr),
+    mCdfwInterface(nullptr),
+    mDGnssNeedReport(false),
+    mDGnssDataUsage(false),
     mLocPositionMode(),
     mNHzNeeded(false),
     mSPEAlreadyRunningAtHighestInterval(false),
@@ -78,6 +107,7 @@
     mAfwControlId(0),
     mNmeaMask(0),
     mGnssSvIdConfig(),
+    mGnssSeconaryBandConfig(),
     mGnssSvTypeConfig(),
     mGnssSvTypeConfigCb(nullptr),
     mLocConfigInfo{},
@@ -87,11 +117,13 @@
     mOdcpiRequestActive(false),
     mOdcpiTimer(this),
     mOdcpiRequest(),
+    mCallbackPriority(OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW),
     mSystemStatus(SystemStatus::getInstance(mMsgTask)),
     mServerUrl(":"),
     mXtraObserver(mSystemStatus->getOsObserver(), mMsgTask),
-    mLocSystemInfo{},
     mBlockCPIInfo{},
+    mDreIntEnabled(false),
+    mLocSystemInfo{},
     mNfwCb(NULL),
     mPowerOn(false),
     mAllowFlpNetworkFixes(0),
@@ -101,7 +133,14 @@
     mGnssMbSvIdUsedInPosition{},
     mGnssMbSvIdUsedInPosAvail(false),
     mSupportNfwControl(true),
-    mSystemPowerState(POWER_STATE_UNKNOWN)
+    mSystemPowerState(POWER_STATE_UNKNOWN),
+    mIsMeasCorrInterfaceOpen(false),
+    mIsAntennaInfoInterfaceOpened(false),
+    mLastDeleteAidingDataTime(0),
+    mDgnssState(0),
+    mSendNmeaConsent(false),
+    mDgnssLastNmeaBootTimeMilli(0),
+    mNativeAgpsHandler(mSystemStatus->getOsObserver(), *this)
 {
     LOC_LOGD("%s]: Constructor %p", __func__, this);
     mLocPositionMode.mode = LOC_POSITION_MODE_INVALID;
@@ -178,6 +217,7 @@
 
 bool
 GnssAdapter::checkAndSetSPEToRunforNHz(TrackingOptions & out) {
+
     // first check if NHz meas is needed at all, if not, just return false
     // if a NHz capable engine is subscribed for NHz measurement or NHz positions,
     // always run the SPE only session at 100ms TBF.
@@ -202,8 +242,7 @@
 
 void
 GnssAdapter::convertLocation(Location& out, const UlpLocation& ulpLocation,
-                             const GpsLocationExtended& locationExtended,
-                             const LocPosTechMask techMask)
+                             const GpsLocationExtended& locationExtended)
 {
     memset(&out, 0, sizeof(Location));
     out.size = sizeof(Location);
@@ -240,24 +279,57 @@
         out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
         out.bearingAccuracy = locationExtended.bearing_unc;
     }
+    if (GPS_LOCATION_EXTENDED_HAS_CONFORMITY_INDEX & locationExtended.flags) {
+        out.flags |= LOCATION_HAS_CONFORMITY_INDEX_BIT;
+        out.conformityIndex = locationExtended.conformityIndex;
+    }
     out.timestamp = ulpLocation.gpsLocation.timestamp;
-    if (LOC_POS_TECH_MASK_SATELLITE & techMask) {
+    if (LOC_POS_TECH_MASK_SATELLITE & locationExtended.tech_mask) {
         out.techMask |= LOCATION_TECHNOLOGY_GNSS_BIT;
     }
-    if (LOC_POS_TECH_MASK_CELLID & techMask) {
+    if (LOC_POS_TECH_MASK_CELLID & locationExtended.tech_mask) {
         out.techMask |= LOCATION_TECHNOLOGY_CELL_BIT;
     }
-    if (LOC_POS_TECH_MASK_WIFI & techMask) {
+    if (LOC_POS_TECH_MASK_WIFI & locationExtended.tech_mask) {
         out.techMask |= LOCATION_TECHNOLOGY_WIFI_BIT;
     }
-    if (LOC_POS_TECH_MASK_SENSORS & techMask) {
+    if (LOC_POS_TECH_MASK_SENSORS & locationExtended.tech_mask) {
         out.techMask |= LOCATION_TECHNOLOGY_SENSORS_BIT;
     }
+    if (LOC_POS_TECH_MASK_REFERENCE_LOCATION & locationExtended.tech_mask) {
+        out.techMask |= LOCATION_TECHNOLOGY_REFERENCE_LOCATION_BIT;
+    }
+    if (LOC_POS_TECH_MASK_INJECTED_COARSE_POSITION & locationExtended.tech_mask) {
+        out.techMask |= LOCATION_TECHNOLOGY_INJECTED_COARSE_POSITION_BIT;
+    }
+    if (LOC_POS_TECH_MASK_AFLT & locationExtended.tech_mask) {
+        out.techMask |= LOCATION_TECHNOLOGY_AFLT_BIT;
+    }
+    if (LOC_POS_TECH_MASK_HYBRID & locationExtended.tech_mask) {
+        out.techMask |= LOCATION_TECHNOLOGY_HYBRID_BIT;
+    }
+    if (LOC_POS_TECH_MASK_PPE & locationExtended.tech_mask) {
+        out.techMask |= LOCATION_TECHNOLOGY_PPE_BIT;
+    }
+    if (LOC_POS_TECH_MASK_VEH & locationExtended.tech_mask) {
+        out.techMask |= LOCATION_TECHNOLOGY_VEH_BIT;
+    }
+    if (LOC_POS_TECH_MASK_VIS & locationExtended.tech_mask) {
+        out.techMask |= LOCATION_TECHNOLOGY_VIS_BIT;
+    }
+    if (LOC_NAV_MASK_DGNSS_CORRECTION & locationExtended.navSolutionMask) {
+        out.techMask |= LOCATION_TECHNOLOGY_DGNSS_BIT;
+    }
 
     if (LOC_GPS_LOCATION_HAS_SPOOF_MASK & ulpLocation.gpsLocation.flags) {
         out.flags |= LOCATION_HAS_SPOOF_MASK;
         out.spoofMask = ulpLocation.gpsLocation.spoof_mask;
     }
+    if (LOC_GPS_LOCATION_HAS_ELAPSED_REAL_TIME & ulpLocation.gpsLocation.flags) {
+        out.flags |= LOCATION_HAS_ELAPSED_REAL_TIME;
+        out.elapsedRealTime = ulpLocation.gpsLocation.elapsedRealTime;
+        out.elapsedRealTimeUnc = ulpLocation.gpsLocation.elapsedRealTimeUnc;
+    }
 }
 
 /* This is utility routine that computes number of SV used
@@ -287,7 +359,8 @@
 
 void
 GnssAdapter::convertLocationInfo(GnssLocationInfoNotification& out,
-                                 const GpsLocationExtended& locationExtended)
+                                 const GpsLocationExtended& locationExtended,
+                                 enum loc_sess_status status)
 {
     out.size = sizeof(GnssLocationInfoNotification);
     if (GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL & locationExtended.flags) {
@@ -407,6 +480,8 @@
                 locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask;
         out.svUsedInPosition.qzssSvUsedIdsMask =
                 locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask;
+        out.svUsedInPosition.navicSvUsedIdsMask =
+                locationExtended.gnss_sv_used_ids.navic_sv_used_ids_mask;
 
         out.flags |= GNSS_LOCATION_INFO_NUM_SV_USED_IN_POSITION_BIT;
         out.numSvUsedInPosition = getNumSvUsed(out.svUsedInPosition.gpsSvUsedIdsMask,
@@ -419,6 +494,8 @@
                                                 BDS_SV_PRN_MAX - BDS_SV_PRN_MIN + 1);
         out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.galSvUsedIdsMask,
                                                 GAL_SV_PRN_MAX - GAL_SV_PRN_MIN + 1);
+        out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.navicSvUsedIdsMask,
+                                                NAVIC_SV_PRN_MAX - NAVIC_SV_PRN_MIN + 1);
 
         out.numOfMeasReceived = locationExtended.numOfMeasReceived;
         for (int idx =0; idx < locationExtended.numOfMeasReceived; idx++) {
@@ -434,10 +511,6 @@
         out.flags |= GNSS_LOCATION_INFO_NAV_SOLUTION_MASK_BIT;
         out.navSolutionMask = locationExtended.navSolutionMask;
     }
-    if (GPS_LOCATION_EXTENDED_HAS_POS_TECH_MASK & locationExtended.flags) {
-        out.flags |= GNSS_LOCATION_INFO_POS_TECH_MASK_BIT;
-        out.posTechMask = locationExtended.tech_mask;
-    }
     if (GPS_LOCATION_EXTENDED_HAS_POS_DYNAMICS_DATA & locationExtended.flags) {
         out.flags |= GPS_LOCATION_EXTENDED_HAS_POS_DYNAMICS_DATA;
         if (locationExtended.bodyFrameData.bodyFrameDataMask &
@@ -452,46 +525,88 @@
                 LOCATION_NAV_DATA_HAS_VERT_ACCEL_BIT) {
             out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_VERT_ACCEL_BIT;
         }
-        if (locationExtended.bodyFrameData.bodyFrameDataMask & LOCATION_NAV_DATA_HAS_YAW_RATE_BIT) {
+        if (locationExtended.bodyFrameData.bodyFrameDataMask &
+                LOCATION_NAV_DATA_HAS_YAW_RATE_BIT) {
             out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_RATE_BIT;
         }
-        if (locationExtended.bodyFrameData.bodyFrameDataMask & LOCATION_NAV_DATA_HAS_PITCH_BIT) {
+        if (locationExtended.bodyFrameData.bodyFrameDataMask &
+            LOCATION_NAV_DATA_HAS_PITCH_BIT) {
             out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_BIT;
         }
+
+        if (locationExtended.bodyFrameData.bodyFrameDataMask &
+                LOCATION_NAV_DATA_HAS_LONG_ACCEL_UNC_BIT) {
+            out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LONG_ACCEL_UNC_BIT;
+        }
+        if (locationExtended.bodyFrameData.bodyFrameDataMask &
+                LOCATION_NAV_DATA_HAS_LAT_ACCEL_UNC_BIT) {
+            out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LAT_ACCEL_UNC_BIT;
+        }
+        if (locationExtended.bodyFrameData.bodyFrameDataMask &
+                LOCATION_NAV_DATA_HAS_VERT_ACCEL_UNC_BIT) {
+            out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_VERT_ACCEL_UNC_BIT;
+        }
+        if (locationExtended.bodyFrameData.bodyFrameDataMask &
+                LOCATION_NAV_DATA_HAS_YAW_RATE_UNC_BIT) {
+            out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_RATE_UNC_BIT;
+        }
+        if (locationExtended.bodyFrameData.bodyFrameDataMask &
+                LOCATION_NAV_DATA_HAS_PITCH_UNC_BIT) {
+            out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_UNC_BIT;
+        }
+
+        if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
+                LOCATION_NAV_DATA_HAS_PITCH_RATE_BIT) {
+            out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_RATE_BIT;
+        }
+        if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
+                LOCATION_NAV_DATA_HAS_PITCH_RATE_UNC_BIT) {
+            out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_RATE_UNC_BIT;
+        }
+        if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
+                LOCATION_NAV_DATA_HAS_ROLL_BIT) {
+            out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_ROLL_BIT;
+        }
+        if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
+                LOCATION_NAV_DATA_HAS_ROLL_UNC_BIT) {
+            out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_ROLL_UNC_BIT;
+        }
+        if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
+                LOCATION_NAV_DATA_HAS_ROLL_RATE_BIT) {
+            out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_ROLL_RATE_BIT;
+        }
+        if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
+                LOCATION_NAV_DATA_HAS_ROLL_RATE_UNC_BIT) {
+            out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_ROLL_RATE_UNC_BIT;
+        }
+        if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
+                LOCATION_NAV_DATA_HAS_YAW_BIT) {
+            out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_BIT;
+        }
+        if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
+                LOCATION_NAV_DATA_HAS_YAW_UNC_BIT) {
+            out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_UNC_BIT;
+        }
+
         out.bodyFrameData.longAccel = locationExtended.bodyFrameData.longAccel;
         out.bodyFrameData.latAccel = locationExtended.bodyFrameData.latAccel;
         out.bodyFrameData.vertAccel = locationExtended.bodyFrameData.vertAccel;
         out.bodyFrameData.yawRate = locationExtended.bodyFrameData.yawRate;
         out.bodyFrameData.pitch = locationExtended.bodyFrameData.pitch;
-    }
-    if (GPS_LOCATION_EXTENDED_HAS_GPS_TIME & locationExtended.flags) {
-        out.flags |= GPS_LOCATION_EXTENDED_HAS_GPS_TIME;
-        out.gnssSystemTime.gnssSystemTimeSrc = locationExtended.gnssSystemTime.gnssSystemTimeSrc;
-        out.gnssSystemTime.u = locationExtended.gnssSystemTime.u;
-    }
-    if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL & locationExtended.flags) {
-        out.flags |= GPS_LOCATION_EXTENDED_HAS_NORTH_VEL;
-        out.northVelocity = locationExtended.northVelocity;
-    }
-    if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL & locationExtended.flags) {
-        out.flags |= GPS_LOCATION_EXTENDED_HAS_EAST_VEL;
-        out.eastVelocity = locationExtended.eastVelocity;
-    }
-    if (GPS_LOCATION_EXTENDED_HAS_UP_VEL & locationExtended.flags) {
-        out.flags |= GPS_LOCATION_EXTENDED_HAS_UP_VEL;
-        out.upVelocity = locationExtended.upVelocity;
-    }
-    if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL_UNC & locationExtended.flags) {
-        out.flags |= GPS_LOCATION_EXTENDED_HAS_NORTH_VEL_UNC;
-        out.northVelocityStdDeviation = locationExtended.northVelocityStdDeviation;
-    }
-    if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL_UNC & locationExtended.flags) {
-        out.flags |= GPS_LOCATION_EXTENDED_HAS_EAST_VEL_UNC;
-        out.eastVelocityStdDeviation = locationExtended.eastVelocityStdDeviation;
-    }
-    if (GPS_LOCATION_EXTENDED_HAS_UP_VEL_UNC & locationExtended.flags) {
-        out.flags |= GPS_LOCATION_EXTENDED_HAS_UP_VEL_UNC;
-        out.upVelocityStdDeviation = locationExtended.upVelocityStdDeviation;
+        out.bodyFrameData.longAccelUnc = locationExtended.bodyFrameData.longAccelUnc;
+        out.bodyFrameData.latAccelUnc  = locationExtended.bodyFrameData.latAccelUnc;
+        out.bodyFrameData.vertAccelUnc = locationExtended.bodyFrameData.vertAccelUnc;
+        out.bodyFrameData.yawRateUnc   = locationExtended.bodyFrameData.yawRateUnc;
+        out.bodyFrameData.pitchUnc     = locationExtended.bodyFrameData.pitchUnc;
+
+        out.bodyFrameDataExt.pitchRate    = locationExtended.bodyFrameDataExt.pitchRate;
+        out.bodyFrameDataExt.pitchRateUnc = locationExtended.bodyFrameDataExt.pitchRateUnc;
+        out.bodyFrameDataExt.roll         = locationExtended.bodyFrameDataExt.roll;
+        out.bodyFrameDataExt.rollUnc      = locationExtended.bodyFrameDataExt.rollUnc;
+        out.bodyFrameDataExt.rollRate     = locationExtended.bodyFrameDataExt.rollRate;
+        out.bodyFrameDataExt.rollRateUnc  = locationExtended.bodyFrameDataExt.rollRateUnc;
+        out.bodyFrameDataExt.yaw          = locationExtended.bodyFrameDataExt.yaw;
+        out.bodyFrameDataExt.yawUnc       = locationExtended.bodyFrameDataExt.yawUnc;
     }
 
     // Validity of this structure is established from the timeSrc of the GnssSystemTime structure.
@@ -526,10 +641,39 @@
         out.flags |= GNSS_LOCATION_INFO_OUTPUT_ENG_MASK_BIT;
         out.locOutputEngMask = locationExtended.locOutputEngMask;
     }
+
+    if (GPS_LOCATION_EXTENDED_HAS_CONFORMITY_INDEX & locationExtended.flags) {
+        out.flags |= GNSS_LOCATION_INFO_CONFORMITY_INDEX_BIT;
+        out.conformityIndex = locationExtended.conformityIndex;
+    }
+
+    if (GPS_LOCATION_EXTENDED_HAS_LLA_VRP_BASED & locationExtended.flags) {
+        out.flags |= GNSS_LOCATION_INFO_LLA_VRP_BASED_BIT;
+        out.llaVRPBased = locationExtended.llaVRPBased;
+    }
+
+    if (GPS_LOCATION_EXTENDED_HAS_ENU_VELOCITY_LLA_VRP_BASED & locationExtended.flags) {
+        out.flags |= GNSS_LOCATION_INFO_ENU_VELOCITY_VRP_BASED_BIT;
+        // copy over east, north and up vrp based velocity
+        out.enuVelocityVRPBased[0] = locationExtended.enuVelocityVRPBased[0];
+        out.enuVelocityVRPBased[1] = locationExtended.enuVelocityVRPBased[1];
+        out.enuVelocityVRPBased[2] = locationExtended.enuVelocityVRPBased[2];
+    }
+
+    if (GPS_LOCATION_EXTENDED_HAS_DR_SOLUTION_STATUS_MASK & locationExtended.flags) {
+        out.flags |= GNSS_LOCATION_INFO_DR_SOLUTION_STATUS_MASK_BIT;
+        out.drSolutionStatusMask = locationExtended.drSolutionStatusMask;
+    }
+
+    if (GPS_LOCATION_EXTENDED_HAS_ALTITUDE_ASSUMED & locationExtended.flags) {
+        out.flags |= GNSS_LOCATION_INFO_ALTITUDE_ASSUMED_BIT;
+        out.altitudeAssumed = locationExtended.altitudeAssumed;
+    }
+
+    out.flags |= GNSS_LOCATION_INFO_SESSION_STATUS_BIT;
+    out.sessionStatus = status;
 }
 
-
-
 inline uint32_t
 GnssAdapter::convertSuplVersion(const GnssConfigSuplVersion suplVersion)
 {
@@ -546,22 +690,6 @@
     }
 }
 
-inline uint32_t
-GnssAdapter::convertLppProfile(const GnssConfigLppProfile lppProfile)
-{
-    switch (lppProfile) {
-        case GNSS_CONFIG_LPP_PROFILE_USER_PLANE:
-            return 1;
-        case GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE:
-            return 2;
-        case GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE:
-            return 3;
-        case GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE:
-        default:
-            return 0;
-    }
-}
-
 uint32_t
 GnssAdapter::convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)
 {
@@ -713,7 +841,9 @@
         } else if (length >= 0) {
             if (LOC_AGPS_SUPL_SERVER == type) {
                 getServerUrl().assign(serverUrl);
-                strlcpy(ContextBase::mGps_conf.SUPL_HOST, server, LOC_MAX_PARAM_STRING);
+                strlcpy(ContextBase::mGps_conf.SUPL_HOST,
+                        (nullptr == server) ? serverUrl : server,
+                        LOC_MAX_PARAM_STRING);
                 ContextBase::mGps_conf.SUPL_PORT = port;
             } else {
                 if (strncasecmp(getMoServerUrl().c_str(), serverUrl, sizeof(serverUrl)) != 0) {
@@ -733,6 +863,9 @@
     uint32_t mask = 0;
     if (NMEA_PROVIDER_MP == ContextBase::mGps_conf.NMEA_PROVIDER) {
         mask |= LOC_NMEA_ALL_GENERAL_SUPPORTED_MASK;
+        if (ContextBase::mGps_conf.NMEA_TAG_BLOCK_GROUPING_ENABLED) {
+            mask |= LOC_NMEA_MASK_TAGBLOCK_V02;
+        }
     }
     if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
         mask |= LOC_NMEA_MASK_DEBUG_V02;
@@ -758,6 +891,8 @@
                       ContextBase::mGps_conf.MO_SUPL_PORT,
                       LOC_AGPS_MO_SUPL_SERVER);
 
+    std::string moServerUrl = getMoServerUrl();
+    std::string serverUrl = getServerUrl();
     // inject the configurations into modem
     loc_gps_cfg_s gpsConf = ContextBase::mGps_conf;
     loc_sap_cfg_s_type sapConf = ContextBase::mSap_conf;
@@ -788,12 +923,9 @@
             GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT |
             GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT |
             GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
-    gnssConfigRequested.suplVersion =
-            mLocApi->convertSuplVersion(gpsConf.SUPL_VER);
-    gnssConfigRequested.lppProfile =
-            mLocApi->convertLppProfile(gpsConf.LPP_PROFILE);
-    gnssConfigRequested.aGlonassPositionProtocolMask =
-            gpsConf.A_GLONASS_POS_PROTOCOL_SELECT;
+    gnssConfigRequested.suplVersion = mLocApi->convertSuplVersion(gpsConf.SUPL_VER);
+    gnssConfigRequested.lppProfileMask = gpsConf.LPP_PROFILE;
+    gnssConfigRequested.aGlonassPositionProtocolMask = gpsConf.A_GLONASS_POS_PROTOCOL_SELECT;
     if (gpsConf.LPPE_CP_TECHNOLOGY) {
         gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT;
         gnssConfigRequested.lppeControlPlaneMask =
@@ -808,13 +940,18 @@
     gnssConfigRequested.blacklistedSvIds.assign(mBlacklistedSvIds.begin(),
                                                 mBlacklistedSvIds.end());
     mLocApi->sendMsg(new LocApiMsg(
-            [this, gpsConf, sapConf, oldMoServerUrl, gnssConfigRequested] () mutable {
-        gnssUpdateConfig(oldMoServerUrl, gnssConfigRequested, gnssConfigRequested);
+            [this, gpsConf, sapConf, oldMoServerUrl, moServerUrl,
+            serverUrl, gnssConfigRequested] () mutable {
+        gnssUpdateConfig(oldMoServerUrl, moServerUrl, serverUrl,
+                gnssConfigRequested, gnssConfigRequested);
 
         // set nmea mask type
         uint32_t mask = 0;
         if (NMEA_PROVIDER_MP == gpsConf.NMEA_PROVIDER) {
             mask |= LOC_NMEA_ALL_GENERAL_SUPPORTED_MASK;
+            if (gpsConf.NMEA_TAG_BLOCK_GROUPING_ENABLED) {
+                mask |= LOC_NMEA_MASK_TAGBLOCK_V02;
+            }
         }
         if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
             mask |= LOC_NMEA_MASK_DEBUG_V02;
@@ -824,8 +961,6 @@
             mLocApi->setNMEATypesSync(mask);
         }
 
-        mLocApi->setXtraVersionCheckSync(gpsConf.XTRA_VERSION_CHECK);
-
         // load tunc configuration from config file on first boot-up,
         // e.g.: adapter.mLocConfigInfo.tuncConfigInfo.isValid is false
         if (mLocConfigInfo.tuncConfigInfo.isValid == false) {
@@ -853,6 +988,13 @@
         mLocApi->setPositionAssistedClockEstimatorMode(
                 mLocConfigInfo.paceConfigInfo.enable);
 
+        // we do not support control robust location from gps.conf
+        if (mLocConfigInfo.robustLocationConfigInfo.isValid == true) {
+            mLocApi->configRobustLocation(
+                    mLocConfigInfo.robustLocationConfigInfo.enable,
+                    mLocConfigInfo.robustLocationConfigInfo.enableFor911);
+        }
+
         if (sapConf.GYRO_BIAS_RANDOM_WALK_VALID ||
             sapConf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
             sapConf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
@@ -882,10 +1024,14 @@
                 sapConf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH,
                 sapConf.SENSOR_ALGORITHM_CONFIG_MASK);
     } ));
-
+    // deal with Measurement Corrections
+    if (true == mIsMeasCorrInterfaceOpen) {
+        initMeasCorr(true);
+    }
 }
 
 std::vector<LocationError> GnssAdapter::gnssUpdateConfig(const std::string& oldMoServerUrl,
+        const std::string& moServerUrl, const std::string& serverUrl,
         GnssConfig& gnssConfigRequested, GnssConfig& gnssConfigNeedEngineUpdate, size_t count) {
     loc_gps_cfg_s gpsConf = ContextBase::mGps_conf;
     size_t index = 0;
@@ -895,9 +1041,6 @@
         errsList.insert(errsList.begin(), count, LOCATION_ERROR_SUCCESS);
     }
 
-    std::string serverUrl = getServerUrl();
-    std::string moServerUrl = getMoServerUrl();
-
     int serverUrlLen = serverUrl.length();
     int moServerUrlLen = moServerUrl.length();
 
@@ -996,7 +1139,7 @@
     if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
         if (gnssConfigNeedEngineUpdate.flags &
                 GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
-            err = mLocApi->setLPPConfigSync(gnssConfigRequested.lppProfile);
+            err = mLocApi->setLPPConfigSync(gnssConfigRequested.lppProfileMask);
             if (index < count) {
                 errsList[index] = err;
             }
@@ -1075,11 +1218,23 @@
         }
         index++;
     }
+
+    if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT) {
+        GnssConfig gnssConfig = {};
+        gnssConfig.flags = GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT;
+        gnssConfig.minSvElevation = gnssConfigRequested.minSvElevation;
+        err = mLocApi->setParameterSync(gnssConfig);
+        if (index < count) {
+            errsList[index] = err;
+        }
+        index++;
+    }
+
     return errsList;
 }
 
 uint32_t*
-GnssAdapter::gnssUpdateConfigCommand(GnssConfig config)
+GnssAdapter::gnssUpdateConfigCommand(const GnssConfig& config)
 {
     // count the number of bits set
     GnssConfigFlagsMask flagsCopy = config.flags;
@@ -1125,19 +1280,26 @@
             mApi(api),
             mConfig(config),
             mCount(count),
-            mIds(ids) {}
+            mIds(nullptr) {
+                if (mCount > 0) {
+                    mIds = new uint32_t[count];
+                    if (mIds) {
+                        for (uint32_t index = 0; index < count; index++) {
+                            mIds[index] = ids[index];
+                        }
+                    } else {
+                        LOC_LOGe("memory allocation for mIds failed");
+                    }
+                }
+        }
+
         inline MsgGnssUpdateConfig(const MsgGnssUpdateConfig& obj) :
                 MsgGnssUpdateConfig(obj.mAdapter, obj.mApi, obj.mConfig,
-                        new uint32_t[obj.mCount], obj.mCount) {
-            if (mIds != nullptr) {
-                for (int i = 0; i < mCount; ++i) {
-                    mIds[i] = obj.mIds[i];
-                }
-            }
-        }
+                        obj.mIds, obj.mCount) {}
+
         inline virtual ~MsgGnssUpdateConfig()
         {
-            delete[] mIds;
+            if (nullptr != mIds) delete[] mIds;
         }
 
         inline virtual void proc() const {
@@ -1154,6 +1316,7 @@
             sessionIds.assign(mIds, mIds + mCount);
             std::vector<LocationError> errs(mCount, LOCATION_ERROR_SUCCESS);
             int index = 0;
+            bool needSuspendResume = false;
 
             if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
                 GnssConfigGpsLock newGpsLock = gnssConfigRequested.gpsLock;
@@ -1207,8 +1370,8 @@
                 index++;
             }
             if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
-                uint32_t newLppProfile = mAdapter.convertLppProfile(gnssConfigRequested.lppProfile);
-                ContextBase::mGps_conf.LPP_PROFILE = newLppProfile;
+                uint32_t newLppProfileMask = gnssConfigRequested.lppProfileMask;
+                ContextBase::mGps_conf.LPP_PROFILE = newLppProfileMask;
                 index++;
             }
             if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
@@ -1253,6 +1416,14 @@
                 index++;
             }
 
+            if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT) {
+                needSuspendResume = true;
+                index++;
+            }
+
+            if (needSuspendResume == true) {
+                mAdapter.suspendSessions();
+            }
             LocApiCollectiveResponse *configCollectiveResponse = new LocApiCollectiveResponse(
                     *adapter.getContext(),
                     [&adapter, sessionIds, countOfConfigs] (std::vector<LocationError> errs) {
@@ -1261,14 +1432,22 @@
                     adapter.reportResponse(countOfConfigs, errs.data(), ids.data());
             });
 
+            std::string moServerUrl = adapter.getMoServerUrl();
+            std::string serverUrl = adapter.getServerUrl();
             mApi.sendMsg(new LocApiMsg(
                     [&adapter, gnssConfigRequested, gnssConfigNeedEngineUpdate,
-                    countOfConfigs, configCollectiveResponse, errs] () mutable {
+                    moServerUrl, serverUrl, countOfConfigs, configCollectiveResponse,
+                    errs] () mutable {
                 std::vector<LocationError> errsList = adapter.gnssUpdateConfig("",
+                        moServerUrl, serverUrl,
                         gnssConfigRequested, gnssConfigNeedEngineUpdate, countOfConfigs);
 
                 configCollectiveResponse->returnToSender(errsList);
             }));
+
+            if (needSuspendResume == true) {
+                mAdapter.restartSessions();
+            }
         }
     };
 
@@ -1302,10 +1481,10 @@
 GnssAdapter::gnssSvIdConfigUpdate()
 {
     LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
-            ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64,
+            ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", navic 0x%" PRIx64,
             mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
-            mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask);
-
+            mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask,
+            mGnssSvIdConfig.sbasBlacklistSvMask, mGnssSvIdConfig.navicBlacklistSvMask);
     // Now set required blacklisted SVs
     mLocApi->setBlacklistSv(mGnssSvIdConfig);
 }
@@ -1327,14 +1506,28 @@
 GnssAdapter::gnssSvIdConfigUpdateSync()
 {
     LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
-            ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64,
+            ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", navic 0x%" PRIx64,
             mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
-            mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask);
+            mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask,
+            mGnssSvIdConfig.sbasBlacklistSvMask, mGnssSvIdConfig.navicBlacklistSvMask);
 
     // Now set required blacklisted SVs
     return mLocApi->setBlacklistSvSync(mGnssSvIdConfig);
 }
 
+void
+GnssAdapter::gnssSecondaryBandConfigUpdate(LocApiResponse* locApiResponse)
+{
+    LOC_LOGd("secondary band config, size %d, enabled constellation 0x%" PRIx64 ","
+             "disabled constellation 0x%" PRIx64 "", mGnssSeconaryBandConfig.size,
+             mGnssSeconaryBandConfig.enabledSvTypesMask,
+             mGnssSeconaryBandConfig.blacklistedSvTypesMask);
+    if (mGnssSeconaryBandConfig.size == sizeof(mGnssSeconaryBandConfig)) {
+        // Now set required secondary band config
+        mLocApi->configConstellationMultiBand(mGnssSeconaryBandConfig, locApiResponse);
+    }
+}
+
 uint32_t*
 GnssAdapter::gnssGetConfigCommand(GnssConfigFlagsMask configMask) {
 
@@ -1381,21 +1574,27 @@
             mAdapter(adapter),
             mApi(api),
             mConfigMask(configMask),
-            mIds(ids),
-            mCount(count) {}
+            mCount(count),
+            mIds(nullptr) {
+                if (mCount > 0) {
+                    mIds = new uint32_t[count];
+                    if (mIds) {
+                        for (uint32_t index = 0; index < count; index++) {
+                            mIds[index] = ids[index];
+                        }
+                    } else {
+                        LOC_LOGe("memory allocation for mIds failed");
+                    }
+                }
+        }
 
         inline MsgGnssGetConfig(const MsgGnssGetConfig& obj) :
                 MsgGnssGetConfig(obj.mAdapter, obj.mApi, obj.mConfigMask,
-                        new uint32_t[obj.mCount], obj.mCount) {
-            if (mIds != nullptr) {
-                for (int i = 0; i < mCount; ++i) {
-                    mIds[i] = obj.mIds[i];
-                }
-            }
-        }
+                        obj.mIds, obj.mCount) {}
+
         inline virtual ~MsgGnssGetConfig()
         {
-            delete[] mIds;
+            if (nullptr != mIds) delete[] mIds;
         }
         inline virtual void proc() const {
             if (!mAdapter.isEngineCapabilitiesKnown()) {
@@ -1483,6 +1682,48 @@
                     errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
                 }
             }
+            if (mConfigMask & GNSS_CONFIG_FLAGS_ROBUST_LOCATION_BIT) {
+                uint32_t sessionId = *(mIds+index);
+                LocApiResponse* locApiResponse =
+                        new LocApiResponse(*mAdapter.getContext(),
+                                           [this, sessionId] (LocationError err) {
+                                           mAdapter.reportResponse(err, sessionId);});
+                if (!locApiResponse) {
+                    LOC_LOGe("memory alloc failed");
+                    mAdapter.reportResponse(LOCATION_ERROR_GENERAL_FAILURE, sessionId);
+                } else {
+                   mApi.getRobustLocationConfig(sessionId, locApiResponse);
+                }
+            }
+
+            if (mConfigMask & GNSS_CONFIG_FLAGS_MIN_GPS_WEEK_BIT) {
+                uint32_t sessionId = *(mIds+index);
+                LocApiResponse* locApiResponse =
+                        new LocApiResponse(*mAdapter.getContext(),
+                                           [this, sessionId] (LocationError err) {
+                                           mAdapter.reportResponse(err, sessionId);});
+                if (!locApiResponse) {
+                    LOC_LOGe("memory alloc failed");
+                    mAdapter.reportResponse(LOCATION_ERROR_GENERAL_FAILURE, sessionId);
+                } else {
+                   mApi.getMinGpsWeek(sessionId, locApiResponse);
+                }
+            }
+
+            if (mConfigMask & GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT) {
+                uint32_t sessionId = *(mIds+index);
+                LocApiResponse* locApiResponse =
+                        new LocApiResponse(*mAdapter.getContext(),
+                                           [this, sessionId] (LocationError err) {
+                                           mAdapter.reportResponse(err, sessionId);});
+                if (!locApiResponse) {
+                    LOC_LOGe("memory alloc failed");
+                    mAdapter.reportResponse(LOCATION_ERROR_GENERAL_FAILURE, sessionId);
+                } else {
+                    mApi.getParameter(sessionId, GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT,
+                                      locApiResponse);
+                }
+            }
 
             mAdapter.reportResponse(index, errs, mIds);
             delete[] errs;
@@ -1512,12 +1753,15 @@
         config.bdsBlacklistSvMask = 0;
         config.qzssBlacklistSvMask = 0;
         config.galBlacklistSvMask = 0;
+        config.sbasBlacklistSvMask = 0;
+        config.navicBlacklistSvMask = 0;
         retVal = true;
     } else {
         // Parse the vector and convert SV IDs to mask values
         for (GnssSvIdSource source : blacklistedSvIds) {
             uint64_t* svMaskPtr = NULL;
             GnssSvId initialSvId = 0;
+            uint16_t svIndexOffset = 0;
             switch(source.constellation) {
             case GNSS_SV_TYPE_GLONASS:
                 svMaskPtr = &config.gloBlacklistSvMask;
@@ -1535,6 +1779,31 @@
                 svMaskPtr = &config.galBlacklistSvMask;
                 initialSvId = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID;
                 break;
+            case GNSS_SV_TYPE_SBAS:
+                // SBAS does not support enable/disable whole constellation
+                // so do not set up svTypeMask for SBAS
+                svMaskPtr = &config.sbasBlacklistSvMask;
+                // SBAS currently has two ranges, [120, 158] and [183, 191]
+                if (0 == source.svId) {
+                    LOC_LOGd("blacklist all SBAS SV");
+                } else if (source.svId >= GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID) {
+                    // handle SV id in range [183, 191]
+                    initialSvId = GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID;
+                    svIndexOffset = GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH;
+                } else if ((source.svId >= GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID) &&
+                           (source.svId < (GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID +
+                                           GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH))){
+                        // handle SV id in range of [120, 158]
+                        initialSvId = GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID;
+                    } else {
+                        LOC_LOGe("invalid SBAS sv id %d", source.svId);
+                        svMaskPtr = nullptr;
+                    }
+                    break;
+            case GNSS_SV_TYPE_NAVIC:
+                 svMaskPtr = &config.navicBlacklistSvMask;
+                 initialSvId = GNSS_SV_CONFIG_NAVIC_INITIAL_SV_ID;
+                break;
             default:
                 break;
             }
@@ -1549,7 +1818,8 @@
                     LOC_LOGe("Invalid sv id %d for sv type %d",
                             source.svId, source.constellation);
                 } else {
-                    *svMaskPtr |= (1ULL << (source.svId - initialSvId));
+                    uint32_t shiftCnt = source.svId + svIndexOffset - initialSvId;
+                    *svMaskPtr |= (1ULL << shiftCnt);
                 }
             }
         }
@@ -1558,41 +1828,67 @@
         if (0 != config.gloBlacklistSvMask ||
                 0 != config.bdsBlacklistSvMask ||
                 0 != config.galBlacklistSvMask ||
-                0 != config.qzssBlacklistSvMask) {
+                0 != config.qzssBlacklistSvMask ||
+                0 != config.sbasBlacklistSvMask ||
+                0 != config.navicBlacklistSvMask) {
             retVal = true;
         }
     }
 
+    LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
+            ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", navic 0x%" PRIx64,
+             config.bdsBlacklistSvMask, config.gloBlacklistSvMask,
+             config.qzssBlacklistSvMask, config.galBlacklistSvMask,
+            config.sbasBlacklistSvMask, config.navicBlacklistSvMask);
+
     return retVal;
 }
 
 void GnssAdapter::convertFromGnssSvIdConfig(
-        const GnssSvIdConfig& svConfig, GnssConfig& config)
+        const GnssSvIdConfig& svConfig, std::vector<GnssSvIdSource>& blacklistedSvIds)
 {
     // Convert blacklisted SV mask values to vectors
     if (svConfig.bdsBlacklistSvMask) {
         convertGnssSvIdMaskToList(
-                svConfig.bdsBlacklistSvMask, config.blacklistedSvIds,
+                svConfig.bdsBlacklistSvMask, blacklistedSvIds,
                 GNSS_SV_CONFIG_BDS_INITIAL_SV_ID, GNSS_SV_TYPE_BEIDOU);
-        config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
     }
     if (svConfig.galBlacklistSvMask) {
         convertGnssSvIdMaskToList(
-                svConfig.galBlacklistSvMask, config.blacklistedSvIds,
+                svConfig.galBlacklistSvMask, blacklistedSvIds,
                 GNSS_SV_CONFIG_GAL_INITIAL_SV_ID, GNSS_SV_TYPE_GALILEO);
-        config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
     }
     if (svConfig.gloBlacklistSvMask) {
         convertGnssSvIdMaskToList(
-                svConfig.gloBlacklistSvMask, config.blacklistedSvIds,
+                svConfig.gloBlacklistSvMask, blacklistedSvIds,
                 GNSS_SV_CONFIG_GLO_INITIAL_SV_ID, GNSS_SV_TYPE_GLONASS);
-        config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
     }
     if (svConfig.qzssBlacklistSvMask) {
         convertGnssSvIdMaskToList(
-                svConfig.qzssBlacklistSvMask, config.blacklistedSvIds,
+                svConfig.qzssBlacklistSvMask, blacklistedSvIds,
                 GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID, GNSS_SV_TYPE_QZSS);
-        config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
+    }
+    if (svConfig.sbasBlacklistSvMask) {
+        // SBAS - SV 120 to 158, maps to 0 to 38
+        //        SV 183 to 191, maps to 39 to 47
+        uint64_t sbasBlacklistSvMask = svConfig.sbasBlacklistSvMask;
+        // operate on 120 and 158 first
+        sbasBlacklistSvMask <<= (64 - GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH);
+        sbasBlacklistSvMask >>= (64 - GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH);
+        convertGnssSvIdMaskToList(
+                sbasBlacklistSvMask, blacklistedSvIds,
+                GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID, GNSS_SV_TYPE_SBAS);
+        // operate on the second range
+        sbasBlacklistSvMask = svConfig.sbasBlacklistSvMask;
+        sbasBlacklistSvMask >>= GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH;
+        convertGnssSvIdMaskToList(
+                sbasBlacklistSvMask, blacklistedSvIds,
+                GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID, GNSS_SV_TYPE_SBAS);
+    }
+    if (svConfig.navicBlacklistSvMask) {
+        convertGnssSvIdMaskToList(
+                svConfig.navicBlacklistSvMask, blacklistedSvIds,
+                GNSS_SV_CONFIG_NAVIC_INITIAL_SV_ID, GNSS_SV_TYPE_NAVIC);
     }
 }
 
@@ -1606,6 +1902,7 @@
 
     // SV ID 0 => All SV IDs in mask
     if (GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK == svIdMask) {
+        LOC_LOGd("blacklist all SVs in constellation %d", source.constellation);
         source.svId = 0;
         svIds.push_back(source);
         return;
@@ -1616,6 +1913,18 @@
     while (svIdMask > 0) {
         if (svIdMask & 0x1) {
             source.svId = bitNumber + initialSvId;
+            // SBAS has two ranges:
+            // SBAS - SV 120 to 158, maps to 0 to 38
+            //        SV 183 to 191, maps to 39 to 47
+            // #define GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID     120
+            // #define GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH 39
+            // #define GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID    183
+            if (svType == GNSS_SV_TYPE_SBAS) {
+                if (bitNumber >= GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH) {
+                    source.svId = bitNumber - GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH +
+                                  GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID;
+                }
+            }
             svIds.push_back(source);
         }
         bitNumber++;
@@ -1649,12 +1958,18 @@
     // Invoke control clients config callback
     if (nullptr != mControlCallbacks.gnssConfigCb &&
             svIdConfig.size == sizeof(GnssSvIdConfig)) {
-        convertFromGnssSvIdConfig(svIdConfig, config);
-        LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
-                ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64,
-                svIdConfig.bdsBlacklistSvMask, svIdConfig.gloBlacklistSvMask,
-                svIdConfig.qzssBlacklistSvMask, svIdConfig.galBlacklistSvMask);
-        mControlCallbacks.gnssConfigCb(config);
+
+        convertFromGnssSvIdConfig(svIdConfig, config.blacklistedSvIds);
+        if (config.blacklistedSvIds.size() > 0) {
+            config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
+        }
+        LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64 ", "
+                 "qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", navic 0x%" PRIx64,
+                 svIdConfig.bdsBlacklistSvMask, svIdConfig.gloBlacklistSvMask,
+                 svIdConfig.qzssBlacklistSvMask, svIdConfig.galBlacklistSvMask,
+                 svIdConfig.sbasBlacklistSvMask,  svIdConfig.navicBlacklistSvMask);
+        // use 0 session id to indicate that receiver does not yet care about session id
+        mControlCallbacks.gnssConfigCb(0, config);
     } else {
         LOC_LOGe("Failed to report, size %d", (uint32_t)config.size);
     }
@@ -1715,6 +2030,18 @@
              mGnssSvTypeConfig.size, mGnssSvTypeConfig.blacklistedSvTypesMask,
              mGnssSvTypeConfig.enabledSvTypesMask, sendReset);
 
+    LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
+            ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", Navic 0x%" PRIx64,
+            mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
+            mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask,
+            mGnssSvIdConfig.sbasBlacklistSvMask, mGnssSvIdConfig.navicBlacklistSvMask);
+
+    LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
+            ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", Navic 0x%" PRIx64,
+            mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
+            mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask,
+            mGnssSvIdConfig.sbasBlacklistSvMask, mGnssSvIdConfig.navicBlacklistSvMask);
+
     if (mGnssSvTypeConfig.size == sizeof(mGnssSvTypeConfig)) {
 
         if (sendReset) {
@@ -1738,6 +2065,9 @@
             if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_GAL_BIT) {
                 blacklistConfig.galBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
             }
+            if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_NAVIC_BIT) {
+                blacklistConfig.navicBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
+            }
         }
 
         // Send blacklist info
@@ -1853,10 +2183,19 @@
 }
 
 void GnssAdapter::deleteAidingData(const GnssAidingData &data, uint32_t sessionId) {
-    mLocApi->deleteAidingData(data, new LocApiResponse(*getContext(),
-            [this, sessionId] (LocationError err) {
-                reportResponse(err, sessionId);
-            }));
+    struct timespec bootDeleteAidingDataTime;
+    int64_t bootDeleteTimeMs;
+    if (clock_gettime(CLOCK_BOOTTIME, &bootDeleteAidingDataTime) == 0) {
+        bootDeleteTimeMs = bootDeleteAidingDataTime.tv_sec * 1000000;
+        int64_t diffTimeBFirSecDelete = bootDeleteTimeMs - mLastDeleteAidingDataTime;
+        if (diffTimeBFirSecDelete > DELETE_AIDING_DATA_EXPECTED_TIME_MS) {
+            mLocApi->deleteAidingData(data, new LocApiResponse(*getContext(),
+                    [this, sessionId] (LocationError err) {
+                        reportResponse(err, sessionId);
+                    }));
+            mLastDeleteAidingDataTime = bootDeleteTimeMs;
+       }
+   }
 }
 
 uint32_t
@@ -1879,14 +2218,23 @@
         inline virtual void proc() const {
             if ((mData.posEngineMask & STANDARD_POSITIONING_ENGINE) != 0) {
                 mAdapter.deleteAidingData(mData, mSessionId);
-
                 SystemStatus* s = mAdapter.getSystemStatus();
                 if ((nullptr != s) && (mData.deleteAll)) {
                     s->setDefaultGnssEngineStates();
                 }
             }
 
-            mAdapter.mEngHubProxy->gnssDeleteAidingData(mData);
+            bool retVal = mAdapter.mEngHubProxy->gnssDeleteAidingData(mData);
+            // When SPE engine is invoked, responseCb will be invoked
+            // from QMI Loc API call.
+            // When SPE engine is not invoked, we also need to deliver responseCb
+            if ((mData.posEngineMask & STANDARD_POSITIONING_ENGINE) == 0) {
+                LocationError err = LOCATION_ERROR_NOT_SUPPORTED;
+                if (retVal == true) {
+                    err = LOCATION_ERROR_SUCCESS;
+                }
+                mAdapter.reportResponse(err, mSessionId);
+            }
         }
     };
 
@@ -1927,35 +2275,38 @@
         double mLatitude;
         double mLongitude;
         float mAccuracy;
+        bool mOnDemandCpi;
         inline MsgInjectLocation(LocApiBase& api,
                                  ContextBase& context,
                                  BlockCPIInfo& blockCPIInfo,
                                  double latitude,
                                  double longitude,
-                                 float accuracy) :
+                                 float accuracy,
+                                 bool onDemandCpi) :
             LocMsg(),
             mApi(api),
             mContext(context),
             mBlockCPI(blockCPIInfo),
             mLatitude(latitude),
             mLongitude(longitude),
-            mAccuracy(accuracy) {}
+            mAccuracy(accuracy),
+            mOnDemandCpi(onDemandCpi) {}
         inline virtual void proc() const {
             if ((uptimeMillis() <= mBlockCPI.blockedTillTsMs) &&
                 (fabs(mLatitude-mBlockCPI.latitude) <= mBlockCPI.latLonDiffThreshold) &&
                 (fabs(mLongitude-mBlockCPI.longitude) <= mBlockCPI.latLonDiffThreshold)) {
 
-                LOC_LOGD("%s]: positon injeciton blocked: lat: %f, lon: %f, accuracy: %f",
+                LOC_LOGD("%s]: positon injection blocked: lat: %f, lon: %f, accuracy: %f",
                          __func__, mLatitude, mLongitude, mAccuracy);
 
             } else {
-                mApi.injectPosition(mLatitude, mLongitude, mAccuracy);
+                mApi.injectPosition(mLatitude, mLongitude, mAccuracy, mOnDemandCpi);
             }
         }
     };
 
     sendMsg(new MsgInjectLocation(*mLocApi, *mContext, mBlockCPIInfo,
-                                  latitude, longitude, accuracy));
+                                  latitude, longitude, accuracy, mOdcpiRequestActive));
 }
 
 void
@@ -2145,7 +2496,10 @@
 void
 GnssAdapter::updateClientsEventMask()
 {
-    LOC_API_ADAPTER_EVENT_MASK_T mask = 0;
+    // need to register for leap second info
+    // for proper nmea generation
+    LOC_API_ADAPTER_EVENT_MASK_T mask = LOC_API_ADAPTER_BIT_LOC_SYSTEM_INFO |
+            LOC_API_ADAPTER_BIT_EVENT_REPORT_INFO;
     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
         if (it->second.trackingCb != nullptr ||
             it->second.gnssLocationInfoCb != nullptr ||
@@ -2180,8 +2534,6 @@
         mask |= LOC_API_ADAPTER_BIT_GNSS_SV_POLYNOMIAL_REPORT;
         mask |= LOC_API_ADAPTER_BIT_PARSED_UNPROPAGATED_POSITION_REPORT;
         mask |= LOC_API_ADAPTER_BIT_GNSS_SV_EPHEMERIS_REPORT;
-        mask |= LOC_API_ADAPTER_BIT_LOC_SYSTEM_INFO;
-        mask |= LOC_API_ADAPTER_BIT_EVENT_REPORT_INFO;
 
         // Nhz measurement bit is set based on callback from loc eng hub
         // for Nhz engines.
@@ -2206,6 +2558,13 @@
     // always register for NI NOTIFY VERIFY to handle internally in HAL
     mask |= LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST;
 
+    // Enable the latency report
+    if (mask & LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT) {
+        if (mLogger.isLogEnabled()) {
+            mask |= LOC_API_ADAPTER_BIT_LATENCY_INFORMATION;
+        }
+    }
+
     updateEvtMask(mask, LOC_REGISTRATION_MASK_SET);
 }
 
@@ -2227,7 +2586,11 @@
             mAdapter.gnssSvIdConfigUpdate();
             mAdapter.gnssSvTypeConfigUpdate();
             mAdapter.updateSystemPowerState(mAdapter.getSystemPowerState());
-            mAdapter.restartSessions();
+            mAdapter.gnssSecondaryBandConfigUpdate();
+            // start CDFW service
+            mAdapter.initCDFWService();
+            // restart sessions
+            mAdapter.restartSessions(true);
             for (auto msg: mAdapter.mPendingMsgs) {
                 mAdapter.sendMsg(msg);
             }
@@ -2240,13 +2603,32 @@
 }
 
 void
-GnssAdapter::restartSessions()
+GnssAdapter::restartSessions(bool modemSSR)
+{
+    LOC_LOGi(":enter");
+
+    if (modemSSR) {
+        // odcpi session is no longer active after restart
+        mOdcpiRequestActive = false;
+    }
+
+    // SPE will be restarted now, so set this variable to false.
+    mSPEAlreadyRunningAtHighestInterval = false;
+
+    if (false == mTimeBasedTrackingSessions.empty()) {
+        // inform engine hub that GNSS session is about to start
+        mEngHubProxy->gnssSetFixMode(mLocPositionMode);
+        mEngHubProxy->gnssStartFix();
+        checkUpdateDgnssNtrip(false);
+    }
+
+    checkAndRestartSPESession();
+}
+
+void GnssAdapter::checkAndRestartSPESession()
 {
     LOC_LOGD("%s]: ", __func__);
 
-    // odcpi session is no longer active after restart
-    mOdcpiRequestActive = false;
-
     // SPE will be restarted now, so set this variable to false.
     mSPEAlreadyRunningAtHighestInterval = false;
 
@@ -2260,6 +2642,24 @@
     }
 }
 
+// suspend all on-going sessions
+void
+GnssAdapter::suspendSessions()
+{
+    LOC_LOGi(":enter");
+
+    if (!mTimeBasedTrackingSessions.empty()) {
+        // inform engine hub that GNSS session has stopped
+        mEngHubProxy->gnssStopFix();
+        mLocApi->stopFix(nullptr);
+        if (isDgnssNmeaRequired()) {
+            mDgnssState &= ~DGNSS_STATE_NO_NMEA_PENDING;
+        }
+        stopDgnssNtrip();
+        mSPEAlreadyRunningAtHighestInterval = false;
+    }
+}
+
 void GnssAdapter::checkAndRestartTimeBasedSession()
 {
     LOC_LOGD("%s]: ", __func__);
@@ -2294,6 +2694,48 @@
     }
 }
 
+LocationCapabilitiesMask
+GnssAdapter::getCapabilities()
+{
+    LocationCapabilitiesMask mask = 0;
+    uint32_t carrierCapabilities = ContextBase::getCarrierCapabilities();
+    // time based tracking always supported
+    mask |= LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT;
+    // geofence always supported
+    mask |= LOCATION_CAPABILITIES_GEOFENCE_BIT;
+    if (carrierCapabilities & LOC_GPS_CAPABILITY_MSB) {
+        mask |= LOCATION_CAPABILITIES_GNSS_MSB_BIT;
+    }
+    if (LOC_GPS_CAPABILITY_MSA & carrierCapabilities) {
+        mask |= LOCATION_CAPABILITIES_GNSS_MSA_BIT;
+    }
+    if (ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_LOCATION_BATCHING)) {
+        mask |= LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT |
+                LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT;
+    }
+    if (ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) {
+        mask |= LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT;
+    }
+    if (ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_OUTDOOR_TRIP_BATCHING)) {
+        mask |= LOCATION_CAPABILITIES_OUTDOOR_TRIP_BATCHING_BIT;
+    }
+    if (ContextBase::gnssConstellationConfig()) {
+        mask |= LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT;
+    }
+    if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
+        mask |= LOCATION_CAPABILITIES_DEBUG_NMEA_BIT;
+    }
+    if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
+        mask |= LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT;
+    }
+    if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_AGPM_V02)) {
+        mask |= LOCATION_CAPABILITIES_AGPM_BIT;
+    }
+    //Get QWES feature status mask
+    mask |= ContextBase::getQwesFeatureStatus();
+    return mask;
+}
+
 void
 GnssAdapter::notifyClientOfCachedLocationSystemInfo(
         LocationAPI* client, const LocationCallbacks& callbacks) {
@@ -2344,7 +2786,8 @@
     auto it = mClientData.find(client);
     if (it != mClientData.end()) {
         if (it->second.trackingCb || it->second.gnssLocationInfoCb ||
-            it->second.engineLocationsInfoCb || it->second.gnssMeasurementsCb) {
+                it->second.engineLocationsInfoCb || it->second.gnssMeasurementsCb ||
+                it->second.gnssDataCb || it->second.gnssSvCb || it->second.gnssNmeaCb) {
             allowed = true;
         } else {
             LOC_LOGi("missing right callback to start tracking")
@@ -2376,15 +2819,15 @@
 }
 
 void
-GnssAdapter::getPowerStateChangesCommand(void* powerStateCb)
+GnssAdapter::getPowerStateChangesCommand(std::function<void(bool)> powerStateCb)
 {
     LOC_LOGD("%s]: ", __func__);
 
     struct MsgReportLocation : public LocMsg {
         GnssAdapter& mAdapter;
-        powerStateCallback mPowerStateCb;
+        std::function<void(bool)> mPowerStateCb;
         inline MsgReportLocation(GnssAdapter& adapter,
-                                 powerStateCallback powerStateCb) :
+                                 std::function<void(bool)> powerStateCb) :
             LocMsg(),
             mAdapter(adapter),
             mPowerStateCb(powerStateCb) {}
@@ -2394,7 +2837,7 @@
         }
     };
 
-    sendMsg(new MsgReportLocation(*this, (powerStateCallback)powerStateCb));
+    sendMsg(new MsgReportLocation(*this, powerStateCb));
 }
 
 void
@@ -2427,7 +2870,6 @@
     reportPowerStateIfChanged();
 }
 
-
 bool GnssAdapter::setLocPositionMode(const LocPosMode& mode) {
     if (!mLocPositionMode.equals(mode)) {
         mLocPositionMode = mode;
@@ -2573,6 +3015,8 @@
     bool reportToClientWithNoWait = true;
 
     if (mTimeBasedTrackingSessions.empty()) {
+        /*Reset previous NMEA reported time stamp */
+        mPrevNmeaRptTimeNsec = 0;
         startTimeBasedTracking(client, sessionId, options);
         // need to wait for QMI callback
         reportToClientWithNoWait = false;
@@ -2626,12 +3070,12 @@
     LOC_LOGd("minInterval %u minDistance %u mode %u powermode %u tbm %u",
             trackingOptions.minInterval, trackingOptions.minDistance,
             trackingOptions.mode, trackingOptions.powerMode, trackingOptions.tbm);
-
     LocPosMode locPosMode = {};
     convertOptions(locPosMode, trackingOptions);
-
+    // save position mode parameters
+    setLocPositionMode(locPosMode);
     // inform engine hub that GNSS session is about to start
-    mEngHubProxy->gnssSetFixMode(locPosMode);
+    mEngHubProxy->gnssSetFixMode(mLocPositionMode);
     mEngHubProxy->gnssStartFix();
 
     // want to run SPE session at a fixed min interval in some automotive scenarios
@@ -2643,6 +3087,8 @@
                           [this, client, sessionId] (LocationError err) {
                 if (LOCATION_ERROR_SUCCESS != err) {
                     eraseTrackingSession(client, sessionId);
+                } else {
+                    checkUpdateDgnssNtrip(false);
                 }
 
                 reportResponse(client, err, sessionId);
@@ -2660,9 +3106,11 @@
 {
     LocPosMode locPosMode = {};
     convertOptions(locPosMode, updatedOptions);
+    // save position mode parameters
+    setLocPositionMode(locPosMode);
 
     // inform engine hub that GNSS session is about to start
-    mEngHubProxy->gnssSetFixMode(locPosMode);
+    mEngHubProxy->gnssSetFixMode(mLocPositionMode);
     mEngHubProxy->gnssStartFix();
 
     // want to run SPE session at a fixed min interval in some automotive scenarios
@@ -2968,7 +3416,6 @@
             // else part: no QMI call is made, need to report back to client right away
         }
     }
-
     return reportToClientWithNoWait;
 }
 
@@ -2983,6 +3430,11 @@
         reportResponse(client, err, id);
     }));
 
+    if (isDgnssNmeaRequired()) {
+        mDgnssState &= ~DGNSS_STATE_NO_NMEA_PENDING;
+    }
+    stopDgnssNtrip();
+
     mSPEAlreadyRunningAtHighestInterval = false;
 }
 
@@ -3195,6 +3647,63 @@
 
 }
 
+// This function computes the VRP based latitude, longitude and alittude, and
+// north, east and up velocity and save the result into EHubTechReport.
+void
+GnssAdapter::computeVRPBasedLla(const UlpLocation& loc, GpsLocationExtended& locExt,
+                                const LeverArmConfigInfo& leverArmConfigInfo) {
+
+    float leverArm[3];
+    float rollPitchYaw[3];
+    double lla[3];
+
+    uint16_t locFlags = loc.gpsLocation.flags;
+    uint64_t locExtFlags = locExt.flags;
+
+    // check for SPE fix
+    if (!((locExtFlags & GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE) &&
+          (locExt.locOutputEngType == LOC_OUTPUT_ENGINE_SPE))){
+        LOC_LOGv("not SPE fix, return");
+        return;
+    }
+
+    // we can only do translation if we have VRP based lever ARM info
+    LeverArmTypeMask leverArmFlags = leverArmConfigInfo.leverArmValidMask;
+    if (!(leverArmFlags & LEVER_ARM_TYPE_GNSS_TO_VRP_BIT)) {
+        LOC_LOGd("no VRP based lever ARM info");
+        return;
+    }
+
+    leverArm[0] = leverArmConfigInfo.gnssToVRP.forwardOffsetMeters;
+    leverArm[1] = leverArmConfigInfo.gnssToVRP.sidewaysOffsetMeters;
+    leverArm[2] = leverArmConfigInfo.gnssToVRP.upOffsetMeters;
+
+    if ((locFlags & LOC_GPS_LOCATION_HAS_LAT_LONG) &&
+        (locFlags & LOC_GPS_LOCATION_HAS_ALTITUDE) &&
+        (locFlags & LOCATION_HAS_BEARING_BIT)) {
+
+        lla[0] = loc.gpsLocation.latitude * DEG2RAD;
+        lla[1] = loc.gpsLocation.longitude * DEG2RAD;
+        lla[2] = loc.gpsLocation.altitude;
+
+        rollPitchYaw[0] = 0.0f;
+        rollPitchYaw[1] = 0.0f;
+        rollPitchYaw[2] = loc.gpsLocation.bearing * DEG2RAD;
+
+        loc_convert_lla_gnss_to_vrp(lla, rollPitchYaw, leverArm);
+
+        // assign the converted value into position report and
+        // set up valid mask
+        locExt.llaVRPBased.latitude  = lla[0] * RAD2DEG;
+        locExt.llaVRPBased.longitude = lla[1] * RAD2DEG;
+        locExt.llaVRPBased.altitude  = lla[2];
+        locExt.flags |= GPS_LOCATION_EXTENDED_HAS_LLA_VRP_BASED;
+    } else {
+        LOC_LOGd("SPE fix missing latitude/longitude/alitutde");
+        return;
+    }
+}
+
 void
 GnssAdapter::reportPositionEvent(const UlpLocation& ulpLocation,
                                  const GpsLocationExtended& locationExtended,
@@ -3206,85 +3715,94 @@
     // this position is from QMI LOC API, then send report to engine hub
     // also, send out SPE fix promptly to the clients that have registered
     // with SPE report
-    LOC_LOGd("reportPositionEvent, eng type: %d, unpro %d, sess status %d",
-             locationExtended.locOutputEngType, ulpLocation.unpropagatedPosition,
-             status);
+    LOC_LOGd("reportPositionEvent, eng type: %d, unpro %d, sess status %d msInWeek %d",
+             locationExtended.locOutputEngType,
+             ulpLocation.unpropagatedPosition, status, msInWeek);
 
-    if (true == initEngHubProxy()){
-        // send the SPE fix to engine hub
-        mEngHubProxy->gnssReportPosition(ulpLocation, locationExtended, status);
-        // report out all SPE fix if it is not propagated, even for failed fix
-        if (false == ulpLocation.unpropagatedPosition) {
-            EngineLocationInfo engLocationInfo = {};
-            engLocationInfo.location = ulpLocation;
-            engLocationInfo.locationExtended = locationExtended;
-            engLocationInfo.sessionStatus = status;
-            reportEnginePositionsEvent(1, &engLocationInfo);
-        }
-        return;
-    }
-
-    // unpropagated report: is only for engine hub to consume and no need
-    // to send out to the clients
-    if (true == ulpLocation.unpropagatedPosition) {
-        return;
-    }
-
-    // Fix is from QMI, and it is not an unpropagated position and engine hub
-    // is not loaded, queue the message when message is processed, the position
-    // can be dispatched to requesting client that registers for SPE report
-    struct MsgReportPosition : public LocMsg {
+    struct MsgReportSPEPosition : public LocMsg {
         GnssAdapter& mAdapter;
-        const UlpLocation mUlpLocation;
-        const GpsLocationExtended mLocationExtended;
-        loc_sess_status mStatus;
+        mutable UlpLocation mUlpLocation;
+        mutable GpsLocationExtended mLocationExtended;
+        enum loc_sess_status mStatus;
         LocPosTechMask mTechMask;
-        GnssDataNotification mDataNotify;
+        mutable GnssDataNotification mDataNotify;
         int mMsInWeek;
-        bool mbIsDataValid;
-        inline MsgReportPosition(GnssAdapter& adapter,
-                                 const UlpLocation& ulpLocation,
-                                 const GpsLocationExtended& locationExtended,
-                                 loc_sess_status status,
-                                 LocPosTechMask techMask,
-                                 GnssDataNotification* pDataNotify,
-                                 int msInWeek) :
+
+        inline MsgReportSPEPosition(GnssAdapter& adapter,
+                                    const UlpLocation& ulpLocation,
+                                    const GpsLocationExtended& locationExtended,
+                                    enum loc_sess_status status,
+                                    LocPosTechMask techMask,
+                                    GnssDataNotification dataNotify,
+                                    int msInWeek) :
             LocMsg(),
             mAdapter(adapter),
             mUlpLocation(ulpLocation),
             mLocationExtended(locationExtended),
             mStatus(status),
             mTechMask(techMask),
-            mMsInWeek(msInWeek) {
-                memset(&mDataNotify, 0, sizeof(mDataNotify));
-                if (pDataNotify != nullptr) {
-                    mDataNotify = *pDataNotify;
-                    mbIsDataValid = true;
-                } else {
-                    mbIsDataValid = false;
-                }
-        }
+            mDataNotify(dataNotify),
+            mMsInWeek(msInWeek) {}
         inline virtual void proc() const {
+            if (mAdapter.mTimeBasedTrackingSessions.empty() &&
+                mAdapter.mDistanceBasedTrackingSessions.empty()) {
+                LOC_LOGd("reportPositionEvent, no session on-going, throw away the SPE reports");
+                return;
+            }
+
+            if (false == mUlpLocation.unpropagatedPosition && mDataNotify.size != 0) {
+                if (mMsInWeek >= 0) {
+                    mAdapter.getDataInformation((GnssDataNotification&)mDataNotify,
+                                                mMsInWeek);
+                }
+                mAdapter.reportData(mDataNotify);
+            }
+
+            if (true == mAdapter.initEngHubProxy()){
+                // send the SPE fix to engine hub
+                mAdapter.mEngHubProxy->gnssReportPosition(mUlpLocation, mLocationExtended, mStatus);
+                // report out all SPE fix if it is not propagated, even for failed fix
+                if (false == mUlpLocation.unpropagatedPosition) {
+                    EngineLocationInfo engLocationInfo = {};
+                    engLocationInfo.location = mUlpLocation;
+                    engLocationInfo.locationExtended = mLocationExtended;
+                    engLocationInfo.sessionStatus = mStatus;
+
+                    // obtain the VRP based latitude/longitude/altitude for SPE fix
+                    computeVRPBasedLla(engLocationInfo.location,
+                                       engLocationInfo.locationExtended,
+                                       mAdapter.mLocConfigInfo.leverArmConfigInfo);
+                    mAdapter.reportEnginePositions(1, &engLocationInfo);
+                }
+                return;
+            }
+
+            // unpropagated report: is only for engine hub to consume and no need
+            // to send out to the clients
+            if (true == mUlpLocation.unpropagatedPosition) {
+                return;
+            }
+
             // extract bug report info - this returns true if consumed by systemstatus
             SystemStatus* s = mAdapter.getSystemStatus();
             if ((nullptr != s) &&
                     ((LOC_SESS_SUCCESS == mStatus) || (LOC_SESS_INTERMEDIATE == mStatus))){
                 s->eventPosition(mUlpLocation, mLocationExtended);
             }
+
             mAdapter.reportPosition(mUlpLocation, mLocationExtended, mStatus, mTechMask);
-            if (true == mbIsDataValid) {
-                if (-1 != mMsInWeek) {
-                    mAdapter.getDataInformation((GnssDataNotification&)mDataNotify,
-                                                mMsInWeek);
-                }
-                mAdapter.reportData((GnssDataNotification&)mDataNotify);
-            }
         }
     };
 
-    sendMsg(new MsgReportPosition(*this, ulpLocation, locationExtended,
-                                  status, techMask,
-                                  pDataNotify, msInWeek));
+    if (mContext != NULL) {
+        GnssDataNotification dataNotifyCopy = {};
+        if (pDataNotify) {
+            dataNotifyCopy = *pDataNotify;
+            dataNotifyCopy.size = sizeof(dataNotifyCopy);
+        }
+        sendMsg(new MsgReportSPEPosition(*this, ulpLocation, locationExtended,
+                                          status, techMask, dataNotifyCopy, msInWeek));
+    }
 }
 
 void
@@ -3335,9 +3853,9 @@
 bool
 GnssAdapter::needReportForFlpClient(enum loc_sess_status status,
                                     LocPosTechMask techMask) {
-    if ((status == LOC_SESS_INTERMEDIATE) &&
-        !(techMask & LOC_POS_TECH_MASK_SENSORS) &&
-        (!getAllowFlpNetworkFixes())) {
+    if (((LOC_SESS_INTERMEDIATE == status) && !(techMask & LOC_POS_TECH_MASK_SENSORS) &&
+        (!getAllowFlpNetworkFixes())) ||
+        (LOC_SESS_FAILURE == status)) {
         return false;
     } else {
         return true;
@@ -3354,6 +3872,97 @@
             locationCallbacks.gnssMeasurementsCb == nullptr);
 }
 
+bool GnssAdapter::needToGenerateNmeaReport(const uint32_t &gpsTimeOfWeekMs,
+        const struct timespec32_t &apTimeStamp)
+{
+    bool retVal = false;
+    uint64_t currentTimeNsec = 0;
+
+    if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTimeBasedTrackingSessions.empty()) {
+        currentTimeNsec = (apTimeStamp.tv_sec * BILLION_NSEC + apTimeStamp.tv_nsec);
+        if ((GNSS_NMEA_REPORT_RATE_NHZ == ContextBase::sNmeaReportRate) ||
+                (GPS_DEFAULT_FIX_INTERVAL_MS <= mLocPositionMode.min_interval)) {
+            retVal = true;
+        } else { /*tbf is less than 1000 milli-seconds and NMEA reporting rate is set to 1Hz */
+            /* Always send NMEA string for first position report
+             * Send when gpsTimeOfWeekMs is closely aligned with integer boundary
+             */
+            if ((0 == mPrevNmeaRptTimeNsec) ||
+                (0 != gpsTimeOfWeekMs) && (NMEA_MIN_THRESHOLD_MSEC >= (gpsTimeOfWeekMs % 1000))) {
+                retVal = true;
+            } else {
+                uint64_t timeDiffMsec = ((currentTimeNsec - mPrevNmeaRptTimeNsec) / 1000000);
+                // Send when the delta time becomes >= 1 sec
+                if (NMEA_MAX_THRESHOLD_MSEC <= timeDiffMsec) {
+                    retVal = true;
+                }
+            }
+        }
+        if (true == retVal) {
+            mPrevNmeaRptTimeNsec = currentTimeNsec;
+        }
+    }
+    return retVal;
+}
+
+void
+GnssAdapter::logLatencyInfo()
+{
+    if (0 == mGnssLatencyInfoQueue.size()) {
+        LOC_LOGv("mGnssLatencyInfoQueue.size is 0");
+        return;
+    }
+    mGnssLatencyInfoQueue.front().hlosQtimer5 = getQTimerTickCount();
+    if (0 == mGnssLatencyInfoQueue.front().hlosQtimer3) {
+        /* if SPE from engine hub is not reported then hlosQtimer3 = 0, set it
+        equal to hlosQtimer2 to make sense */
+        LOC_LOGv("hlosQtimer3 is 0, setting it to hlosQtimer2");
+        mGnssLatencyInfoQueue.front().hlosQtimer3 = mGnssLatencyInfoQueue.front().hlosQtimer2;
+    }
+    if (0 == mGnssLatencyInfoQueue.front().hlosQtimer4) {
+        /* if PPE from engine hub is not reported then hlosQtimer4 = 0, set it
+        equal to hlosQtimer3 to make sense */
+        LOC_LOGv("hlosQtimer4 is 0, setting it to hlosQtimer3");
+        mGnssLatencyInfoQueue.front().hlosQtimer4 = mGnssLatencyInfoQueue.front().hlosQtimer3;
+    }
+    if (mGnssLatencyInfoQueue.front().hlosQtimer4 < mGnssLatencyInfoQueue.front().hlosQtimer3) {
+        /* hlosQtimer3 is timestamped when SPE from engine hub is reported,
+        and hlosQtimer4 is timestamped when PPE from engine hub is reported.
+        The order is random though, hence making sure the timestamps are sorted */
+        LOC_LOGv("hlosQtimer4 is < hlosQtimer3, swapping them");
+        std::swap(mGnssLatencyInfoQueue.front().hlosQtimer3,
+                  mGnssLatencyInfoQueue.front().hlosQtimer4);
+    }
+    LOC_LOGv("meQtimer1=%" PRIi64 " "
+             "meQtimer2=%" PRIi64 " "
+             "meQtimer3=%" PRIi64 " "
+             "peQtimer1=%" PRIi64 " "
+             "peQtimer2=%" PRIi64 " "
+             "peQtimer3=%" PRIi64 " "
+             "smQtimer1=%" PRIi64 " "
+             "smQtimer2=%" PRIi64 " "
+             "smQtimer3=%" PRIi64 " "
+             "locMwQtimer=%" PRIi64 " "
+             "hlosQtimer1=%" PRIi64 " "
+             "hlosQtimer2=%" PRIi64 " "
+             "hlosQtimer3=%" PRIi64 " "
+             "hlosQtimer4=%" PRIi64 " "
+             "hlosQtimer5=%" PRIi64 " ",
+             mGnssLatencyInfoQueue.front().meQtimer1, mGnssLatencyInfoQueue.front().meQtimer2,
+             mGnssLatencyInfoQueue.front().meQtimer3, mGnssLatencyInfoQueue.front().peQtimer1,
+             mGnssLatencyInfoQueue.front().peQtimer2, mGnssLatencyInfoQueue.front().peQtimer3,
+             mGnssLatencyInfoQueue.front().smQtimer1, mGnssLatencyInfoQueue.front().smQtimer2,
+             mGnssLatencyInfoQueue.front().smQtimer3, mGnssLatencyInfoQueue.front().locMwQtimer,
+             mGnssLatencyInfoQueue.front().hlosQtimer1, mGnssLatencyInfoQueue.front().hlosQtimer2,
+             mGnssLatencyInfoQueue.front().hlosQtimer3, mGnssLatencyInfoQueue.front().hlosQtimer4,
+             mGnssLatencyInfoQueue.front().hlosQtimer5);
+    mLogger.log(mGnssLatencyInfoQueue.front());
+    mGnssLatencyInfoQueue.pop();
+    LOC_LOGv("mGnssLatencyInfoQueue.size after pop=%zu", mGnssLatencyInfoQueue.size());
+}
+
+// only fused report (when engine hub is enabled) or
+// SPE report (when engine hub is disabled) will reach this function
 void
 GnssAdapter::reportPosition(const UlpLocation& ulpLocation,
                             const GpsLocationExtended& locationExtended,
@@ -3365,16 +3974,16 @@
 
     if (reportToGnssClient || reportToFlpClient) {
         GnssLocationInfoNotification locationInfo = {};
-        convertLocationInfo(locationInfo, locationExtended);
-        convertLocation(locationInfo.location, ulpLocation, locationExtended, techMask);
-
+        convertLocationInfo(locationInfo, locationExtended, status);
+        convertLocation(locationInfo.location, ulpLocation, locationExtended);
+        logLatencyInfo();
         for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
             if ((reportToFlpClient && isFlpClient(it->second)) ||
                     (reportToGnssClient && !isFlpClient(it->second))) {
                 if (nullptr != it->second.gnssLocationInfoCb) {
                     it->second.gnssLocationInfoCb(locationInfo);
                 } else if ((nullptr != it->second.engineLocationsInfoCb) &&
-                        (false == initEngHubProxy())) {
+                           (false == initEngHubProxy())) {
                     // if engine hub is disabled, this is SPE fix from modem
                     // we need to mark one copy marked as fused and one copy marked as PPE
                     // and dispatch it to the engineLocationsInfoCb
@@ -3402,18 +4011,24 @@
                 }
             }
 
-            // if PACE is enabled and engine hub is running and the fix is from sensor,
-            // e.g.: DRE, inject DRE fix to modem
-            if ((true == mLocConfigInfo.paceConfigInfo.isValid &&
-                 true == mLocConfigInfo.paceConfigInfo.enable) &&
-                (true == initEngHubProxy()) && (LOC_POS_TECH_MASK_SENSORS & techMask)) {
-                mLocApi->injectPosition(locationInfo, false);
+            // if PACE is enabled
+            if ((true == mLocConfigInfo.paceConfigInfo.isValid) &&
+                (true == mLocConfigInfo.paceConfigInfo.enable)) {
+                // If fix has sensor contribution, and it is fused fix with DRE engine
+                // contributing to the fix, inject to modem
+                if ((LOC_POS_TECH_MASK_SENSORS & techMask) &&
+                        (locationInfo.flags & GNSS_LOCATION_INFO_OUTPUT_ENG_TYPE_BIT) &&
+                        (locationInfo.locOutputEngType == LOC_OUTPUT_ENGINE_FUSED) &&
+                        (locationInfo.flags & GNSS_LOCATION_INFO_OUTPUT_ENG_MASK_BIT) &&
+                        (locationInfo.locOutputEngMask & DEAD_RECKONING_ENGINE)) {
+                    mLocApi->injectPosition(locationInfo, false);
+                }
             }
         }
     }
 
-    if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER &&
-        !mTimeBasedTrackingSessions.empty()) {
+    if (needToGenerateNmeaReport(locationExtended.gpsTime.gpsTimeOfWeekMs,
+            locationExtended.timeStamp.apTimeStamp)) {
         /*Only BlankNMEA sentence needs to be processed and sent, if both lat, long is 0 &
           horReliability is not set. */
         bool blank_fix = ((0 == ulpLocation.gpsLocation.latitude) &&
@@ -3421,19 +4036,50 @@
                           (LOC_RELIABILITY_NOT_SET == locationExtended.horizontal_reliability));
         uint8_t generate_nmea = (reportToGnssClient && status != LOC_SESS_FAILURE && !blank_fix);
         bool custom_nmea_gga = (1 == ContextBase::mGps_conf.CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED);
+        bool isTagBlockGroupingEnabled =
+                (1 == ContextBase::mGps_conf.NMEA_TAG_BLOCK_GROUPING_ENABLED);
         std::vector<std::string> nmeaArraystr;
-        loc_nmea_generate_pos(ulpLocation, locationExtended, mLocSystemInfo,
-                              generate_nmea, custom_nmea_gga, nmeaArraystr);
+        int indexOfGGA = -1;
+        loc_nmea_generate_pos(ulpLocation, locationExtended, mLocSystemInfo, generate_nmea,
+                custom_nmea_gga, nmeaArraystr, indexOfGGA, isTagBlockGroupingEnabled);
         stringstream ss;
         for (auto itor = nmeaArraystr.begin(); itor != nmeaArraystr.end(); ++itor) {
             ss << *itor;
         }
         string s = ss.str();
         reportNmea(s.c_str(), s.length());
+
+        /* DgnssNtrip */
+        if (-1 != indexOfGGA && isDgnssNmeaRequired()) {
+            mDgnssState |= DGNSS_STATE_NO_NMEA_PENDING;
+            mStartDgnssNtripParams.nmea = std::move(nmeaArraystr[indexOfGGA]);
+            bool isLocationValid = (0 != ulpLocation.gpsLocation.latitude) ||
+                    (0 != ulpLocation.gpsLocation.longitude);
+            checkUpdateDgnssNtrip(isLocationValid);
+        }
     }
 }
 
 void
+GnssAdapter::reportLatencyInfoEvent(const GnssLatencyInfo& gnssLatencyInfo)
+{
+    struct MsgReportLatencyInfo : public LocMsg {
+        GnssAdapter& mAdapter;
+        GnssLatencyInfo mGnssLatencyInfo;
+        inline MsgReportLatencyInfo(GnssAdapter& adapter,
+            const GnssLatencyInfo& gnssLatencyInfo) :
+            mGnssLatencyInfo(gnssLatencyInfo),
+            mAdapter(adapter) {}
+        inline virtual void proc() const {
+            mAdapter.mGnssLatencyInfoQueue.push(mGnssLatencyInfo);
+            LOC_LOGv("mGnssLatencyInfoQueue.size after push=%zu",
+                      mAdapter.mGnssLatencyInfoQueue.size());
+        }
+    };
+    sendMsg(new MsgReportLatencyInfo(*this, gnssLatencyInfo));
+}
+
+void
 GnssAdapter::reportEnginePositions(unsigned int count,
                                    const EngineLocationInfo* locationArr)
 {
@@ -3458,14 +4104,30 @@
         }
 
         if (needReportEnginePositions) {
-            convertLocationInfo(locationInfo[i], engLocation->locationExtended);
+            convertLocationInfo(locationInfo[i], engLocation->locationExtended,
+                                engLocation->sessionStatus);
             convertLocation(locationInfo[i].location,
                             engLocation->location,
-                            engLocation->locationExtended,
-                            engLocation->location.tech_mask);
+                            engLocation->locationExtended);
         }
     }
 
+    const EngineLocationInfo* engLocation = locationArr;
+    LOC_LOGv("engLocation->locationExtended.locOutputEngType=%d",
+             engLocation->locationExtended.locOutputEngType);
+
+    if (0 != mGnssLatencyInfoQueue.size()) {
+        if ((GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE & engLocation->locationExtended.flags) &&
+            (LOC_OUTPUT_ENGINE_SPE == engLocation->locationExtended.locOutputEngType)) {
+            mGnssLatencyInfoQueue.front().hlosQtimer3 = getQTimerTickCount();
+            LOC_LOGv("SPE hlosQtimer3=%" PRIi64 " ", mGnssLatencyInfoQueue.front().hlosQtimer3);
+        }
+        if ((GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE & engLocation->locationExtended.flags) &&
+            (LOC_OUTPUT_ENGINE_PPE == engLocation->locationExtended.locOutputEngType)) {
+            mGnssLatencyInfoQueue.front().hlosQtimer4 = getQTimerTickCount();
+            LOC_LOGv("PPE hlosQtimer4=%" PRIi64 " ", mGnssLatencyInfoQueue.front().hlosQtimer4);
+        }
+    }
     if (needReportEnginePositions) {
         for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
             if (nullptr != it->second.engineLocationsInfoCb) {
@@ -3506,7 +4168,7 @@
 GnssAdapter::reportSv(GnssSvNotification& svNotify)
 {
     int numSv = svNotify.count;
-    int16_t gnssSvId = 0;
+    uint16_t gnssSvId = 0;
     uint64_t svUsedIdMask = 0;
     for (int i=0; i < numSv; i++) {
         svUsedIdMask = 0;
@@ -3550,6 +4212,9 @@
                         svUsedIdMask = mGnssSvIdUsedInPosition.glo_sv_used_ids_mask;
                     }
                 }
+                // map the svid to respective constellation range 1..xx
+                // then repective constellation svUsedIdMask map correctly to svid
+                gnssSvId = gnssSvId - GLO_SV_PRN_MIN + 1;
                 break;
             case GNSS_SV_TYPE_BEIDOU:
                 if (mGnssSvIdUsedInPosAvail) {
@@ -3575,6 +4240,7 @@
                         svUsedIdMask = mGnssSvIdUsedInPosition.bds_sv_used_ids_mask;
                     }
                 }
+                gnssSvId = gnssSvId - BDS_SV_PRN_MIN + 1;
                 break;
             case GNSS_SV_TYPE_GALILEO:
                 if (mGnssSvIdUsedInPosAvail) {
@@ -3594,6 +4260,7 @@
                         svUsedIdMask = mGnssSvIdUsedInPosition.gal_sv_used_ids_mask;
                     }
                 }
+                gnssSvId = gnssSvId - GAL_SV_PRN_MIN + 1;
                 break;
             case GNSS_SV_TYPE_QZSS:
                 if (mGnssSvIdUsedInPosAvail) {
@@ -3616,15 +4283,13 @@
                         svUsedIdMask = mGnssSvIdUsedInPosition.qzss_sv_used_ids_mask;
                     }
                 }
-                // QZSS SV id's need to reported as it is to framework, since
-                // framework expects it as it is. See GnssStatus.java.
-                // SV id passed to here by LocApi is 1-based.
-                svNotify.gnssSvs[i].svId += (QZSS_SV_PRN_MIN - 1);
+                gnssSvId = gnssSvId - QZSS_SV_PRN_MIN + 1;
                 break;
             case GNSS_SV_TYPE_NAVIC:
                 if (mGnssSvIdUsedInPosAvail) {
                     svUsedIdMask = mGnssSvIdUsedInPosition.navic_sv_used_ids_mask;
                 }
+                gnssSvId = gnssSvId - NAVIC_SV_PRN_MIN + 1;
                 break;
             default:
                 svUsedIdMask = 0;
@@ -3633,7 +4298,7 @@
 
         // If SV ID was used in previous position fix, then set USED_IN_FIX
         // flag, else clear the USED_IN_FIX flag.
-        if ((gnssSvId < 64) && (svUsedIdMask & (1ULL << (gnssSvId - 1)))) {
+        if (svFitsMask(svUsedIdMask, gnssSvId) && (svUsedIdMask & (1ULL << (gnssSvId - 1)))) {
             svNotify.gnssSvs[i].gnssSvOptionsMask |= GNSS_SV_OPTIONS_USED_IN_FIX_BIT;
         }
     }
@@ -3657,6 +4322,7 @@
     }
 
     mGnssSvIdUsedInPosAvail = false;
+    mGnssMbSvIdUsedInPosAvail = false;
 }
 
 void
@@ -3698,6 +4364,8 @@
             if (false == ret) {
                 // forward NMEA message to upper layer
                 mAdapter.reportNmea(mNmea, mLength);
+                // DgnssNtrip
+                mAdapter.reportGGAToNtrip(mNmea);
             }
         }
     };
@@ -3723,6 +4391,10 @@
             it->second.gnssNmeaCb(nmeaNotification);
         }
     }
+
+    if (isNMEAPrintEnabled()) {
+        LOC_LOGd("[%" PRId64 ", %zu] %s", now, length, nmea);
+    }
 }
 
 void
@@ -3734,15 +4406,15 @@
         GnssDataNotification mDataNotify;
         int mMsInWeek;
         inline MsgReportData(GnssAdapter& adapter,
-            const GnssDataNotification& dataNotify,
-            int msInWeek) :
+                             const GnssDataNotification& dataNotify,
+                             int msInWeek) :
             LocMsg(),
             mAdapter(adapter),
             mDataNotify(dataNotify),
             mMsInWeek(msInWeek) {
         }
         inline virtual void proc() const {
-            if (-1 != mMsInWeek) {
+            if (mMsInWeek >= 0) {
                 mAdapter.getDataInformation((GnssDataNotification&)mDataNotify,
                                             mMsInWeek);
             }
@@ -4081,6 +4753,9 @@
         sendMsg(new MsgReportGnssMeasurementData(*this, gnssMeasurements, msInWeek));
     }
     mEngHubProxy->gnssReportSvMeasurement(gnssMeasurements.gnssSvMeasurementSet);
+    if (mDGnssNeedReport) {
+        reportDGnssDataUsable(gnssMeasurements.gnssSvMeasurementSet);
+    }
 }
 
 void
@@ -4094,6 +4769,27 @@
 }
 
 void
+GnssAdapter::reportDGnssDataUsable(const GnssSvMeasurementSet &svMeasurementSet)
+{
+    uint32_t i;
+    bool preDGnssDataUsage = mDGnssDataUsage;
+
+    mDGnssDataUsage = false;
+    for (i = 0; i < svMeasurementSet.svMeasCount; i++) {
+        const Gnss_SVMeasurementStructType& svMeas = svMeasurementSet.svMeas[i];
+        if (svMeas.dgnssSvMeas.dgnssMeasStatus) {
+            mDGnssDataUsage = true;
+            break;
+        }
+    }
+    if (mDGnssDataUsage != preDGnssDataUsage) {
+        if (mCdfwInterface) {
+            mCdfwInterface->reportUsable(mQDgnssListenerHDL, mDGnssDataUsage);
+        }
+    }
+}
+
+void
 GnssAdapter::reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial)
 {
     LOC_LOGD("%s]: ", __func__);
@@ -4164,8 +4860,12 @@
         // the request is being stopped, but allow timer to expire first
         // before stopping the timer just in case more ODCPI requests come
         // to avoid spamming more odcpi requests to the framework
-        } else {
+        } else if (ODCPI_REQUEST_TYPE_STOP == request.type) {
+            LOC_LOGd("request: type %d, isEmergency %d", request.type, request.isEmergencyMode);
+            mOdcpiRequestCb(request);
             mOdcpiRequestActive = false;
+        } else {
+            LOC_LOGE("Invalid ODCPI request type..");
         }
     } else {
         LOC_LOGw("ODCPI request not supported");
@@ -4194,31 +4894,63 @@
     return true;
 }
 
-void GnssAdapter::initOdcpiCommand(const OdcpiRequestCallback& callback)
+bool GnssAdapter::reportQwesCapabilities(
+        const std::unordered_map<LocationQwesFeatureType, bool> &featureMap)
+{
+    struct MsgReportQwesFeatureStatus : public LocMsg {
+        GnssAdapter& mAdapter;
+        const std::unordered_map<LocationQwesFeatureType, bool> mFeatureMap;
+        inline MsgReportQwesFeatureStatus(GnssAdapter& adapter,
+                const std::unordered_map<LocationQwesFeatureType, bool> &featureMap) :
+            LocMsg(),
+            mAdapter(adapter),
+            mFeatureMap(std::move(featureMap)) {}
+        inline virtual void proc() const {
+            LOC_LOGi("ReportQwesFeatureStatus before caps %" PRIx64 " ",
+                mAdapter.getCapabilities());
+            ContextBase::setQwesFeatureStatus(mFeatureMap);
+            LOC_LOGi("ReportQwesFeatureStatus After caps %" PRIx64 " ",
+                mAdapter.getCapabilities());
+            mAdapter.broadcastCapabilities(mAdapter.getCapabilities());
+        }
+    };
+
+    sendMsg(new MsgReportQwesFeatureStatus(*this, featureMap));
+    return true;
+}
+
+void GnssAdapter::initOdcpiCommand(const OdcpiRequestCallback& callback,
+                                   OdcpiPrioritytype priority)
 {
     struct MsgInitOdcpi : public LocMsg {
         GnssAdapter& mAdapter;
         OdcpiRequestCallback mOdcpiCb;
+        OdcpiPrioritytype mPriority;
         inline MsgInitOdcpi(GnssAdapter& adapter,
-                const OdcpiRequestCallback& callback) :
+                const OdcpiRequestCallback& callback,
+                OdcpiPrioritytype priority) :
                 LocMsg(),
                 mAdapter(adapter),
-                mOdcpiCb(callback) {}
+                mOdcpiCb(callback), mPriority(priority){}
         inline virtual void proc() const {
-            mAdapter.initOdcpi(mOdcpiCb);
+            mAdapter.initOdcpi(mOdcpiCb, mPriority);
         }
     };
 
-    sendMsg(new MsgInitOdcpi(*this, callback));
+    sendMsg(new MsgInitOdcpi(*this, callback, priority));
 }
 
-void GnssAdapter::initOdcpi(const OdcpiRequestCallback& callback)
+void GnssAdapter::initOdcpi(const OdcpiRequestCallback& callback,
+            OdcpiPrioritytype priority)
 {
-    mOdcpiRequestCb = callback;
-
-    /* Register for WIFI request */
-    updateEvtMask(LOC_API_ADAPTER_BIT_REQUEST_WIFI,
-            LOC_REGISTRATION_MASK_ENABLED);
+    LOC_LOGd("In priority: %d, Curr priority: %d", priority, mCallbackPriority);
+    if (priority >= mCallbackPriority) {
+        mOdcpiRequestCb = callback;
+        mCallbackPriority = priority;
+        /* Register for WIFI request */
+        updateEvtMask(LOC_API_ADAPTER_BIT_REQUEST_WIFI,
+                LOC_REGISTRATION_MASK_ENABLED);
+    }
 }
 
 void GnssAdapter::injectOdcpiCommand(const Location& location)
@@ -4316,23 +5048,20 @@
 
 void GnssAdapter::initDefaultAgps() {
     LOC_LOGD("%s]: ", __func__);
-
     void *handle = nullptr;
-    if ((handle = dlopen("libloc_net_iface.so", RTLD_NOW)) == nullptr) {
-        LOC_LOGD("%s]: libloc_net_iface.so not found !", __func__);
-        return;
-    }
 
-    LocAgpsGetAgpsCbInfo getAgpsCbInfo = (LocAgpsGetAgpsCbInfo)
-            dlsym(handle, "LocNetIfaceAgps_getAgpsCbInfo");
-    if (getAgpsCbInfo == nullptr) {
-        LOC_LOGE("%s]: Failed to get method LocNetIfaceAgps_getStatusCb", __func__);
-        dlclose(handle);
-        return;
+    LocAgpsGetAgpsCbInfo getAgpsCbInfo =
+        (LocAgpsGetAgpsCbInfo)dlGetSymFromLib(handle, "libloc_net_iface.so",
+            "LocNetIfaceAgps_getAgpsCbInfo");
+    // Below step is to make sure we init nativeAgpsHandler
+    // for Android platforms only
+    AgpsCbInfo cbInfo = {};
+    if (nullptr != getAgpsCbInfo) {
+        cbInfo = getAgpsCbInfo(agpsOpenResultCb, agpsCloseResultCb, this);
+    } else {
+        cbInfo = mNativeAgpsHandler.getAgpsCbInfo();
     }
 
-    AgpsCbInfo& cbInfo = getAgpsCbInfo(agpsOpenResultCb, agpsCloseResultCb, this);
-
     if (cbInfo.statusV4Cb == nullptr) {
         LOC_LOGE("%s]: statusV4Cb is nullptr!", __func__);
         dlclose(handle);
@@ -4497,6 +5226,38 @@
     return true;
 }
 
+void GnssAdapter::reportPdnTypeFromWds(int pdnType, AGpsExtType agpsType, std::string apnName,
+        AGpsBearerType bearerType) {
+    LOC_LOGd("pdnType from WDS QMI: %d, agpsType: %d, apnName: %s, bearerType: %d",
+            pdnType, agpsType, apnName.c_str(), bearerType);
+
+    struct MsgReportAtlPdn : public LocMsg {
+        GnssAdapter& mAdapter;
+        int mPdnType;
+        AgpsManager* mAgpsManager;
+        AGpsExtType mAgpsType;
+        string mApnName;
+        AGpsBearerType mBearerType;
+
+        inline MsgReportAtlPdn(GnssAdapter& adapter, int pdnType,
+                AgpsManager* agpsManager, AGpsExtType agpsType,
+                const string& apnName, AGpsBearerType bearerType) :
+            LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType),
+            mApnName(apnName), mBearerType(bearerType),
+            mAdapter(adapter), mPdnType(pdnType) {}
+        inline virtual void proc() const {
+            mAgpsManager->reportAtlOpenSuccess(mAgpsType,
+                    const_cast<char*>(mApnName.c_str()),
+                    mApnName.length(), mPdnType<=0? mBearerType:mPdnType);
+        }
+    };
+
+    AGpsBearerType atlPdnType = (pdnType+1) & 3; // convert WDS QMI pdn type to AgpsBearerType
+    sendMsg(new MsgReportAtlPdn(*this, atlPdnType, &mAgpsManager,
+                agpsType, apnName, bearerType));
+}
+
+
 void GnssAdapter::dataConnOpenCommand(
         AGpsExtType agpsType,
         const char* apnName, int apnLen, AGpsBearerType bearerType){
@@ -4504,17 +5265,16 @@
     LOC_LOGI("GnssAdapter::frameworkDataConnOpen");
 
     struct AgpsMsgAtlOpenSuccess: public LocMsg {
-
+        GnssAdapter& mAdapter;
         AgpsManager* mAgpsManager;
         AGpsExtType mAgpsType;
         char* mApnName;
-        int mApnLen;
         AGpsBearerType mBearerType;
 
-        inline AgpsMsgAtlOpenSuccess(AgpsManager* agpsManager, AGpsExtType agpsType,
-                const char* apnName, int apnLen, AGpsBearerType bearerType) :
+        inline AgpsMsgAtlOpenSuccess(GnssAdapter& adapter, AgpsManager* agpsManager,
+                AGpsExtType agpsType, const char* apnName, int apnLen, AGpsBearerType bearerType) :
                 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType), mApnName(
-                        new char[apnLen + 1]), mApnLen(apnLen), mBearerType(bearerType) {
+                        new char[apnLen + 1]), mBearerType(bearerType), mAdapter(adapter) {
 
             LOC_LOGV("AgpsMsgAtlOpenSuccess");
             if (mApnName == nullptr) {
@@ -4532,18 +5292,36 @@
         }
 
         inline virtual void proc() const {
+            LOC_LOGv("AgpsMsgAtlOpenSuccess::proc()");
+            string apn(mApnName);
+            //Use QMI WDS API to query IP Protocol from modem profile
+            void* libHandle = nullptr;
+            getPdnTypeFromWds* getPdnTypeFunc = (getPdnTypeFromWds*)dlGetSymFromLib(libHandle,
+            #ifdef USE_GLIB
+                    "libloc_api_wds.so", "_Z10getPdnTypeRKNSt7__cxx1112basic_string"\
+                    "IcSt11char_traitsIcESaIcEEESt8functionIFviEE");
+            #else
+                    "libloc_api_wds.so", "_Z10getPdnTypeRKNSt3__112basic_stringIcNS_11char_traits"\
+                    "IcEENS_9allocatorIcEEEENS_8functionIFviEEE");
+            #endif
 
-            LOC_LOGV("AgpsMsgAtlOpenSuccess::proc()");
-            mAgpsManager->reportAtlOpenSuccess(mAgpsType, mApnName, mApnLen, mBearerType);
+            std::function<void(int)> wdsPdnTypeCb = std::bind(&GnssAdapter::reportPdnTypeFromWds,
+                    &mAdapter, std::placeholders::_1, mAgpsType, apn, mBearerType);
+           if (getPdnTypeFunc != nullptr) {
+               LOC_LOGv("dlGetSymFromLib success");
+               (*getPdnTypeFunc)(apn, wdsPdnTypeCb);
+           } else {
+               mAgpsManager->reportAtlOpenSuccess(mAgpsType, mApnName, apn.length(), mBearerType);
+           }
         }
     };
     // Added inital length checks for apnlen check to avoid security issues
     // In case of failure reporting the same
-    if (NULL == apnName || apnLen <= 0 || apnLen > MAX_APN_LEN || (strlen(apnName) != apnLen)) {
+    if (NULL == apnName || apnLen > MAX_APN_LEN || (strlen(apnName) != (unsigned)apnLen)) {
         LOC_LOGe("%s]: incorrect apnlen length or incorrect apnName", __func__);
         mAgpsManager.reportAtlClosed(agpsType);
     } else {
-        sendMsg( new AgpsMsgAtlOpenSuccess(
+        sendMsg( new AgpsMsgAtlOpenSuccess(*this,
                     &mAgpsManager, agpsType, apnName, apnLen, bearerType));
     }
 }
@@ -4873,28 +5651,28 @@
                 case GNSS_SV_TYPE_GPS:
                 case GNSS_SV_TYPE_QZSS:
                     measurements.measurements[i].agcLevelDb =
-                            reports.mRfAndParams.back().mAgcGps;
+                            (double)-reports.mRfAndParams.back().mJammerGps;
                     measurements.measurements[i].flags |=
                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
                     break;
 
                 case GNSS_SV_TYPE_GALILEO:
                     measurements.measurements[i].agcLevelDb =
-                            reports.mRfAndParams.back().mAgcGal;
+                            (double)-reports.mRfAndParams.back().mJammerGal;
                     measurements.measurements[i].flags |=
                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
                     break;
 
                 case GNSS_SV_TYPE_GLONASS:
                     measurements.measurements[i].agcLevelDb =
-                            reports.mRfAndParams.back().mAgcGlo;
+                            (double)-reports.mRfAndParams.back().mJammerGlo;
                     measurements.measurements[i].flags |=
                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
                     break;
 
                 case GNSS_SV_TYPE_BEIDOU:
                     measurements.measurements[i].agcLevelDb =
-                            reports.mRfAndParams.back().mAgcBds;
+                            (double)-reports.mRfAndParams.back().mJammerBds;
                     measurements.measurements[i].flags |=
                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
                     break;
@@ -4929,67 +5707,47 @@
                 data.jammerInd[sig] = 0.0;
                 data.agc[sig] = 0.0;
             }
-            if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mAgcGps) {
-                data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] |=
-                        GNSS_LOC_DATA_AGC_BIT;
-                data.agc[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] =
-                        reports.mRfAndParams.back().mAgcGps;
-                data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] |=
-                        GNSS_LOC_DATA_AGC_BIT;
-                data.agc[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] =
-                        reports.mRfAndParams.back().mAgcGps;
-                data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] |=
-                        GNSS_LOC_DATA_AGC_BIT;
-                data.agc[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] =
-                    reports.mRfAndParams.back().mAgcGps;
-            }
             if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerGps) {
                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] |=
-                        GNSS_LOC_DATA_JAMMER_IND_BIT;
+                        GNSS_LOC_DATA_AGC_BIT | GNSS_LOC_DATA_JAMMER_IND_BIT;
+                data.agc[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] =
+                        (double)-reports.mRfAndParams.back().mJammerGps;
                 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] =
                         (double)reports.mRfAndParams.back().mJammerGps;
                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] |=
-                        GNSS_LOC_DATA_JAMMER_IND_BIT;
+                        GNSS_LOC_DATA_AGC_BIT | GNSS_LOC_DATA_JAMMER_IND_BIT;
+                data.agc[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] =
+                        (double)-reports.mRfAndParams.back().mJammerGps;
                 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] =
                         (double)reports.mRfAndParams.back().mJammerGps;
                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] |=
-                        GNSS_LOC_DATA_JAMMER_IND_BIT;
+                        GNSS_LOC_DATA_AGC_BIT | GNSS_LOC_DATA_JAMMER_IND_BIT;
+                data.agc[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] =
+                        (double)-reports.mRfAndParams.back().mJammerGps;
                 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] =
-                    (double)reports.mRfAndParams.back().mJammerGps;
-            }
-            if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mAgcGlo) {
-                data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] |=
-                        GNSS_LOC_DATA_AGC_BIT;
-                data.agc[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] =
-                        reports.mRfAndParams.back().mAgcGlo;
+                        (double)reports.mRfAndParams.back().mJammerGps;
             }
             if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerGlo) {
                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] |=
-                        GNSS_LOC_DATA_JAMMER_IND_BIT;
+                        GNSS_LOC_DATA_AGC_BIT | GNSS_LOC_DATA_JAMMER_IND_BIT;
+                data.agc[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] =
+                        (double)-reports.mRfAndParams.back().mJammerGlo;
                 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] =
                         (double)reports.mRfAndParams.back().mJammerGlo;
             }
-            if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mAgcBds) {
-                data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] |=
-                        GNSS_LOC_DATA_AGC_BIT;
-                data.agc[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] =
-                        reports.mRfAndParams.back().mAgcBds;
-            }
             if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerBds) {
                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] |=
-                        GNSS_LOC_DATA_JAMMER_IND_BIT;
+                        GNSS_LOC_DATA_AGC_BIT | GNSS_LOC_DATA_JAMMER_IND_BIT;
+                data.agc[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] =
+                        (double)-reports.mRfAndParams.back().mJammerBds;
                 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] =
                         (double)reports.mRfAndParams.back().mJammerBds;
             }
-            if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mAgcGal) {
-                data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] |=
-                        GNSS_LOC_DATA_AGC_BIT;
-                data.agc[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] =
-                        reports.mRfAndParams.back().mAgcGal;
-            }
             if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerGal) {
                 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] |=
-                        GNSS_LOC_DATA_JAMMER_IND_BIT;
+                        GNSS_LOC_DATA_AGC_BIT | GNSS_LOC_DATA_JAMMER_IND_BIT;
+                data.agc[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] =
+                        (double)-reports.mRfAndParams.back().mJammerGal;
                 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] =
                         (double)reports.mRfAndParams.back().mJammerGal;
             }
@@ -5204,40 +5962,54 @@
     return sessionId;
 }
 
-void
-GnssAdapter::updateSvConfig(uint32_t         sessionId,
-                            const GnssSvTypeConfig& svTypeConfig,
-                            const GnssSvIdConfig&   svIdConfig) {
+void GnssAdapter::gnssUpdateSvConfig(
+        uint32_t sessionId, const GnssSvTypeConfig& constellationEnablementConfig,
+        const GnssSvIdConfig&   blacklistSvConfig) {
 
-    // check whether if any constellation is removed from the new config
-    GnssSvTypesMask enabledRemoved = mGnssSvTypeConfig.enabledSvTypesMask &
-            (mGnssSvTypeConfig.enabledSvTypesMask ^ svTypeConfig.enabledSvTypesMask);
-    // Send reset if any constellation is removed from the enabled list
-    if (enabledRemoved != 0) {
+    // suspend all tracking sessions to apply the constellation config
+    suspendSessions();
+    if (constellationEnablementConfig.size == sizeof(constellationEnablementConfig)) {
+        // check whether if any constellation is removed from the new config
+        GnssSvTypesMask currentEnabledMask = mGnssSvTypeConfig.enabledSvTypesMask;
+        GnssSvTypesMask newEnabledMask = constellationEnablementConfig.enabledSvTypesMask;
+        GnssSvTypesMask enabledRemoved = currentEnabledMask & (currentEnabledMask ^ newEnabledMask);
+        // Send reset if any constellation is removed from the enabled list
+        if (enabledRemoved != 0) {
+            mLocApi->resetConstellationControl();
+        }
+
+        // if the constellation config is valid, issue request to modem
+        // to enable/disable constellation
+        mLocApi->setConstellationControl(mGnssSvTypeConfig);
+    } else if (constellationEnablementConfig.size == 0) {
+        // when the size is not set, meaning reset to modem default
         mLocApi->resetConstellationControl();
     }
+    // save the constellation settings to be used for modem SSR
+    mGnssSvTypeConfig = constellationEnablementConfig;
 
-    mGnssSvTypeConfig = svTypeConfig;
-    mGnssSvIdConfig   = svIdConfig;
-
-    // Send blacklist info
-    mLocApi->setBlacklistSv(mGnssSvIdConfig);
-
-    // Send only enabled constellation config
-    GnssSvTypeConfig svTypeConfigCopy = {sizeof(GnssSvTypeConfig), 0, 0};
-    svTypeConfigCopy.enabledSvTypesMask = mGnssSvTypeConfig.enabledSvTypesMask;
+    // handle blacklisted SV settings
+    mGnssSvIdConfig   = blacklistSvConfig;
+    // process blacklist svs info
+    mBlacklistedSvIds.clear();
+    // need to save the balcklisted sv info into mBlacklistedSvIds as well
+    convertFromGnssSvIdConfig(blacklistSvConfig, mBlacklistedSvIds);
     LocApiResponse* locApiResponse = new LocApiResponse(*getContext(),
             [this, sessionId] (LocationError err) {
             reportResponse(err, sessionId);});
     if (!locApiResponse) {
         LOC_LOGe("memory alloc failed");
     }
-    mLocApi->setConstellationControl(svTypeConfigCopy, locApiResponse);
+    mLocApi->setBlacklistSv(mGnssSvIdConfig, locApiResponse);
+
+    // resume all tracking sessions after the constellation config has been applied
+    restartSessions(false);
 }
 
-uint32_t GnssAdapter::gnssUpdateSvConfigCommand(
-        const GnssSvTypeConfig& svTypeConfig,
-        const GnssSvIdConfig& svIdConfig) {
+uint32_t
+GnssAdapter::gnssUpdateSvConfigCommand(
+        const GnssSvTypeConfig& constellationEnablementConfig,
+        const GnssSvIdConfig& blacklistSvConfig) {
 
     // generated session id will be none-zero
     uint32_t sessionId = generateSessionId();
@@ -5246,67 +6018,115 @@
     struct MsgUpdateSvConfig : public LocMsg {
         GnssAdapter&     mAdapter;
         uint32_t         mSessionId;
-        GnssSvTypeConfig mSvTypeConfig;
-        GnssSvIdConfig   mSvIdConfig;
+        GnssSvTypeConfig mConstellationEnablementConfig;
+        GnssSvIdConfig   mBlacklistSvIdConfig;
 
         inline MsgUpdateSvConfig(GnssAdapter& adapter,
                                  uint32_t sessionId,
-                                 const GnssSvTypeConfig& svTypeConfig,
-                                 const GnssSvIdConfig& svIdConfig) :
+                                 const GnssSvTypeConfig& constellationEnablementConfig,
+                                 const GnssSvIdConfig& blacklistSvConfig) :
             LocMsg(),
             mAdapter(adapter),
             mSessionId(sessionId),
-            mSvTypeConfig(svTypeConfig),
-            mSvIdConfig(svIdConfig) {}
+            mConstellationEnablementConfig(constellationEnablementConfig),
+            mBlacklistSvIdConfig(blacklistSvConfig) {}
         inline virtual void proc() const {
-            mAdapter.updateSvConfig(mSessionId, mSvTypeConfig, mSvIdConfig);
+            mAdapter.gnssUpdateSvConfig(mSessionId, mConstellationEnablementConfig,
+                                        mBlacklistSvIdConfig);
         }
     };
 
     if (sessionId != 0) {
-        sendMsg(new MsgUpdateSvConfig(*this, sessionId,
-                                       svTypeConfig, svIdConfig));
+        sendMsg(new MsgUpdateSvConfig(*this, sessionId, constellationEnablementConfig,
+                                      blacklistSvConfig));
     }
     return sessionId;
 }
 
-void
-GnssAdapter::resetSvConfig(uint32_t sessionId) {
+void GnssAdapter::gnssUpdateSecondaryBandConfig(
+        uint32_t sessionId, const GnssSvTypeConfig& secondaryBandConfig) {
 
-    LocApiResponse* locApiResponse = nullptr;
-    if (sessionId != 0) {
-        locApiResponse =
-                new LocApiResponse(*getContext(),
-                                   [this, sessionId] (LocationError err) {
-                                   reportResponse(err, sessionId);});
-        if (!locApiResponse) {
-            LOC_LOGe("memory alloc failed");
-        }
+    LocApiResponse* locApiResponse = new LocApiResponse(*getContext(),
+            [this, sessionId] (LocationError err) {
+            reportResponse(err, sessionId);});
+    if (!locApiResponse) {
+        LOC_LOGe("memory alloc failed");
     }
-    mLocApi->resetConstellationControl(locApiResponse);
+
+    // handle secondary band info
+    mGnssSeconaryBandConfig = secondaryBandConfig;
+    gnssSecondaryBandConfigUpdate(locApiResponse);
 }
 
-uint32_t GnssAdapter::gnssResetSvConfigCommand() {
+uint32_t
+GnssAdapter::gnssUpdateSecondaryBandConfigCommand(
+        const GnssSvTypeConfig& secondaryBandConfig) {
 
     // generated session id will be none-zero
     uint32_t sessionId = generateSessionId();
     LOC_LOGd("session id %u", sessionId);
 
-    struct MsgResetSvConfig : public LocMsg {
+    struct MsgUpdateSecondaryBandConfig : public LocMsg {
         GnssAdapter&     mAdapter;
         uint32_t         mSessionId;
+        GnssSvTypeConfig mSecondaryBandConfig;
 
-        inline MsgResetSvConfig(GnssAdapter& adapter,
-                                uint32_t sessionId) :
+        inline MsgUpdateSecondaryBandConfig(GnssAdapter& adapter,
+                                 uint32_t sessionId,
+                                 const GnssSvTypeConfig& secondaryBandConfig) :
+            LocMsg(),
+            mAdapter(adapter),
+            mSessionId(sessionId),
+            mSecondaryBandConfig(secondaryBandConfig) {}
+        inline virtual void proc() const {
+            mAdapter.gnssUpdateSecondaryBandConfig(mSessionId,  mSecondaryBandConfig);
+        }
+    };
+
+    if (sessionId != 0) {
+        sendMsg(new MsgUpdateSecondaryBandConfig(*this, sessionId, secondaryBandConfig));
+    }
+    return sessionId;
+}
+
+// This function currently retrieves secondary band configuration
+// for constellation enablement/disablement.
+void
+GnssAdapter::gnssGetSecondaryBandConfig(uint32_t sessionId) {
+
+    LocApiResponse* locApiResponse = new LocApiResponse(*getContext(),
+            [this, sessionId] (LocationError err) {
+            reportResponse(err, sessionId);});
+    if (!locApiResponse) {
+        LOC_LOGe("memory alloc failed");
+    }
+
+    mLocApi->getConstellationMultiBandConfig(sessionId, locApiResponse);
+}
+
+uint32_t
+GnssAdapter::gnssGetSecondaryBandConfigCommand() {
+
+    // generated session id will be none-zero
+    uint32_t sessionId = generateSessionId();
+    LOC_LOGd("session id %u", sessionId);
+
+    struct MsgGetSecondaryBandConfig : public LocMsg {
+        GnssAdapter& mAdapter;
+        uint32_t     mSessionId;
+        inline MsgGetSecondaryBandConfig(GnssAdapter& adapter,
+                              uint32_t sessionId) :
             LocMsg(),
             mAdapter(adapter),
             mSessionId(sessionId) {}
         inline virtual void proc() const {
-            mAdapter.resetSvConfig(mSessionId);
+            mAdapter.gnssGetSecondaryBandConfig(mSessionId);
         }
     };
 
-    sendMsg(new MsgResetSvConfig(*this, sessionId));
+    if (sessionId != 0) {
+        sendMsg(new MsgGetSecondaryBandConfig(*this, sessionId));
+    }
     return sessionId;
 }
 
@@ -5341,6 +6161,13 @@
             mSessionId(sessionId),
             mConfigInfo(configInfo) {}
         inline virtual void proc() const {
+            // save the lever ARM config info for translating position from GNSS antenna based
+            // to VRP based
+            if (mConfigInfo.leverArmValidMask & LEVER_ARM_TYPE_GNSS_TO_VRP_BIT) {
+                mAdapter.mLocConfigInfo.leverArmConfigInfo.leverArmValidMask |=
+                        LEVER_ARM_TYPE_GNSS_TO_VRP_BIT;
+                mAdapter.mLocConfigInfo.leverArmConfigInfo.gnssToVRP = mConfigInfo.gnssToVRP;
+            }
             mAdapter.configLeverArm(mSessionId, mConfigInfo);
         }
     };
@@ -5349,6 +6176,313 @@
     return sessionId;
 }
 
+bool GnssAdapter::initMeasCorr(bool bSendCbWhenNotSupported) {
+    LOC_LOGv("GnssAdapter::initMeasCorr");
+    /* Message to initialize Measurement Corrections */
+    struct MsgInitMeasCorr : public LocMsg {
+        GnssAdapter& mAdapter;
+        GnssMeasurementCorrectionsCapabilitiesMask mCapMask;
+
+        inline MsgInitMeasCorr(GnssAdapter& adapter,
+                GnssMeasurementCorrectionsCapabilitiesMask capMask) :
+            LocMsg(), mAdapter(adapter), mCapMask(capMask) {
+            LOC_LOGv("MsgInitMeasCorr");
+        }
+
+        inline virtual void proc() const {
+            LOC_LOGv("MsgInitMeasCorr::proc()");
+
+            mAdapter.mMeasCorrSetCapabilitiesCb(mCapMask);
+        }
+    };
+    if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_MEASUREMENTS_CORRECTION)) {
+        sendMsg(new MsgInitMeasCorr(*this, GNSS_MEAS_CORR_LOS_SATS |
+                GNSS_MEAS_CORR_EXCESS_PATH_LENGTH | GNSS_MEAS_CORR_REFLECTING_PLANE));
+        return true;
+    } else {
+        LOC_LOGv("MEASUREMENTS_CORRECTION feature is not supported in the modem");
+        if (bSendCbWhenNotSupported) {
+            sendMsg(new MsgInitMeasCorr(*this, 0));
+        }
+        return false;
+    }
+}
+
+bool GnssAdapter::openMeasCorrCommand(const measCorrSetCapabilitiesCb setCapabilitiesCb) {
+    LOC_LOGi("GnssAdapter::openMeasCorrCommand");
+
+    /* Send message to initialize Measurement Corrections */
+        mMeasCorrSetCapabilitiesCb = setCapabilitiesCb;
+        mIsMeasCorrInterfaceOpen = true;
+        if (isEngineCapabilitiesKnown()) {
+        LOC_LOGv("Capabilities are known, proceed with measurement corrections init");
+            return initMeasCorr(false);
+        } else {
+        LOC_LOGv("Capabilities are not known, wait for open");
+            return true;
+        }
+}
+
+bool GnssAdapter::measCorrSetCorrectionsCommand(const GnssMeasurementCorrections gnssMeasCorr) {
+    LOC_LOGi("GnssAdapter::measCorrSetCorrectionsCommand");
+
+    /* Message to set Measurement Corrections */
+    struct MsgSetCorrectionsMeasCorr : public LocMsg {
+        const GnssMeasurementCorrections mGnssMeasCorr;
+        GnssAdapter& mAdapter;
+        LocApiBase& mApi;
+
+        inline MsgSetCorrectionsMeasCorr(
+            const GnssMeasurementCorrections gnssMeasCorr,
+            GnssAdapter& adapter,
+            LocApiBase& api) :
+            LocMsg(),
+            mGnssMeasCorr(gnssMeasCorr),
+            mAdapter(adapter),
+            mApi(api) {
+            LOC_LOGv("MsgSetCorrectionsMeasCorr");
+        }
+
+        inline virtual void proc() const {
+            LOC_LOGv("MsgSetCorrectionsMeasCorr::proc()");
+            mApi.setMeasurementCorrections(mGnssMeasCorr);
+        }
+    };
+
+    if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_MEASUREMENTS_CORRECTION)) {
+        sendMsg(new MsgSetCorrectionsMeasCorr(gnssMeasCorr, *this, *mLocApi));
+        return true;
+    } else {
+        LOC_LOGw("Measurement Corrections are not supported!");
+        return false;
+    }
+}
+uint32_t GnssAdapter::antennaInfoInitCommand(const antennaInfoCb antennaInfoCallback) {
+    LOC_LOGi("GnssAdapter::antennaInfoInitCommand");
+
+    /* Message to initialize Antenna Information */
+    struct MsgInitAi : public LocMsg {
+        const antennaInfoCb mAntennaInfoCb;
+        GnssAdapter& mAdapter;
+
+        inline MsgInitAi(const antennaInfoCb antennaInfoCallback, GnssAdapter& adapter) :
+            LocMsg(), mAntennaInfoCb(antennaInfoCallback), mAdapter(adapter) {
+            LOC_LOGv("MsgInitAi");
+        }
+
+        inline virtual void proc() const {
+            LOC_LOGv("MsgInitAi::proc()");
+            mAdapter.reportGnssAntennaInformation(mAntennaInfoCb);
+        }
+    };
+    if (mIsAntennaInfoInterfaceOpened) {
+        return ANTENNA_INFO_ERROR_ALREADY_INIT;
+    } else {
+        mIsAntennaInfoInterfaceOpened = true;
+        sendMsg(new MsgInitAi(antennaInfoCallback, *this));
+        return ANTENNA_INFO_SUCCESS;
+    }
+}
+
+void
+GnssAdapter::configRobustLocation(uint32_t sessionId,
+                                  bool enable, bool enableForE911) {
+
+    mLocConfigInfo.robustLocationConfigInfo.isValid = true;
+    mLocConfigInfo.robustLocationConfigInfo.enable = enable;
+    mLocConfigInfo.robustLocationConfigInfo.enableFor911 = enableForE911;
+
+    LocApiResponse* locApiResponse = nullptr;
+    if (sessionId != 0) {
+        locApiResponse =
+                new LocApiResponse(*getContext(),
+                                   [this, sessionId] (LocationError err) {
+                                   reportResponse(err, sessionId);});
+        if (!locApiResponse) {
+            LOC_LOGe("memory alloc failed");
+        }
+    }
+    mLocApi->configRobustLocation(enable, enableForE911, locApiResponse);
+}
+
+uint32_t GnssAdapter::configRobustLocationCommand(
+        bool enable, bool enableForE911) {
+
+    // generated session id will be none-zero
+    uint32_t sessionId = generateSessionId();
+    LOC_LOGd("session id %u", sessionId);
+
+    struct MsgConfigRobustLocation : public LocMsg {
+        GnssAdapter&     mAdapter;
+        uint32_t         mSessionId;
+        bool             mEnable;
+        bool             mEnableForE911;
+
+        inline MsgConfigRobustLocation(GnssAdapter& adapter,
+                                uint32_t sessionId,
+                                bool     enable,
+                                bool     enableForE911) :
+            LocMsg(),
+            mAdapter(adapter),
+            mSessionId(sessionId),
+            mEnable(enable),
+            mEnableForE911(enableForE911) {}
+        inline virtual void proc() const {
+            mAdapter.configRobustLocation(mSessionId, mEnable, mEnableForE911);
+        }
+    };
+
+    sendMsg(new MsgConfigRobustLocation(*this, sessionId, enable, enableForE911));
+    return sessionId;
+}
+
+void
+GnssAdapter::configMinGpsWeek(uint32_t sessionId, uint16_t minGpsWeek) {
+    // suspend all sessions for modem to take the min GPS week config
+    suspendSessions();
+
+    LocApiResponse* locApiResponse = nullptr;
+    if (sessionId != 0) {
+        locApiResponse =
+                new LocApiResponse(*getContext(),
+                                   [this, sessionId] (LocationError err) {
+                                   reportResponse(err, sessionId);});
+        if (!locApiResponse) {
+            LOC_LOGe("memory alloc failed");
+        }
+    }
+    mLocApi->configMinGpsWeek(minGpsWeek, locApiResponse);
+
+    // resume all tracking sessions after the min GPS week config
+    // has been changed
+    restartSessions(false);
+}
+
+uint32_t GnssAdapter::configMinGpsWeekCommand(uint16_t minGpsWeek) {
+    // generated session id will be none-zero
+    uint32_t sessionId = generateSessionId();
+    LOC_LOGd("session id %u", sessionId);
+
+    struct MsgConfigMinGpsWeek : public LocMsg {
+        GnssAdapter&     mAdapter;
+        uint32_t         mSessionId;
+        uint16_t         mMinGpsWeek;
+
+        inline MsgConfigMinGpsWeek(GnssAdapter& adapter,
+                                   uint32_t sessionId,
+                                   uint16_t minGpsWeek) :
+            LocMsg(),
+            mAdapter(adapter),
+            mSessionId(sessionId),
+            mMinGpsWeek(minGpsWeek) {}
+        inline virtual void proc() const {
+            mAdapter.configMinGpsWeek(mSessionId, mMinGpsWeek);
+        }
+    };
+
+    sendMsg(new MsgConfigMinGpsWeek(*this, sessionId, minGpsWeek));
+    return sessionId;
+}
+
+uint32_t GnssAdapter::configDeadReckoningEngineParamsCommand(
+        const DeadReckoningEngineConfig& dreConfig) {
+
+    // generated session id will be none-zero
+    uint32_t sessionId = generateSessionId();
+    LOC_LOGd("session id %u", sessionId);
+
+    struct MsgConfigDrEngine : public LocMsg {
+        GnssAdapter& mAdapter;
+        uint32_t     mSessionId;
+        DeadReckoningEngineConfig mDreConfig;
+
+        inline MsgConfigDrEngine(GnssAdapter& adapter,
+                                  uint32_t sessionId,
+                                  const DeadReckoningEngineConfig& dreConfig) :
+            LocMsg(),
+            mAdapter(adapter),
+            mSessionId(sessionId),
+            mDreConfig(dreConfig) {}
+        inline virtual void proc() const {
+            LocationError err = LOCATION_ERROR_NOT_SUPPORTED;
+            if (true == mAdapter.mEngHubProxy->configDeadReckoningEngineParams(mDreConfig)) {
+                err = LOCATION_ERROR_SUCCESS;
+            }
+            mAdapter.reportResponse(err, mSessionId);
+        }
+    };
+
+    sendMsg(new MsgConfigDrEngine(*this, sessionId, dreConfig));
+    return sessionId;
+}
+
+uint32_t GnssAdapter::configEngineRunStateCommand(
+        PositioningEngineMask engType, LocEngineRunState engState) {
+
+    // generated session id will be none-zero
+    uint32_t sessionId = generateSessionId();
+    LOC_LOGe("session id %u, eng type 0x%x, eng state %d, dre enabled %d",
+             sessionId, engType, engState, mDreIntEnabled);
+
+    struct MsgConfigEngineRunState : public LocMsg {
+        GnssAdapter& mAdapter;
+        uint32_t     mSessionId;
+        PositioningEngineMask mEngType;
+        LocEngineRunState mEngState;
+
+        inline MsgConfigEngineRunState(GnssAdapter& adapter,
+                                       uint32_t sessionId,
+                                       PositioningEngineMask engType,
+                                       LocEngineRunState engState) :
+            LocMsg(),
+            mAdapter(adapter),
+            mSessionId(sessionId),
+            mEngType(engType),
+            mEngState(engState) {}
+        inline virtual void proc() const {
+            LocationError err = LOCATION_ERROR_NOT_SUPPORTED;
+            // Currently, only DR engine supports pause/resume request
+            if ((mEngType == DEAD_RECKONING_ENGINE) &&
+                (mAdapter.mDreIntEnabled == true)) {
+                if (true == mAdapter.mEngHubProxy->configEngineRunState(mEngType, mEngState)) {
+                    err = LOCATION_ERROR_SUCCESS;
+                }
+            }
+            mAdapter.reportResponse(err, mSessionId);
+        }
+    };
+
+    sendMsg(new MsgConfigEngineRunState(*this, sessionId, engType, engState));
+
+    return sessionId;
+}
+
+void GnssAdapter::reportGnssConfigEvent(uint32_t sessionId, const GnssConfig& gnssConfig)
+{
+    struct MsgReportGnssConfig : public LocMsg {
+        GnssAdapter& mAdapter;
+        uint32_t     mSessionId;
+        mutable GnssConfig   mGnssConfig;
+        inline MsgReportGnssConfig(GnssAdapter& adapter,
+                                   uint32_t sessionId,
+                                   const GnssConfig& gnssConfig) :
+            LocMsg(),
+            mAdapter(adapter),
+            mSessionId(sessionId),
+            mGnssConfig(gnssConfig) {}
+        inline virtual void proc() const {
+            // Invoke control clients config callback
+            if (nullptr != mAdapter.mControlCallbacks.gnssConfigCb) {
+                mAdapter.mControlCallbacks.gnssConfigCb(mSessionId, mGnssConfig);
+            } else {
+                LOC_LOGe("Failed to report, callback not registered");
+            }
+        }
+    };
+
+    sendMsg(new MsgReportGnssConfig(*this, sessionId, gnssConfig));
+}
+
 /* ==== Eng Hub Proxy ================================================================= */
 /* ======== UTILITIES ================================================================= */
 void
@@ -5397,13 +6531,23 @@
                          strlen(PROCESS_NAME_ENGINE_SERVICE)) == 0) &&
                 (processInfoList[i].proc_status == ENABLED)) {
                 pluginDaemonEnabled = true;
-                break;
+                // check if this is DRE-INT engine
+                if ((processInfoList[i].args[1]!= nullptr) &&
+                    (strncmp(processInfoList[i].args[1], "DRE-INT", sizeof("DRE-INT")) == 0)) {
+                    mDreIntEnabled = true;
+                    break;
+                }
             }
         }
 
-        // no plugin daemon is enabled for this platform, no need to load eng hub .so
+        // no plugin daemon is enabled for this platform,
+        // check if external engine is present for which we need
+        // libloc_eng_hub.so to be loaded
         if (pluginDaemonEnabled == false) {
-            break;
+            UTIL_READ_CONF(LOC_PATH_IZAT_CONF, izatConfParamTable);
+            if (!loadEngHubForExternalEngine) {
+                break;
+            }
         }
 
         // load the engine hub .so, if the .so is not present
@@ -5450,16 +6594,22 @@
 
             if (mNHzNeeded != nHzNeeded) {
                 mNHzNeeded = nHzNeeded;
-                checkAndRestartTimeBasedSession();
+                checkAndRestartSPESession();
             }
-       };
+        };
+
+        GnssAdapterUpdateQwesFeatureStatusCb updateQwesFeatureStatusCb =
+            [this] (const std::unordered_map<LocationQwesFeatureType, bool> &featureMap) {
+            reportQwesCapabilities(featureMap);
+        };
 
         getEngHubProxyFn* getter = (getEngHubProxyFn*) dlsym(handle, "getEngHubProxy");
         if(getter != nullptr) {
             EngineHubProxyBase* hubProxy = (*getter) (mMsgTask, mSystemStatus->getOsObserver(),
-                                                      reportPositionEventCb,
-                                                      reportSvEventCb, reqAidingDataCb,
-                                                      updateNHzRequirementCb);
+                      reportPositionEventCb,
+                      reportSvEventCb, reqAidingDataCb,
+                      updateNHzRequirementCb,
+                      updateQwesFeatureStatusCb);
             if (hubProxy != nullptr) {
                 mEngHubProxy = hubProxy;
                 engHubLoadSuccessful = true;
@@ -5482,3 +6632,332 @@
     firstTime = false;
     return engHubLoadSuccessful;
 }
+
+std::vector<double>
+GnssAdapter::parseDoublesString(char* dString) {
+    std::vector<double> dVector;
+    char* tmp = NULL;
+    char* substr;
+
+    dVector.clear();
+    for (substr = strtok_r(dString, " ", &tmp);
+        substr != NULL;
+        substr = strtok_r(NULL, " ", &tmp)) {
+        dVector.push_back(std::stod(substr));
+    }
+    return dVector;
+}
+
+void
+GnssAdapter::reportGnssAntennaInformation(const antennaInfoCb antennaInfoCallback)
+{
+#define MAX_TEXT_WIDTH      50
+#define MAX_COLUMN_WIDTH    20
+
+    /* parse antenna_corrections file and fill in
+    a vector of GnssAntennaInformation data structure */
+
+    std::vector<GnssAntennaInformation> gnssAntennaInformations;
+    GnssAntennaInformation gnssAntennaInfo;
+
+    uint32_t antennaInfoVectorSize;
+    loc_param_s_type ant_info_vector_table[] =
+    {
+        { "ANTENNA_INFO_VECTOR_SIZE", &antennaInfoVectorSize, NULL, 'n' }
+    };
+    UTIL_READ_CONF(LOC_PATH_ANT_CORR, ant_info_vector_table);
+
+    for (uint32_t i = 0; i < antennaInfoVectorSize; i++) {
+        double carrierFrequencyMHz;
+        char pcOffsetStr[LOC_MAX_PARAM_STRING];
+        uint32_t numberOfRows = 0;
+        uint32_t numberOfColumns = 0;
+        uint32_t numberOfRowsSGC = 0;
+        uint32_t numberOfColumnsSGC = 0;
+
+        gnssAntennaInfo.phaseCenterVariationCorrectionMillimeters.clear();
+        gnssAntennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters.clear();
+        gnssAntennaInfo.signalGainCorrectionDbi.clear();
+        gnssAntennaInfo.signalGainCorrectionUncertaintyDbi.clear();
+        string s1 = "CARRIER_FREQUENCY_";
+        s1 += to_string(i);
+        string s2 = "PC_OFFSET_";
+        s2 += to_string(i);
+        string s3 = "NUMBER_OF_ROWS_";
+        s3 += to_string(i);
+        string s4 = "NUMBER_OF_COLUMNS_";
+        s4 += to_string(i);
+        string s5 = "NUMBER_OF_ROWS_SGC_";
+        s5 += to_string(i);
+        string s6 = "NUMBER_OF_COLUMNS_SGC_";
+        s6 += to_string(i);
+
+        gnssAntennaInfo.size = sizeof(gnssAntennaInfo);
+        loc_param_s_type ant_cf_table[] =
+        {
+            { s1.c_str(), &carrierFrequencyMHz, NULL, 'f' },
+            { s2.c_str(), &pcOffsetStr, NULL, 's' },
+            { s3.c_str(), &numberOfRows, NULL, 'n' },
+            { s4.c_str(), &numberOfColumns, NULL, 'n' },
+            { s5.c_str(), &numberOfRowsSGC, NULL, 'n' },
+            { s6.c_str(), &numberOfColumnsSGC, NULL, 'n' },
+        };
+        UTIL_READ_CONF(LOC_PATH_ANT_CORR, ant_cf_table);
+
+        if (0 == numberOfRowsSGC) {
+            numberOfRowsSGC = numberOfRows;
+        }
+        if (0 == numberOfColumnsSGC) {
+            numberOfColumnsSGC = numberOfColumns;
+        }
+
+        gnssAntennaInfo.carrierFrequencyMHz = carrierFrequencyMHz;
+
+        // now parse pcOffsetStr to get each entry
+        std::vector<double> pcOffset;
+        pcOffset = parseDoublesString(pcOffsetStr);
+        gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.size =
+                sizeof(gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters);
+        gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.x = pcOffset[0];
+        gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.xUncertainty = pcOffset[1];
+        gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.y = pcOffset[2];
+        gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.yUncertainty = pcOffset[3];
+        gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.z = pcOffset[4];
+        gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.zUncertainty = pcOffset[5];
+
+        uint16_t array_size = MAX_TEXT_WIDTH + MAX_COLUMN_WIDTH*numberOfColumns;
+        uint16_t array_size_SGC = MAX_TEXT_WIDTH + MAX_COLUMN_WIDTH*numberOfColumnsSGC;
+        for (uint32_t j = 0; j < numberOfRows; j++) {
+            char pcVarCorrStr[array_size];
+            char pcVarCorrUncStr[array_size];
+
+            string s1 = "PC_VARIATION_CORRECTION_" + to_string(i) + "_ROW_";
+            s1 += to_string(j);
+            string s2 = "PC_VARIATION_CORRECTION_UNC_" + to_string(i) + "_ROW_";
+            s2 += to_string(j);
+
+            loc_param_s_type ant_row_table[] =
+            {
+                { s1.c_str(), &pcVarCorrStr, NULL, 's' },
+                { s2.c_str(), &pcVarCorrUncStr, NULL, 's' },
+            };
+            UTIL_READ_CONF_LONG(LOC_PATH_ANT_CORR, ant_row_table, array_size);
+
+            gnssAntennaInfo.phaseCenterVariationCorrectionMillimeters.push_back(
+                    parseDoublesString(pcVarCorrStr));
+            gnssAntennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters.push_back(
+                    parseDoublesString(pcVarCorrUncStr));
+        }
+        for (uint32_t j = 0; j < numberOfRowsSGC; j++) {
+            char sigGainCorrStr[array_size_SGC];
+            char sigGainCorrUncStr[array_size_SGC];
+
+            string s3 = "SIGNAL_GAIN_CORRECTION_" + to_string(i) + "_ROW_";
+            s3 += to_string(j);
+            string s4 = "SIGNAL_GAIN_CORRECTION_UNC_" + to_string(i) + "_ROW_";
+            s4 += to_string(j);
+
+            loc_param_s_type ant_row_table[] =
+            {
+                { s3.c_str(), &sigGainCorrStr, NULL, 's' },
+                { s4.c_str(), &sigGainCorrUncStr, NULL, 's' },
+            };
+            UTIL_READ_CONF_LONG(LOC_PATH_ANT_CORR, ant_row_table, array_size_SGC);
+
+            gnssAntennaInfo.signalGainCorrectionDbi.push_back(
+                    parseDoublesString(sigGainCorrStr));
+            gnssAntennaInfo.signalGainCorrectionUncertaintyDbi.push_back(
+                    parseDoublesString(sigGainCorrUncStr));
+        }
+        gnssAntennaInformations.push_back(std::move(gnssAntennaInfo));
+    }
+    if (antennaInfoVectorSize > 0) {
+        antennaInfoCallback(gnssAntennaInformations);
+    }
+}
+
+/* ==== DGnss Usable Reporter ========================================================= */
+/* ======== UTILITIES ================================================================= */
+
+void GnssAdapter::initCDFWService()
+{
+    LOC_LOGv("mCdfwInterface %p", mCdfwInterface);
+    if (nullptr == mCdfwInterface) {
+        void* libHandle = nullptr;
+        const char* libName = "libcdfw.so";
+
+        libHandle = nullptr;
+        getCdfwInterface getter  = (getCdfwInterface)dlGetSymFromLib(libHandle,
+                          libName, "getQCdfwInterface");
+        if (nullptr == getter) {
+            LOC_LOGe("dlGetSymFromLib getQCdfwInterface failed");
+        } else {
+            mCdfwInterface = getter();
+        }
+
+        if (nullptr != mCdfwInterface) {
+            QDgnssSessionActiveCb qDgnssSessionActiveCb = [this] (bool sessionActive) {
+                mDGnssNeedReport = sessionActive;
+            };
+            mCdfwInterface->startDgnssApiService(*mMsgTask);
+            mQDgnssListenerHDL = mCdfwInterface->createUsableReporter(qDgnssSessionActiveCb);
+        }
+    }
+}
+
+/*==== DGnss Ntrip Source ==========================================================*/
+void GnssAdapter::enablePPENtripStreamCommand(const GnssNtripConnectionParams& params,
+                                              bool enableRTKEngine) {
+
+    (void)enableRTKEngine; //future parameter, not used
+    if (0 == params.size || params.hostNameOrIp.empty() || params.mountPoint.empty() ||
+            params.username.empty() || params.password.empty()) {
+        LOC_LOGe("Ntrip parameters are invalid!");
+        return;
+    }
+
+    struct enableNtripMsg : public LocMsg {
+        GnssAdapter& mAdapter;
+        const GnssNtripConnectionParams mParams;
+
+        inline enableNtripMsg(GnssAdapter& adapter,
+                const GnssNtripConnectionParams& params) :
+            LocMsg(),
+            mAdapter(adapter),
+            mParams(std::move(params)) {}
+        inline virtual void proc() const {
+            mAdapter.handleEnablePPENtrip(mParams);
+        }
+    };
+    sendMsg(new enableNtripMsg(*this, params));
+}
+
+void GnssAdapter::handleEnablePPENtrip(const GnssNtripConnectionParams& params) {
+    LOC_LOGd("%d %s %d %s %s %s %d mSendNmeaConsent %d",
+             params.useSSL, params.hostNameOrIp.data(), params.port,
+             params.mountPoint.data(), params.username.data(), params.password.data(),
+             params.requiresNmeaLocation, mSendNmeaConsent);
+
+    GnssNtripConnectionParams* pNtripParams = &(mStartDgnssNtripParams.ntripParams);
+
+    if (pNtripParams->useSSL == params.useSSL &&
+            0 == pNtripParams->hostNameOrIp.compare(params.hostNameOrIp) &&
+            pNtripParams->port == params.port &&
+            0 == pNtripParams->mountPoint.compare(params.mountPoint) &&
+            0 == pNtripParams->username.compare(params.username) &&
+            0 == pNtripParams->password.compare(params.password) &&
+            pNtripParams->requiresNmeaLocation == params.requiresNmeaLocation &&
+            mDgnssState & DGNSS_STATE_ENABLE_NTRIP_COMMAND) {
+        LOC_LOGd("received same Ntrip param");
+        return;
+    }
+
+    mDgnssState |= DGNSS_STATE_ENABLE_NTRIP_COMMAND;
+    mDgnssState |= DGNSS_STATE_NO_NMEA_PENDING;
+    mDgnssState &= ~DGNSS_STATE_NTRIP_SESSION_STARTED;
+
+    mStartDgnssNtripParams.ntripParams = std::move(params);
+    mStartDgnssNtripParams.nmea.clear();
+    if (mSendNmeaConsent && pNtripParams->requiresNmeaLocation) {
+        mDgnssState &= ~DGNSS_STATE_NO_NMEA_PENDING;
+        mDgnssLastNmeaBootTimeMilli = 0;
+        return;
+    }
+
+    checkUpdateDgnssNtrip(false);
+}
+
+void GnssAdapter::disablePPENtripStreamCommand() {
+    struct disableNtripMsg : public LocMsg {
+        GnssAdapter& mAdapter;
+
+        inline disableNtripMsg(GnssAdapter& adapter) :
+            LocMsg(),
+            mAdapter(adapter) {}
+        inline virtual void proc() const {
+            mAdapter.handleDisablePPENtrip();
+        }
+    };
+    sendMsg(new disableNtripMsg(*this));
+}
+
+void GnssAdapter::handleDisablePPENtrip() {
+    mDgnssState &= ~DGNSS_STATE_ENABLE_NTRIP_COMMAND;
+    mDgnssState |= DGNSS_STATE_NO_NMEA_PENDING;
+    stopDgnssNtrip();
+}
+
+void GnssAdapter::checkUpdateDgnssNtrip(bool isLocationValid) {
+    LOC_LOGd("isInSession %d mDgnssState 0x%x isLocationValid %d",
+            isInSession(), mDgnssState, isLocationValid);
+    if (isInSession()) {
+        uint64_t curBootTime = getBootTimeMilliSec();
+        if (mDgnssState == (DGNSS_STATE_ENABLE_NTRIP_COMMAND | DGNSS_STATE_NO_NMEA_PENDING)) {
+            mDgnssState |= DGNSS_STATE_NTRIP_SESSION_STARTED;
+            mXtraObserver.startDgnssSource(mStartDgnssNtripParams);
+            if (isDgnssNmeaRequired()) {
+                mDgnssLastNmeaBootTimeMilli = curBootTime;
+            }
+        } else if ((mDgnssState & DGNSS_STATE_NTRIP_SESSION_STARTED) && isLocationValid &&
+            isDgnssNmeaRequired() &&
+            curBootTime - mDgnssLastNmeaBootTimeMilli > DGNSS_RANGE_UPDATE_TIME_10MIN_IN_MILLI ) {
+            mXtraObserver.updateNmeaToDgnssServer(mStartDgnssNtripParams.nmea);
+            mDgnssLastNmeaBootTimeMilli = curBootTime;
+        }
+    }
+}
+
+void GnssAdapter::stopDgnssNtrip() {
+    LOC_LOGd("isInSession %d mDgnssState 0x%x", isInSession(), mDgnssState);
+    mStartDgnssNtripParams.nmea.clear();
+    if (mDgnssState & DGNSS_STATE_NTRIP_SESSION_STARTED) {
+        mDgnssState &= ~DGNSS_STATE_NTRIP_SESSION_STARTED;
+        mXtraObserver.stopDgnssSource();
+    }
+}
+
+void GnssAdapter::reportGGAToNtrip(const char* nmea) {
+
+#define POS_OF_GGA (3)  //start position of "GGA"
+#define COMMAS_BEFORE_VALID (6) //"$GPGGA,,,,,,0,,,,,,,,*hh"
+
+    if (!isDgnssNmeaRequired()) {
+        return;
+    }
+
+    if (nullptr == nmea || 0 == strlen(nmea)) {
+        return;
+    }
+
+    string nmeaString(nmea);
+    size_t foundPos = nmeaString.find("GGA");
+    size_t foundNth = 0;
+    string GGAString;
+
+    if (foundPos != string::npos && foundPos >= POS_OF_GGA) {
+        size_t foundNextSentence = nmeaString.find("$", foundPos);
+        if (foundNextSentence != string::npos) {
+            /* remove other sentences after GGA */
+            GGAString = nmeaString.substr(foundPos - POS_OF_GGA, foundNextSentence);
+        } else {
+            /* GGA is the last sentence */
+            GGAString = nmeaString.substr(foundPos - POS_OF_GGA);
+        }
+        LOC_LOGd("GGAString %s", GGAString.c_str());
+
+        foundPos = GGAString.find(",");
+        while (foundPos != string::npos && foundNth < COMMAS_BEFORE_VALID) {
+            foundPos++;
+            foundNth++;
+            foundPos = GGAString.find(",", foundPos);
+        }
+
+        if (COMMAS_BEFORE_VALID == foundNth && GGAString.at(foundPos-1) != '0') {
+            mDgnssState |= DGNSS_STATE_NO_NMEA_PENDING;
+            mStartDgnssNtripParams.nmea = std::move(GGAString);
+            checkUpdateDgnssNtrip(true);
+        }
+    }
+
+    return;
+}
diff --git a/gnss/GnssAdapter.h b/gnss/GnssAdapter.h
index 136c5c0..d7b4275 100644
--- a/gnss/GnssAdapter.h
+++ b/gnss/GnssAdapter.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -38,6 +38,10 @@
 #include <SystemStatus.h>
 #include <XtraSystemStatusObserver.h>
 #include <map>
+#include <functional>
+#include <loc_misc_utils.h>
+#include <queue>
+#include <NativeAgpsHandler.h>
 
 #define MAX_URL_LEN 256
 #define NMEA_SENTENCE_MAX_LENGTH 200
@@ -46,6 +50,7 @@
 #define LOC_NI_NO_RESPONSE_TIME 20
 #define LOC_GPS_NI_RESPONSE_IGNORE 4
 #define ODCPI_EXPECTED_INJECTION_TIME_MS 10000
+#define DELETE_AIDING_DATA_EXPECTED_TIME_MS 5000
 
 class GnssAdapter;
 
@@ -135,8 +140,16 @@
 } PaceConfigInfo;
 
 typedef struct {
+    bool isValid;
+    bool enable;
+    bool enableFor911;
+} RobustLocationConfigInfo;
+
+typedef struct {
     TuncConfigInfo tuncConfigInfo;
     PaceConfigInfo paceConfigInfo;
+    RobustLocationConfigInfo robustLocationConfigInfo;
+    LeverArmConfigInfo  leverArmConfigInfo;
 } LocIntegrationConfigInfo;
 
 using namespace loc_core;
@@ -149,7 +162,40 @@
     uint64_t gnssEnergyConsumedFromFirstBoot
 )> GnssEnergyConsumedCallback;
 
-typedef void (*powerStateCallback)(bool on);
+typedef void* QDgnssListenerHDL;
+typedef std::function<void(
+    bool    sessionActive
+)> QDgnssSessionActiveCb;
+
+struct CdfwInterface {
+    void (*startDgnssApiService)(const MsgTask& msgTask);
+    QDgnssListenerHDL (*createUsableReporter)(
+            QDgnssSessionActiveCb sessionActiveCb);
+    void (*destroyUsableReporter)(QDgnssListenerHDL handle);
+    void (*reportUsable)(QDgnssListenerHDL handle, bool usable);
+};
+
+typedef uint16_t  DGnssStateBitMask;
+#define DGNSS_STATE_ENABLE_NTRIP_COMMAND      0X01
+#define DGNSS_STATE_NO_NMEA_PENDING           0X02
+#define DGNSS_STATE_NTRIP_SESSION_STARTED     0X04
+
+class GnssReportLoggerUtil {
+public:
+    typedef void (*LogGnssLatency)(const GnssLatencyInfo& gnssLatencyMeasInfo);
+
+    GnssReportLoggerUtil() : mLogLatency(nullptr) {
+        const char* libname = "liblocdiagiface.so";
+        void* libHandle = nullptr;
+        mLogLatency = (LogGnssLatency)dlGetSymFromLib(libHandle, libname, "LogGnssLatency");
+    }
+
+    bool isLogEnabled();
+    void log(const GnssLatencyInfo& gnssLatencyMeasInfo);
+
+private:
+    LogGnssLatency mLogLatency;
+};
 
 class GnssAdapter : public LocAdapterBase {
 
@@ -171,7 +217,9 @@
     LocationControlCallbacks mControlCallbacks;
     uint32_t mAfwControlId;
     uint32_t mNmeaMask;
+    uint64_t mPrevNmeaRptTimeNsec;
     GnssSvIdConfig mGnssSvIdConfig;
+    GnssSvTypeConfig mGnssSeconaryBandConfig;
     GnssSvTypeConfig mGnssSvTypeConfig;
     GnssSvTypeConfigCallback mGnssSvTypeConfigCb;
     bool mSupportNfwControl;
@@ -193,13 +241,30 @@
         mIsE911Session = (IsInEmergencySession)cbInfo.isInEmergencySession;
     }
 
+    /* ==== Measurement Corrections========================================================= */
+    bool mIsMeasCorrInterfaceOpen;
+    measCorrSetCapabilitiesCb mMeasCorrSetCapabilitiesCb;
+    bool initMeasCorr(bool bSendCbWhenNotSupported);
+    bool mIsAntennaInfoInterfaceOpened;
+
+    /* ==== DGNSS Data Usable Report======================================================== */
+    QDgnssListenerHDL mQDgnssListenerHDL;
+    const CdfwInterface* mCdfwInterface;
+    bool mDGnssNeedReport;
+    bool mDGnssDataUsage;
+    void reportDGnssDataUsable(const GnssSvMeasurementSet &svMeasurementSet);
+
     /* ==== ODCPI ========================================================================== */
     OdcpiRequestCallback mOdcpiRequestCb;
     bool mOdcpiRequestActive;
+    OdcpiPrioritytype mCallbackPriority;
     OdcpiTimer mOdcpiTimer;
     OdcpiRequestInfo mOdcpiRequest;
     void odcpiTimerExpire();
 
+    /* ==== DELETEAIDINGDATA =============================================================== */
+    int64_t mLastDeleteAidingDataTime;
+
     /* === SystemStatus ===================================================================== */
     SystemStatus* mSystemStatus;
     std::string mServerUrl;
@@ -213,34 +278,49 @@
     BlockCPIInfo mBlockCPIInfo;
     bool mPowerOn;
     uint32_t mAllowFlpNetworkFixes;
+    std::queue<GnssLatencyInfo> mGnssLatencyInfoQueue;
+    GnssReportLoggerUtil mLogger;
+    bool mDreIntEnabled;
+
+    /* === NativeAgpsHandler ======================================================== */
+    NativeAgpsHandler mNativeAgpsHandler;
 
     /* === Misc callback from QMI LOC API ============================================== */
     GnssEnergyConsumedCallback mGnssEnergyConsumedCb;
-    powerStateCallback mPowerStateCb;
+    std::function<void(bool)> mPowerStateCb;
 
     /*==== CONVERSION ===================================================================*/
     static void convertOptions(LocPosMode& out, const TrackingOptions& trackingOptions);
     static void convertLocation(Location& out, const UlpLocation& ulpLocation,
-                                const GpsLocationExtended& locationExtended,
-                                const LocPosTechMask techMask);
+                                const GpsLocationExtended& locationExtended);
     static void convertLocationInfo(GnssLocationInfoNotification& out,
-                                    const GpsLocationExtended& locationExtended);
+                                    const GpsLocationExtended& locationExtended,
+                                    loc_sess_status status);
     static uint16_t getNumSvUsed(uint64_t svUsedIdsMask,
                                  int totalSvCntInThisConstellation);
 
     /* ======== UTILITIES ================================================================== */
-    inline void initOdcpi(const OdcpiRequestCallback& callback);
+    inline void initOdcpi(const OdcpiRequestCallback& callback, OdcpiPrioritytype priority);
     inline void injectOdcpi(const Location& location);
     static bool isFlpClient(LocationCallbacks& locationCallbacks);
 
+    /*==== DGnss Ntrip Source ==========================================================*/
+    StartDgnssNtripParams   mStartDgnssNtripParams;
+    bool    mSendNmeaConsent;
+    DGnssStateBitMask   mDgnssState;
+    void checkUpdateDgnssNtrip(bool isLocationValid);
+    void stopDgnssNtrip();
+    uint64_t   mDgnssLastNmeaBootTimeMilli;
+
 protected:
 
     /* ==== CLIENT ========================================================================= */
     virtual void updateClientsEventMask();
     virtual void stopClientSessions(LocationAPI* client);
+    inline void setNmeaReportRateConfig();
+    void logLatencyInfo();
 
 public:
-
     GnssAdapter();
     virtual inline ~GnssAdapter() { }
 
@@ -248,8 +328,10 @@
     /* ======== EVENTS ====(Called from QMI Thread)========================================= */
     virtual void handleEngineUpEvent();
     /* ======== UTILITIES ================================================================== */
-    void restartSessions();
+    void restartSessions(bool modemSSR = false);
     void checkAndRestartTimeBasedSession();
+    void checkAndRestartSPESession();
+    void suspendSessions();
 
     /* ==== CLIENT ========================================================================= */
     /* ======== COMMANDS ====(Called from Client Thread)==================================== */
@@ -291,10 +373,17 @@
     void setConstrainedTunc(bool enable, float tuncConstraint,
                             uint32_t energyBudget, uint32_t sessionId);
     void setPositionAssistedClockEstimator(bool enable, uint32_t sessionId);
-    void updateSvConfig(uint32_t sessionId, const GnssSvTypeConfig& svTypeConfig,
-                        const GnssSvIdConfig& svIdConfig);
+    void gnssUpdateSvConfig(uint32_t sessionId,
+                        const GnssSvTypeConfig& constellationEnablementConfig,
+                        const GnssSvIdConfig& blacklistSvConfig);
+
+    void gnssUpdateSecondaryBandConfig(
+        uint32_t sessionId, const GnssSvTypeConfig& secondaryBandConfig);
+    void gnssGetSecondaryBandConfig(uint32_t sessionId);
     void resetSvConfig(uint32_t sessionId);
     void configLeverArm(uint32_t sessionId, const LeverArmConfigInfo& configInfo);
+    void configRobustLocation(uint32_t sessionId, bool enable, bool enableForE911);
+    void configMinGpsWeek(uint32_t sessionId, uint16_t minGpsWeek);
 
     /* ==== NI ============================================================================= */
     /* ======== COMMANDS ====(Called from Client Thread)==================================== */
@@ -313,12 +402,14 @@
     void readConfigCommand();
     void requestUlpCommand();
     void initEngHubProxyCommand();
-    uint32_t* gnssUpdateConfigCommand(GnssConfig config);
+    uint32_t* gnssUpdateConfigCommand(const GnssConfig& config);
     uint32_t* gnssGetConfigCommand(GnssConfigFlagsMask mask);
     uint32_t gnssDeleteAidingDataCommand(GnssAidingData& data);
     void deleteAidingData(const GnssAidingData &data, uint32_t sessionId);
     void gnssUpdateXtraThrottleCommand(const bool enabled);
     std::vector<LocationError> gnssUpdateConfig(const std::string& oldMoServerUrl,
+            const std::string& moServerUrl,
+            const std::string& serverUrl,
             GnssConfig& gnssConfigRequested,
             GnssConfig& gnssConfigNeedEngineUpdate, size_t count = 0);
 
@@ -343,6 +434,7 @@
     inline GnssSvTypeConfigCallback gnssGetSvTypeConfigCallback()
     { return mGnssSvTypeConfigCb; }
     void setConfig();
+    void gnssSecondaryBandConfigUpdate(LocApiResponse* locApiResponse= nullptr);
 
     /* ========= AGPS ====================================================================== */
     /* ======== COMMANDS ====(Called from Client Thread)==================================== */
@@ -358,14 +450,26 @@
     uint32_t setConstrainedTuncCommand (bool enable, float tuncConstraint,
                                         uint32_t energyBudget);
     uint32_t setPositionAssistedClockEstimatorCommand (bool enable);
-    uint32_t gnssUpdateSvConfigCommand(const GnssSvTypeConfig& svTypeConfig,
-                                       const GnssSvIdConfig& svIdConfig);
-    uint32_t gnssResetSvConfigCommand();
+    uint32_t gnssUpdateSvConfigCommand(const GnssSvTypeConfig& constellationEnablementConfig,
+                                       const GnssSvIdConfig& blacklistSvConfig);
+    uint32_t gnssUpdateSecondaryBandConfigCommand(
+                                       const GnssSvTypeConfig& secondaryBandConfig);
+    uint32_t gnssGetSecondaryBandConfigCommand();
     uint32_t configLeverArmCommand(const LeverArmConfigInfo& configInfo);
+    uint32_t configRobustLocationCommand(bool enable, bool enableForE911);
+    bool openMeasCorrCommand(const measCorrSetCapabilitiesCb setCapabilitiesCb);
+    bool measCorrSetCorrectionsCommand(const GnssMeasurementCorrections gnssMeasCorr);
+    inline void closeMeasCorrCommand() { mIsMeasCorrInterfaceOpen = false; }
+    uint32_t antennaInfoInitCommand(const antennaInfoCb antennaInfoCallback);
+    inline void antennaInfoCloseCommand() { mIsAntennaInfoInterfaceOpened = false; }
+    uint32_t configMinGpsWeekCommand(uint16_t minGpsWeek);
+    uint32_t configDeadReckoningEngineParamsCommand(const DeadReckoningEngineConfig& dreConfig);
+    uint32_t configEngineRunStateCommand(PositioningEngineMask engType,
+                                         LocEngineRunState engState);
 
     /* ========= ODCPI ===================================================================== */
     /* ======== COMMANDS ====(Called from Client Thread)==================================== */
-    void initOdcpiCommand(const OdcpiRequestCallback& callback);
+    void initOdcpiCommand(const OdcpiRequestCallback& callback, OdcpiPrioritytype priority);
     void injectOdcpiCommand(const Location& location);
     /* ======== RESPONSES ================================================================== */
     void reportResponse(LocationError err, uint32_t sessionId);
@@ -379,6 +483,7 @@
     virtual bool isInSession() { return !mTimeBasedTrackingSessions.empty(); }
     void initDefaultAgps();
     bool initEngHubProxy();
+    void initCDFWService();
     void odcpiTimerExpireEvent();
 
     /* ==== REPORTS ======================================================================== */
@@ -404,6 +509,7 @@
     virtual void reportSvEphemerisEvent(GnssSvEphemerisReport & svEphemeris);
     virtual void reportGnssSvIdConfigEvent(const GnssSvIdConfig& config);
     virtual void reportGnssSvTypeConfigEvent(const GnssSvTypeConfig& config);
+    virtual void reportGnssConfigEvent(uint32_t sessionId, const GnssConfig& gnssConfig);
     virtual bool reportGnssEngEnergyConsumedEvent(uint64_t energyConsumedSinceFirstBoot);
     virtual void reportLocationSystemInfoEvent(const LocationSystemInfo& locationSystemInfo);
 
@@ -415,11 +521,20 @@
     virtual bool reportGnssAdditionalSystemInfoEvent(
             GnssAdditionalSystemInfo& additionalSystemInfo);
     virtual void reportNfwNotificationEvent(GnssNfwNotification& notification);
+    virtual void reportLatencyInfoEvent(const GnssLatencyInfo& gnssLatencyInfo);
+    virtual bool reportQwesCapabilities
+    (
+        const std::unordered_map<LocationQwesFeatureType, bool> &featureMap
+    );
+    void reportPdnTypeFromWds(int pdnType, AGpsExtType agpsType, std::string apnName,
+            AGpsBearerType bearerType);
 
     /* ======== UTILITIES ================================================================= */
     bool needReportForGnssClient(const UlpLocation& ulpLocation,
             enum loc_sess_status status, LocPosTechMask techMask);
     bool needReportForFlpClient(enum loc_sess_status status, LocPosTechMask techMask);
+    bool needToGenerateNmeaReport(const uint32_t &gpsTimeOfWeekMs,
+        const struct timespec32_t &apTimeStamp);
     void reportPosition(const UlpLocation &ulpLocation,
                         const GpsLocationExtended &locationExtended,
                         enum loc_sess_status status,
@@ -434,6 +549,7 @@
     void reportGnssMeasurementData(const GnssMeasurementsNotification& measurements);
     void reportGnssSvIdConfig(const GnssSvIdConfig& config);
     void reportGnssSvTypeConfig(const GnssSvTypeConfig& config);
+    void reportGnssConfig(uint32_t sessionId, const GnssConfig& gnssConfig);
     void requestOdcpi(const OdcpiRequestInfo& request);
     void invokeGnssEnergyConsumedCallback(uint64_t energyConsumedSinceFirstBoot);
     void saveGnssEnergyConsumedCallback(GnssEnergyConsumedCallback energyConsumedCb);
@@ -451,6 +567,11 @@
     }
 
     void updateSystemPowerState(PowerStateType systemPowerState);
+    void reportSvPolynomial(const GnssSvPolynomial &svPolynomial);
+
+
+    std::vector<double> parseDoublesString(char* dString);
+    void reportGnssAntennaInformation(const antennaInfoCb antennaInfoCallback);
 
     /*======== GNSSDEBUG ================================================================*/
     bool getDebugReport(GnssDebugReport& report);
@@ -466,7 +587,6 @@
 
     /*==== CONVERSION ===================================================================*/
     static uint32_t convertSuplVersion(const GnssConfigSuplVersion suplVersion);
-    static uint32_t convertLppProfile(const GnssConfigLppProfile lppProfile);
     static uint32_t convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl);
     static uint32_t convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices);
     static uint32_t convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask);
@@ -479,10 +599,12 @@
     static bool convertToGnssSvIdConfig(
             const std::vector<GnssSvIdSource>& blacklistedSvIds, GnssSvIdConfig& config);
     static void convertFromGnssSvIdConfig(
-            const GnssSvIdConfig& svConfig, GnssConfig& config);
+            const GnssSvIdConfig& svConfig, std::vector<GnssSvIdSource>& blacklistedSvIds);
     static void convertGnssSvIdMaskToList(
             uint64_t svIdMask, std::vector<GnssSvIdSource>& svIds,
             GnssSvId initialSvId, GnssSvType svType);
+    static void computeVRPBasedLla(const UlpLocation& loc, GpsLocationExtended& locExt,
+                                   const LeverArmConfigInfo& leverArmConfigInfo);
 
     void injectLocationCommand(double latitude, double longitude, float accuracy);
     void injectLocationExtCommand(const GnssLocationInfoNotification &locationInfo);
@@ -493,10 +615,11 @@
 
     /* ==== MISCELLANEOUS ================================================================== */
     /* ======== COMMANDS ====(Called from Client Thread)==================================== */
-    void getPowerStateChangesCommand(void* powerStateCb);
+    void getPowerStateChangesCommand(std::function<void(bool)> powerStateCb);
     /* ======== UTILITIES ================================================================== */
     void reportPowerStateIfChanged();
-    void savePowerStateCallback(powerStateCallback powerStateCb){ mPowerStateCb = powerStateCb; }
+    void savePowerStateCallback(std::function<void(bool)> powerStateCb){
+            mPowerStateCb = powerStateCb; }
     bool getPowerState() { return mPowerOn; }
     inline PowerStateType getSystemPowerState() { return mSystemPowerState; }
 
@@ -505,7 +628,24 @@
     void setSuplHostServer(const char* server, int port, LocServerType type);
     void notifyClientOfCachedLocationSystemInfo(LocationAPI* client,
                                                 const LocationCallbacks& callbacks);
+    LocationCapabilitiesMask getCapabilities();
     void updateSystemPowerStateCommand(PowerStateType systemPowerState);
+
+    /*==== DGnss Usable Report Flag ====================================================*/
+    inline void setDGnssUsableFLag(bool dGnssNeedReport) { mDGnssNeedReport = dGnssNeedReport;}
+    inline bool isNMEAPrintEnabled() {
+       return ((mContext != NULL) && (0 != mContext->mGps_conf.ENABLE_NMEA_PRINT));
+    }
+
+    /*==== DGnss Ntrip Source ==========================================================*/
+    void updateNTRIPGGAConsentCommand(bool consentAccepted) { mSendNmeaConsent = consentAccepted; }
+    void enablePPENtripStreamCommand(const GnssNtripConnectionParams& params, bool enableRTKEngine);
+    void disablePPENtripStreamCommand();
+    void handleEnablePPENtrip(const GnssNtripConnectionParams& params);
+    void handleDisablePPENtrip();
+    void reportGGAToNtrip(const char* nmea);
+    inline bool isDgnssNmeaRequired() { return mSendNmeaConsent &&
+            mStartDgnssNtripParams.ntripParams.requiresNmeaLocation;}
 };
 
 #endif //GNSS_ADAPTER_H
diff --git a/gnss/Makefile.am b/gnss/Makefile.am
index db20c15..dd313a1 100644
--- a/gnss/Makefile.am
+++ b/gnss/Makefile.am
@@ -13,7 +13,8 @@
     location_gnss.cpp \
     GnssAdapter.cpp \
     XtraSystemStatusObserver.cpp \
-    Agps.cpp
+    Agps.cpp \
+    NativeAgpsHandler.cpp
 
 if USE_GLIB
 libgnss_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@
diff --git a/gnss/NativeAgpsHandler.cpp b/gnss/NativeAgpsHandler.cpp
new file mode 100644
index 0000000..ce4c03a
--- /dev/null
+++ b/gnss/NativeAgpsHandler.cpp
@@ -0,0 +1,127 @@
+/* Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation, nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#define LOG_TAG "LocSvc_NativeAgpsHandler"
+
+#include <LocAdapterBase.h>
+#include <SystemStatus.h>
+#include <DataItemId.h>
+#include <DataItemsFactoryProxy.h>
+#include <DataItemConcreteTypesBase.h>
+#include <loc_log.h>
+#include <NativeAgpsHandler.h>
+#include <GnssAdapter.h>
+
+using namespace loc_core;
+
+// IDataItemObserver overrides
+void NativeAgpsHandler::getName(string& name) {
+    name = "NativeAgpsHandler";
+}
+
+void NativeAgpsHandler::notify(const list<IDataItemCore*>& dlist) {
+    for (auto each : dlist) {
+        switch (each->getId()) {
+            case NETWORKINFO_DATA_ITEM_ID: {
+                    NetworkInfoDataItemBase* networkInfo =
+                        static_cast<NetworkInfoDataItemBase*>(each);
+                    uint64_t mobileBit = (uint64_t )1 << loc_core::TYPE_MOBILE;
+                    uint64_t allTypes = networkInfo->mAllTypes;
+                    mConnected = ((networkInfo->mAllTypes & mobileBit) == mobileBit);
+                    /**
+                     * mApn Telephony preferred Access Point Name to use for
+                     * carrier data connection when connected to a cellular network.
+                     * Empty string, otherwise.
+                     */
+                    mApn = networkInfo->mApn;
+                    LOC_LOGd("updated mConnected:%d, mApn: %s", mConnected, mApn.c_str());
+                    break;
+            }
+            default:
+                    break;
+        }
+    }
+}
+
+NativeAgpsHandler* NativeAgpsHandler::sLocalHandle = nullptr;
+NativeAgpsHandler::NativeAgpsHandler(IOsObserver* sysStatObs, GnssAdapter& adapter) :
+        mSystemStatusObsrvr(sysStatObs), mConnected(false), mAdapter(adapter) {
+    sLocalHandle = this;
+    list<DataItemId> subItemIdList = {NETWORKINFO_DATA_ITEM_ID};
+    mSystemStatusObsrvr->subscribe(subItemIdList, this);
+}
+
+NativeAgpsHandler::~NativeAgpsHandler() {
+    if (nullptr != mSystemStatusObsrvr) {
+        LOC_LOGd("Unsubscribe for network info.");
+        list<DataItemId> subItemIdList = {NETWORKINFO_DATA_ITEM_ID};
+        mSystemStatusObsrvr->unsubscribe(subItemIdList, this);
+    }
+    sLocalHandle = nullptr;
+    mSystemStatusObsrvr = nullptr;
+}
+
+
+AgpsCbInfo NativeAgpsHandler::getAgpsCbInfo() {
+    AgpsCbInfo nativeCbInfo = {};
+    nativeCbInfo.statusV4Cb = (void*)agnssStatusIpV4Cb;
+    nativeCbInfo.atlType = AGPS_ATL_TYPE_WWAN;
+    return nativeCbInfo;
+}
+
+void NativeAgpsHandler::agnssStatusIpV4Cb(AGnssExtStatusIpV4 statusInfo) {
+    if (nullptr != sLocalHandle) {
+        sLocalHandle->processATLRequestRelease(statusInfo);
+    } else {
+        LOC_LOGe("sLocalHandle is null");
+    }
+}
+
+void NativeAgpsHandler::processATLRequestRelease(AGnssExtStatusIpV4 statusInfo) {
+    if (LOC_AGPS_TYPE_WWAN_ANY == statusInfo.type) {
+        LOC_LOGd("status.type = %d status.apnTypeMask = 0x%X", statusInfo.type,
+                 statusInfo.apnTypeMask);
+        switch (statusInfo.status) {
+        case LOC_GPS_REQUEST_AGPS_DATA_CONN:
+            if (mConnected) {
+                mAdapter.dataConnOpenCommand(LOC_AGPS_TYPE_WWAN_ANY, mApn.c_str(), mApn.size(),
+                    AGPS_APN_BEARER_IPV4);
+            } else {
+                mAdapter.dataConnFailedCommand(LOC_AGPS_TYPE_WWAN_ANY);
+            }
+            break;
+        case LOC_GPS_RELEASE_AGPS_DATA_CONN:
+            mAdapter.dataConnClosedCommand(LOC_AGPS_TYPE_WWAN_ANY);
+            break;
+        default:
+            LOC_LOGe("Invalid Request: %d", statusInfo.status);
+        }
+    } else {
+        LOC_LOGe("mAgpsManger is null or invalid request type!");
+    }
+}
diff --git a/gnss/NativeAgpsHandler.h b/gnss/NativeAgpsHandler.h
new file mode 100644
index 0000000..fb0b46c
--- /dev/null
+++ b/gnss/NativeAgpsHandler.h
@@ -0,0 +1,64 @@
+/* Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation, nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef NATIVEAGPSHANDLER_H
+#define NATIVEAGPSHANDLER_H
+
+#include <cinttypes>
+#include <string.h>
+#include <gps_extended_c.h>
+#include <IDataItemObserver.h>
+#include <IDataItemCore.h>
+#include <IOsObserver.h>
+
+using namespace std;
+using loc_core::IOsObserver;
+using loc_core::IDataItemObserver;
+using loc_core::IDataItemCore;
+
+class GnssAdapter;
+
+class NativeAgpsHandler : public IDataItemObserver {
+public:
+    NativeAgpsHandler(IOsObserver* sysStatObs, GnssAdapter& adapter);
+    ~NativeAgpsHandler();
+    AgpsCbInfo getAgpsCbInfo();
+    // IDataItemObserver overrides
+    virtual void notify(const list<IDataItemCore*>& dlist);
+    inline virtual void getName(string& name);
+private:
+    static NativeAgpsHandler* sLocalHandle;
+    static void agnssStatusIpV4Cb(AGnssExtStatusIpV4 statusInfo);
+    void processATLRequestRelease(AGnssExtStatusIpV4 statusInfo);
+    IOsObserver* mSystemStatusObsrvr;
+    bool mConnected;
+    string mApn;
+    GnssAdapter& mAdapter;
+};
+
+#endif // NATIVEAGPSHANDLER_H
diff --git a/gnss/XtraSystemStatusObserver.cpp b/gnss/XtraSystemStatusObserver.cpp
index a58f735..d65622f 100644
--- a/gnss/XtraSystemStatusObserver.cpp
+++ b/gnss/XtraSystemStatusObserver.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, 2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -72,9 +72,13 @@
             LOC_LOGd("ping received");
 #ifdef USE_GLIB
         } else if (!STRNCMP(data, "connectBackhaul")) {
-            mSystemStatusObsrvr->connectBackhaul();
+            char clientName[30] = {0};
+            sscanf(data, "%*s %29s", clientName);
+            mSystemStatusObsrvr->connectBackhaul(string(clientName));
         } else if (!STRNCMP(data, "disconnectBackhaul")) {
-            mSystemStatusObsrvr->disconnectBackhaul();
+            char clientName[30] = {0};
+            sscanf(data, "%*s %29s", clientName);
+            mSystemStatusObsrvr->disconnectBackhaul(string(clientName));
 #endif
         } else if (!STRNCMP(data, "requestStatus")) {
             int32_t xtraStatusUpdated = 0;
@@ -88,6 +92,8 @@
                         mXSSO(xsso), mXtraStatusUpdated(xtraStatusUpdated) {}
                 inline void proc() const override {
                     mXSSO.onStatusRequested(mXtraStatusUpdated);
+                    /* SSR for DGnss Ntrip Source*/
+                    mXSSO.restartDgnssSource();
                 }
             };
             mMsgTask->sendMsg(new HandleStatusRequestMsg(mXSSO, xtraStatusUpdated));
@@ -231,6 +237,55 @@
     return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) );
 }
 
+void XtraSystemStatusObserver::startDgnssSource(const StartDgnssNtripParams& params) {
+    stringstream ss;
+    const GnssNtripConnectionParams* ntripParams = &(params.ntripParams);
+
+    ss <<  "startDgnssSource" << endl;
+    ss << ntripParams->useSSL << endl;
+    ss << ntripParams->hostNameOrIp.data() << endl;
+    ss << ntripParams->port << endl;
+    ss << ntripParams->mountPoint.data() << endl;
+    ss << ntripParams->username.data() << endl;
+    ss << ntripParams->password.data() << endl;
+    if (ntripParams->requiresNmeaLocation && !params.nmea.empty()) {
+        ss << params.nmea.data() << endl;
+    }
+    string s = ss.str();
+
+    LOC_LOGd("%s", s.data());
+    LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size());
+    // make a local copy of the string for SSR
+    mNtripParamsString.assign(std::move(s));
+}
+
+void XtraSystemStatusObserver::restartDgnssSource() {
+    if (!mNtripParamsString.empty()) {
+        LocIpc::send(*mSender,
+            (const uint8_t*)mNtripParamsString.data(), mNtripParamsString.size());
+        LOC_LOGv("Xtra SSR %s", mNtripParamsString.data());
+    }
+}
+
+void XtraSystemStatusObserver::stopDgnssSource() {
+    LOC_LOGv();
+    mNtripParamsString.clear();
+
+    const char s[] = "stopDgnssSource";
+    LocIpc::send(*mSender, (const uint8_t*)s, strlen(s));
+}
+
+void XtraSystemStatusObserver::updateNmeaToDgnssServer(const string& nmea)
+{
+    stringstream ss;
+    ss <<  "updateDgnssServerNmea" << endl;
+    ss << nmea.data() << endl;
+
+    string s = ss.str();
+    LOC_LOGd("%s", s.data());
+    LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size());
+}
+
 void XtraSystemStatusObserver::subscribe(bool yes)
 {
     // Subscription data list
diff --git a/gnss/XtraSystemStatusObserver.h b/gnss/XtraSystemStatusObserver.h
index 3a5259d..56a3a9c 100644
--- a/gnss/XtraSystemStatusObserver.h
+++ b/gnss/XtraSystemStatusObserver.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -33,6 +33,7 @@
 #include <MsgTask.h>
 #include <LocIpc.h>
 #include <LocTimer.h>
+#include <stdlib.h>
 
 using namespace std;
 using namespace loc_util;
@@ -40,6 +41,22 @@
 using loc_core::IDataItemObserver;
 using loc_core::IDataItemCore;
 
+struct StartDgnssNtripParams {
+    GnssNtripConnectionParams ntripParams;
+    string                    nmea;
+
+    void clear() {
+        ntripParams.hostNameOrIp.clear();
+        ntripParams.mountPoint.clear();
+        ntripParams.username.clear();
+        ntripParams.password.clear();
+        ntripParams.port = 0;
+        ntripParams.useSSL = false;
+        ntripParams.requiresNmeaLocation = false;
+        nmea.clear();
+    }
+};
+
 class XtraSystemStatusObserver : public IDataItemObserver {
 public :
     // constructor & destructor
@@ -62,6 +79,10 @@
     inline const MsgTask* getMsgTask() { return mMsgTask; }
     void subscribe(bool yes);
     bool onStatusRequested(int32_t xtraStatusUpdated);
+    void startDgnssSource(const StartDgnssNtripParams& params);
+    void restartDgnssSource();
+    void stopDgnssSource();
+    void updateNmeaToDgnssServer(const string& nmea);
 
 private:
     IOsObserver*    mSystemStatusObsrvr;
@@ -76,6 +97,7 @@
     bool mReqStatusReceived;
     bool mIsConnectivityStatusKnown;
     shared_ptr<LocIpcSender> mSender;
+    string mNtripParamsString;
 
     class DelayLocTimer : public LocTimer {
         LocIpcSender& mSender;
diff --git a/gnss/location_gnss.cpp b/gnss/location_gnss.cpp
index c3ea105..8f67369 100644
--- a/gnss/location_gnss.cpp
+++ b/gnss/location_gnss.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -50,7 +50,7 @@
 static void setControlCallbacks(LocationControlCallbacks& controlCallbacks);
 static uint32_t enable(LocationTechnologyType techType);
 static void disable(uint32_t id);
-static uint32_t* gnssUpdateConfig(GnssConfig config);
+static uint32_t* gnssUpdateConfig(const GnssConfig& config);
 static uint32_t* gnssGetConfig(GnssConfigFlagsMask mask);
 
 static void gnssUpdateSvTypeConfig(GnssSvTypeConfig& config);
@@ -66,14 +66,14 @@
 static void agpsDataConnClosed(AGpsExtType agpsType);
 static void agpsDataConnFailed(AGpsExtType agpsType);
 static void getDebugReport(GnssDebugReport& report);
-static void updateConnectionStatus(bool connected, int8_t type, bool roaming = false,
-                                   NetworkHandle networkHandle = NETWORK_HANDLE_UNKNOWN);
+static void updateConnectionStatus(bool connected, int8_t type, bool roaming,
+                                   NetworkHandle networkHandle, string& apn);
 static void getGnssEnergyConsumed(GnssEnergyConsumedCallback energyConsumedCb);
 static void enableNfwLocationAccess(bool enable);
 static void nfwInit(const NfwCbInfo& cbInfo);
-static void getPowerStateChanges(void* powerStateCb);
+static void getPowerStateChanges(std::function<void(bool)> powerStateCb);
 
-static void odcpiInit(const OdcpiRequestCallback& callback);
+static void odcpiInit(const OdcpiRequestCallback& callback, OdcpiPrioritytype priority);
 static void odcpiInject(const Location& location);
 
 static void blockCPI(double latitude, double longitude, float accuracy,
@@ -83,10 +83,27 @@
 static uint32_t setConstrainedTunc (bool enable, float tuncConstraint,
                                     uint32_t energyBudget);
 static uint32_t setPositionAssistedClockEstimator(bool enable);
-static uint32_t gnssUpdateSvConfig(const GnssSvTypeConfig& svTypeConfig,
-                                   const GnssSvIdConfig& svIdConfig);
+static uint32_t gnssUpdateSvConfig(const GnssSvTypeConfig& constellationEnablementConfig,
+                                   const GnssSvIdConfig& blacklistSvConfig);
 static uint32_t gnssResetSvConfig();
 static uint32_t configLeverArm(const LeverArmConfigInfo& configInfo);
+static uint32_t configRobustLocation(bool enable, bool enableForE911);
+static uint32_t configMinGpsWeek(uint16_t minGpsWeek);
+static uint32_t configDeadReckoningEngineParams(const DeadReckoningEngineConfig& dreConfig);
+static uint32_t gnssUpdateSecondaryBandConfig(const GnssSvTypeConfig& secondaryBandConfig);
+static uint32_t gnssGetSecondaryBandConfig();
+static void resetNetworkInfo();
+
+static void updateNTRIPGGAConsent(bool consentAccepted);
+static void enablePPENtripStream(const GnssNtripConnectionParams& params, bool enableRTKEngine);
+static void disablePPENtripStream();
+
+static bool measCorrInit(const measCorrSetCapabilitiesCb setCapabilitiesCb);
+static bool measCorrSetCorrections(const GnssMeasurementCorrections gnssMeasCorr);
+static void measCorrClose();
+static uint32_t antennaInfoInit(const antennaInfoCb antennaInfoCallback);
+static void antennaInfoClose();
+static uint32_t configEngineRunState(PositioningEngineMask engType, LocEngineRunState engState);
 
 static const GnssInterface gGnssInterface = {
     sizeof(GnssInterface),
@@ -130,8 +147,22 @@
     setConstrainedTunc,
     setPositionAssistedClockEstimator,
     gnssUpdateSvConfig,
-    gnssResetSvConfig,
     configLeverArm,
+    measCorrInit,
+    measCorrSetCorrections,
+    measCorrClose,
+    antennaInfoInit,
+    antennaInfoClose,
+    configRobustLocation,
+    configMinGpsWeek,
+    configDeadReckoningEngineParams,
+    updateNTRIPGGAConsent,
+    enablePPENtripStream,
+    disablePPENtripStream,
+    gnssUpdateSecondaryBandConfig,
+    gnssGetSecondaryBandConfig,
+    resetNetworkInfo,
+    configEngineRunState
 };
 
 #ifndef DEBUG_X86
@@ -236,7 +267,7 @@
     }
 }
 
-static uint32_t* gnssUpdateConfig(GnssConfig config)
+static uint32_t* gnssUpdateConfig(const GnssConfig& config)
 {
     if (NULL != gGnssAdapter) {
         return gGnssAdapter->gnssUpdateConfigCommand(config);
@@ -340,17 +371,18 @@
 }
 
 static void updateConnectionStatus(bool connected, int8_t type,
-                                   bool roaming, NetworkHandle networkHandle) {
+                                   bool roaming, NetworkHandle networkHandle,
+                                   string& apn) {
     if (NULL != gGnssAdapter) {
         gGnssAdapter->getSystemStatus()->eventConnectionStatus(
-                connected, type, roaming, networkHandle);
+                connected, type, roaming, networkHandle, apn);
     }
 }
 
-static void odcpiInit(const OdcpiRequestCallback& callback)
+static void odcpiInit(const OdcpiRequestCallback& callback, OdcpiPrioritytype priority)
 {
     if (NULL != gGnssAdapter) {
-        gGnssAdapter->initOdcpiCommand(callback);
+        gGnssAdapter->initOdcpiCommand(callback, priority);
     }
 }
 
@@ -386,7 +418,8 @@
         gGnssAdapter->initNfwCommand(cbInfo);
     }
 }
-static void getPowerStateChanges(void* powerStateCb)
+
+static void getPowerStateChanges(std::function<void(bool)> powerStateCb)
 {
     if (NULL != gGnssAdapter) {
         gGnssAdapter->getPowerStateChangesCommand(powerStateCb);
@@ -406,6 +439,12 @@
     }
 }
 
+static void resetNetworkInfo() {
+    if (NULL != gGnssAdapter) {
+        gGnssAdapter->getSystemStatus()->resetNetworkInfo();
+    }
+}
+
 static void updateSystemPowerState(PowerStateType systemPowerState) {
    if (NULL != gGnssAdapter) {
        gGnssAdapter->updateSystemPowerStateCommand(systemPowerState);
@@ -429,19 +468,11 @@
 }
 
 static uint32_t gnssUpdateSvConfig(
-        const GnssSvTypeConfig& svTypeConfig,
-        const GnssSvIdConfig& svIdConfig) {
+        const GnssSvTypeConfig& constellationEnablementConfig,
+        const GnssSvIdConfig&   blacklistSvConfig) {
     if (NULL != gGnssAdapter) {
         return gGnssAdapter->gnssUpdateSvConfigCommand(
-                svTypeConfig, svIdConfig);
-    } else {
-        return 0;
-    }
-}
-
-static uint32_t gnssResetSvConfig() {
-    if (NULL != gGnssAdapter) {
-        return gGnssAdapter->gnssResetSvConfigCommand();
+                constellationEnablementConfig, blacklistSvConfig);
     } else {
         return 0;
     }
@@ -454,3 +485,109 @@
         return 0;
     }
 }
+
+static bool measCorrInit(const measCorrSetCapabilitiesCb setCapabilitiesCb) {
+    if (NULL != gGnssAdapter) {
+        return gGnssAdapter->openMeasCorrCommand(setCapabilitiesCb);
+    } else {
+        return false;
+    }
+}
+
+static bool measCorrSetCorrections(const GnssMeasurementCorrections gnssMeasCorr) {
+    if (NULL != gGnssAdapter) {
+        return gGnssAdapter->measCorrSetCorrectionsCommand(gnssMeasCorr);
+    } else {
+        return false;
+    }
+}
+
+static void measCorrClose() {
+    if (NULL != gGnssAdapter) {
+        gGnssAdapter->closeMeasCorrCommand();
+    }
+}
+
+static uint32_t antennaInfoInit(const antennaInfoCb antennaInfoCallback) {
+    if (NULL != gGnssAdapter) {
+        return gGnssAdapter->antennaInfoInitCommand(antennaInfoCallback);
+    } else {
+        return ANTENNA_INFO_ERROR_GENERIC;
+    }
+}
+
+static void antennaInfoClose() {
+    if (NULL != gGnssAdapter) {
+        return gGnssAdapter->antennaInfoCloseCommand();
+    }
+}
+
+static uint32_t configRobustLocation(bool enable, bool enableForE911){
+    if (NULL != gGnssAdapter) {
+        return gGnssAdapter->configRobustLocationCommand(enable, enableForE911);
+    } else {
+        return 0;
+    }
+}
+
+static uint32_t configMinGpsWeek(uint16_t minGpsWeek){
+    if (NULL != gGnssAdapter) {
+        return gGnssAdapter->configMinGpsWeekCommand(minGpsWeek);
+    } else {
+        return 0;
+    }
+}
+
+static uint32_t configDeadReckoningEngineParams(const DeadReckoningEngineConfig& dreConfig){
+    if (NULL != gGnssAdapter) {
+        return gGnssAdapter->configDeadReckoningEngineParamsCommand(dreConfig);
+    } else {
+        return 0;
+    }
+}
+
+static uint32_t gnssUpdateSecondaryBandConfig(
+        const GnssSvTypeConfig& secondaryBandConfig) {
+    if (NULL != gGnssAdapter) {
+        return gGnssAdapter->gnssUpdateSecondaryBandConfigCommand(secondaryBandConfig);
+    } else {
+        return 0;
+    }
+}
+
+static uint32_t gnssGetSecondaryBandConfig(){
+    if (NULL != gGnssAdapter) {
+        return gGnssAdapter->gnssGetSecondaryBandConfigCommand();
+    } else {
+        return 0;
+    }
+}
+
+static void updateNTRIPGGAConsent(bool consentAccepted){
+    if (NULL != gGnssAdapter) {
+        // Call will be enabled once GnssAdapter impl. is ready.
+        gGnssAdapter->updateNTRIPGGAConsentCommand(consentAccepted);
+    }
+}
+
+static void enablePPENtripStream(const GnssNtripConnectionParams& params, bool enableRTKEngine){
+    if (NULL != gGnssAdapter) {
+        // Call will be enabled once GnssAdapter impl. is ready.
+        gGnssAdapter->enablePPENtripStreamCommand(params, enableRTKEngine);
+    }
+}
+
+static void disablePPENtripStream(){
+    if (NULL != gGnssAdapter) {
+        // Call will be enabled once GnssAdapter impl. is ready.
+        gGnssAdapter->disablePPENtripStreamCommand();
+    }
+}
+
+static uint32_t configEngineRunState(PositioningEngineMask engType, LocEngineRunState engState) {
+    if (NULL != gGnssAdapter) {
+        return gGnssAdapter->configEngineRunStateCommand(engType, engState);
+    } else {
+        return 0;
+    }
+}
diff --git a/gps_vendor_product.mk b/gps_vendor_product.mk
index 6e938b3..cd35684 100644
--- a/gps_vendor_product.mk
+++ b/gps_vendor_product.mk
@@ -1,14 +1,48 @@
 # HAL packages
-PRODUCT_PACKAGES += android.hardware.gnss@1.0-impl-qti
-PRODUCT_PACKAGES += android.hardware.gnss@1.0-service-qti
-PRODUCT_PACKAGES += android.hardware.gnss@1.1-impl-qti
-PRODUCT_PACKAGES += android.hardware.gnss@1.1-service-qti
-PRODUCT_PACKAGES += android.hardware.gnss@2.0-impl-qti
-PRODUCT_PACKAGES += android.hardware.gnss@2.0-service-qti
+ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),)
+
+# GPS-HIDL
+LOC_BOARD_PLATFORM_LIST += msm8937
+LOC_BOARD_PLATFORM_LIST += msm8953
+LOC_BOARD_PLATFORM_LIST += msm8998
+LOC_BOARD_PLATFORM_LIST += apq8098_latv
+LOC_BOARD_PLATFORM_LIST += sdm710
+LOC_BOARD_PLATFORM_LIST += qcs605
+LOC_BOARD_PLATFORM_LIST += sdm845
+LOC_BOARD_PLATFORM_LIST += sdm660
+LOC_BOARD_PLATFORM_LIST += msmnile
+LOC_BOARD_PLATFORM_LIST += sdmshrike
+LOC_BOARD_PLATFORM_LIST += $(MSMSTEPPE)
+LOC_BOARD_PLATFORM_LIST += $(TRINKET)
+LOC_BOARD_PLATFORM_LIST += kona
+LOC_BOARD_PLATFORM_LIST += atoll
+LOC_BOARD_PLATFORM_LIST += lito
+LOC_BOARD_PLATFORM_LIST += bengal
+LOC_BOARD_PLATFORM_LIST += lahaina
+LOC_BOARD_PLATFORM_LIST += holi
+
+# Add product packages
+ifneq (,$(filter $(LOC_BOARD_PLATFORM_LIST),$(TARGET_BOARD_PLATFORM)))
+
 PRODUCT_PACKAGES += gps.conf
-PRODUCT_PACKAGES += libloc_core
-PRODUCT_PACKAGES += libgnss
+PRODUCT_PACKAGES += flp.conf
+PRODUCT_PACKAGES += gnss_antenna_info.conf
+PRODUCT_PACKAGES += gnss@2.0-base.policy
+PRODUCT_PACKAGES += gnss@2.0-xtra-daemon.policy
+PRODUCT_PACKAGES += gnss@2.0-xtwifi-client.policy
+PRODUCT_PACKAGES += gnss@2.0-xtwifi-inet-agent.policy
+PRODUCT_PACKAGES += libloc_pla_headers
+PRODUCT_PACKAGES += liblocation_api_headers
+PRODUCT_PACKAGES += libgps.utils_headers
 PRODUCT_PACKAGES += liblocation_api
 PRODUCT_PACKAGES += libgps.utils
 PRODUCT_PACKAGES += libbatching
 PRODUCT_PACKAGES += libgeofencing
+PRODUCT_PACKAGES += libloc_core
+PRODUCT_PACKAGES += libgnss
+
+PRODUCT_PACKAGES += android.hardware.gnss@2.1-impl-qti
+PRODUCT_PACKAGES += android.hardware.gnss@2.1-service-qti
+
+endif # ifneq (,$(filter $(LOC_BOARD_PLATFORM_LIST),$(TARGET_BOARD_PLATFORM)))
+endif # ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),)
diff --git a/location/Android.bp b/location/Android.bp
new file mode 100644
index 0000000..9126305
--- /dev/null
+++ b/location/Android.bp
@@ -0,0 +1,45 @@
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_qcom_sm7250_gps_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-BSD
+    default_applicable_licenses: ["hardware_qcom_sm7250_gps_license"],
+}
+
+cc_library_shared {
+
+    name: "liblocation_api",
+    vendor: true,
+
+
+
+    shared_libs: [
+        "libutils",
+        "libcutils",
+        "libgps.utils",
+        "libdl",
+        "liblog",
+    ],
+
+    srcs: [
+        "LocationAPI.cpp",
+        "LocationAPIClientBase.cpp",
+    ],
+
+    cflags: ["-fno-short-enums"] + GNSS_CFLAGS,
+
+    header_libs: [
+        "libloc_pla_headers",
+        "libgps.utils_headers",
+    ],
+
+}
+
+cc_library_headers {
+
+    name: "liblocation_api_headers",
+    export_include_dirs: ["."],
+    vendor: true,
+}
diff --git a/location/Android.mk b/location/Android.mk
deleted file mode 100644
index 2a59541..0000000
--- a/location/Android.mk
+++ /dev/null
@@ -1,44 +0,0 @@
-ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),)
-ifneq ($(BUILD_TINY_ANDROID),true)
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := liblocation_api
-LOCAL_SANITIZE += $(GNSS_SANITIZE)
-# activate the following line for debug purposes only, comment out for production
-#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SHARED_LIBRARIES := \
-    libutils \
-    libcutils \
-    libgps.utils \
-    libdl \
-    liblog
-
-LOCAL_SRC_FILES += \
-    LocationAPI.cpp \
-    LocationAPIClientBase.cpp
-
-LOCAL_CFLAGS += \
-     -fno-short-enums
-
-LOCAL_HEADER_LIBRARIES := \
-    libloc_pla_headers \
-    libgps.utils_headers
-
-LOCAL_PRELINK_MODULE := false
-
-LOCAL_CFLAGS += $(GNSS_CFLAGS)
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := liblocation_api_headers
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-include $(BUILD_HEADER_LIBRARY)
-
-endif # not BUILD_TINY_ANDROID
-endif # BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE
diff --git a/location/ILocationAPI.h b/location/ILocationAPI.h
index 87aa99b..29846ac 100644
--- a/location/ILocationAPI.h
+++ b/location/ILocationAPI.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -179,7 +179,7 @@
                 LOCATION_ERROR_SUCCESS if session was successful
                 LOCATION_ERROR_INVALID_PARAMETER if any other parameters are invalid
                 LOCATION_ERROR_GENERAL_FAILURE if failure for any other reason */
-    virtual uint32_t* gnssUpdateConfig(GnssConfig config) = 0;
+    virtual uint32_t* gnssUpdateConfig(const GnssConfig& config) = 0;
 
     /** @brief Delete specific gnss aiding data for testing, which returns a session id
        that will be returned in responseCallback to match command with response.
@@ -191,27 +191,17 @@
     virtual uint32_t gnssDeleteAidingData(GnssAidingData& data) = 0;
 
     /** @brief
-        Reset the constellation settings to modem default.
-
-        @param
-        None
-
-        @return
-        A session id that will be returned in responseCallback to
-        match command with response. This effect is global for all
-        clients of LocationAPI responseCallback returns:
-                LOCATION_ERROR_SUCCESS if successful
-                LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
-    */
-    virtual uint32_t resetConstellationConfig() = 0;
-
-    /** @brief
-        Configure the constellation to be used by the GNSS engine on
+        Configure the constellation and SVs to be used by the GNSS engine on
         modem.
 
         @param
-        constellationConfig: specify the constellation configuration
-        used by GNSS engine.
+        constellationEnablementConfig: configuration to enable/disable SV
+        constellation to be used by SPE engine. When size in
+        constellationEnablementConfig is set to 0, this indicates to reset SV
+        constellation configuration to modem NV default.
+
+        blacklistSvConfig: configuration to blacklist or unblacklist SVs
+        used by SPE engine
 
         @return
         A session id that will be returned in responseCallback to
@@ -221,8 +211,26 @@
                 LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
     */
     virtual uint32_t configConstellations(
-            const GnssSvTypeConfig& svTypeConfig,
-            const GnssSvIdConfig&   svIdConfig) = 0;
+            const GnssSvTypeConfig& constellationEnablementConfig,
+            const GnssSvIdConfig&   blacklistSvConfig) = 0;
+
+    /** @brief
+        Configure the secondary band of constellations to be used by
+        the GNSS engine on modem.
+
+        @param
+        secondaryBandConfig: configuration the secondary band usage
+        for SPE engine
+
+        @return
+        A session id that will be returned in responseCallback to
+        match command with response. This effect is global for all
+        clients of LocationAPI responseCallback returns:
+                LOCATION_ERROR_SUCCESS if successful
+                LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+    */
+    virtual uint32_t configConstellationSecondaryBand(
+            const GnssSvTypeConfig& secondaryBandConfig) = 0;
 
     /** @brief
         Enable or disable the constrained time uncertainty feature.
@@ -302,6 +310,97 @@
                 LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
     */
     virtual uint32_t configLeverArm(const LeverArmConfigInfo& configInfo) = 0;
+
+    /** @brief
+        Configure the robust location setting.
+
+        @param
+        enable: true to enable robust location and false to disable
+        robust location.
+
+        @param
+        enableForE911: true to enable robust location when device is on
+        E911 session and false to disable on E911 session.
+        This parameter is only valid if robust location is enabled.
+
+        @return
+        A session id that will be returned in responseCallback to
+        match command with response. This effect is global for all
+        clients of LocationAPI responseCallback returns:
+                LOCATION_ERROR_SUCCESS if successful
+                LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+    */
+    virtual uint32_t configRobustLocation(bool enable, bool enableForE911) = 0;
+
+    /** @brief
+        Config the minimum GPS week used by modem GNSS engine.
+
+        @param
+        minGpsWeek: minimum GPS week to be used by modem GNSS engine.
+
+        @return
+        A session id that will be returned in responseCallback to
+        match command with response. This effect is global for all
+        clients of LocationAPI responseCallback returns:
+                LOCATION_ERROR_SUCCESS if successful
+                LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+    */
+    virtual uint32_t configMinGpsWeek(uint16_t minGpsWeek) = 0;
+
+    /** @brief
+        Configure the vehicle body-to-Sensor mount parameters and
+        other parameters for dead reckoning position engine.
+
+        @param
+        dreConfig: vehicle body-to-Sensor mount angles and other
+        parameters.
+
+        @return
+        A session id that will be returned in responseCallback to
+        match command with response. This effect is global for all
+        clients of LocationAPI responseCallback returns:
+                LOCATION_ERROR_SUCCESS if successful
+                LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+    */
+    virtual uint32_t configDeadReckoningEngineParams(const DeadReckoningEngineConfig& dreConfig)=0;
+
+    /** @brief
+        This API is used to instruct the specified engine to be in
+        the pause/resume state. <br/>
+
+        When the engine is placed in paused state, the engine will
+        stop. If there is an on-going session, engine will no longer
+        produce fixes. In the paused state, calling API to delete
+        aiding data from the paused engine may not have effect.
+        Request to delete Aiding data shall be issued after
+        engine resume. <br/>
+
+        Currently, only DRE engine will support pause/resume
+        request. responseCb() will return not supported when request
+        is made to pause/resume none-DRE engine. <br/>
+
+        Request to pause/resume DRE engine can be made with or
+        without an on-going session. With QDR engine, on resume,
+        GNSS position & heading re-acquisition is needed for DR
+        engine to engage. If DR engine is already in the requested
+        state, the request will be no-op.  <br/>
+
+        @param
+        engType: the engine that is instructed to change its run
+        state. <br/>
+
+        engState: the new engine run state that the engine is
+        instructed to be in. <br/>
+
+        @return
+        A session id that will be returned in responseCallback to
+        match command with response. This effect is global for all
+        clients of LocationAPI responseCallback returns:
+                LOCATION_ERROR_SUCCESS if successful
+                LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+    */
+    virtual uint32_t configEngineRunState(PositioningEngineMask engType,
+                                          LocEngineRunState engState) = 0;
 };
 
 #endif /* ILOCATIONAPI_H */
diff --git a/location/LocationAPI.cpp b/location/LocationAPI.cpp
index 7c125b8..3a50c46 100644
--- a/location/LocationAPI.cpp
+++ b/location/LocationAPI.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -39,6 +39,15 @@
 typedef const GnssInterface* (getGnssInterface)();
 typedef const GeofenceInterface* (getGeofenceInterface)();
 typedef const BatchingInterface* (getBatchingInterface)();
+typedef void (createOSFramework)();
+typedef void (destroyOSFramework)();
+
+// GTP services
+typedef uint32_t (setOptInStatusGetter)(bool userConsent, responseCallback* callback);
+typedef void (enableProviderGetter)();
+typedef void (disableProviderGetter)();
+typedef void (getSingleNetworkLocationGetter)(trackingCallback* callback);
+typedef void (stopNetworkLocationGetter)(trackingCallback* callback);
 
 typedef struct {
     // bit mask of the adpaters that we need to wait for the removeClientCompleteCallback
@@ -68,6 +77,7 @@
 static bool gGnssLoadFailed = false;
 static bool gBatchingLoadFailed = false;
 static bool gGeofenceLoadFailed = false;
+static uint32_t gOSFrameworkRefCount = 0;
 
 template <typename T1, typename T2>
 static const T1* loadLocationInterface(const char* library, const char* name) {
@@ -80,13 +90,49 @@
     }
 }
 
+static void createOSFrameworkInstance() {
+    void* libHandle = nullptr;
+    createOSFramework* getter = (createOSFramework*)dlGetSymFromLib(libHandle,
+            "liblocationservice_glue.so", "createOSFramework");
+    if (getter != nullptr) {
+        (*getter)();
+    } else {
+        LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
+    }
+}
+
+static void destroyOSFrameworkInstance() {
+    void* libHandle = nullptr;
+    destroyOSFramework* getter = (destroyOSFramework*)dlGetSymFromLib(libHandle,
+            "liblocationservice_glue.so", "destroyOSFramework");
+    if (getter != nullptr) {
+        (*getter)();
+    } else {
+        LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
+    }
+}
+
+static bool needsGnssTrackingInfo(LocationCallbacks& locationCallbacks)
+{
+    return (locationCallbacks.gnssLocationInfoCb != nullptr ||
+            locationCallbacks.engineLocationsInfoCb != nullptr ||
+            locationCallbacks.gnssSvCb != nullptr ||
+            locationCallbacks.gnssNmeaCb != nullptr ||
+            locationCallbacks.gnssDataCb != nullptr ||
+            locationCallbacks.gnssMeasurementsCb != nullptr);
+}
+
 static bool isGnssClient(LocationCallbacks& locationCallbacks)
 {
     return (locationCallbacks.gnssNiCb != nullptr ||
             locationCallbacks.trackingCb != nullptr ||
             locationCallbacks.gnssLocationInfoCb != nullptr ||
             locationCallbacks.engineLocationsInfoCb != nullptr ||
-            locationCallbacks.gnssMeasurementsCb != nullptr);
+            locationCallbacks.gnssSvCb != nullptr ||
+            locationCallbacks.gnssNmeaCb != nullptr ||
+            locationCallbacks.gnssDataCb != nullptr ||
+            locationCallbacks.gnssMeasurementsCb != nullptr ||
+            locationCallbacks.locationSystemInfoCb != nullptr);
 }
 
 static bool isBatchingClient(LocationCallbacks& locationCallbacks)
@@ -118,10 +164,11 @@
     }
     pthread_mutex_unlock(&gDataMutex);
 
-    if ((true == invokeCallback) && (nullptr != destroyCompleteCb)) {
+    if (invokeCallback) {
         LOC_LOGd("invoke client destroy cb");
-        (destroyCompleteCb) ();
-        LOC_LOGd("finish invoke client destroy cb");
+        if (!destroyCompleteCb) {
+            (destroyCompleteCb) ();
+        }
 
         delete this;
     }
@@ -143,11 +190,12 @@
 }
 
 LocationAPI*
-LocationAPI::createInstance(LocationCallbacks& locationCallbacks)
+LocationAPI::createInstance (LocationCallbacks& locationCallbacks)
 {
     if (nullptr == locationCallbacks.capabilitiesCb ||
         nullptr == locationCallbacks.responseCb ||
         nullptr == locationCallbacks.collectiveResponseCb) {
+        LOC_LOGe("missing mandatory callback, return null");
         return NULL;
     }
 
@@ -156,6 +204,11 @@
 
     pthread_mutex_lock(&gDataMutex);
 
+    gOSFrameworkRefCount++;
+    if (1 == gOSFrameworkRefCount) {
+        createOSFrameworkInstance();
+    }
+
     if (isGnssClient(locationCallbacks)) {
         if (NULL == gData.gnssInterface && !gGnssLoadFailed) {
             gData.gnssInterface =
@@ -234,15 +287,12 @@
     pthread_mutex_lock(&gDataMutex);
     auto it = gData.clientData.find(this);
     if (it != gData.clientData.end()) {
-        bool removeFromGnssInf =
-                (isGnssClient(it->second) && NULL != gData.gnssInterface);
-        bool removeFromBatchingInf =
-                (isBatchingClient(it->second) && NULL != gData.batchingInterface);
-        bool removeFromGeofenceInf =
-                (isGeofenceClient(it->second) && NULL != gData.geofenceInterface);
+        bool removeFromGnssInf = (NULL != gData.gnssInterface);
+        bool removeFromBatchingInf = (NULL != gData.batchingInterface);
+        bool removeFromGeofenceInf = (NULL != gData.geofenceInterface);
         bool needToWait = (removeFromGnssInf || removeFromBatchingInf || removeFromGeofenceInf);
         LOC_LOGe("removeFromGnssInf: %d, removeFromBatchingInf: %d, removeFromGeofenceInf: %d,"
-                 "need %d", removeFromGnssInf, removeFromBatchingInf, removeFromGeofenceInf,
+                 "needToWait: %d", removeFromGnssInf, removeFromBatchingInf, removeFromGeofenceInf,
                  needToWait);
 
         if ((NULL != destroyCompleteCb) && (true == needToWait)) {
@@ -258,7 +308,7 @@
             destroyCbData.waitAdapterMask |=
                     (removeFromGeofenceInf ? LOCATION_ADAPTER_GEOFENCE_TYPE_BIT : 0);
             gData.destroyClientData[this] = destroyCbData;
-            LOC_LOGe("destroy data stored in the map: 0x%x", destroyCbData.waitAdapterMask);
+            LOC_LOGi("destroy data stored in the map: 0x%x", destroyCbData.waitAdapterMask);
         }
 
         if (removeFromGnssInf) {
@@ -276,7 +326,7 @@
 
         gData.clientData.erase(it);
 
-        if ((NULL != destroyCompleteCb) && (false == needToWait)) {
+        if (!needToWait) {
             invokeDestroyCb = true;
         }
     } else {
@@ -284,9 +334,16 @@
                  __func__, __LINE__, this);
     }
 
+    if (1 == gOSFrameworkRefCount) {
+        destroyOSFrameworkInstance();
+    }
+    gOSFrameworkRefCount--;
+
     pthread_mutex_unlock(&gDataMutex);
-    if (invokeDestroyCb == true) {
-        (destroyCompleteCb) ();
+    if (invokeDestroyCb) {
+        if (!destroyCompleteCb) {
+            (destroyCompleteCb) ();
+        }
         delete this;
     }
 }
@@ -592,6 +649,52 @@
     pthread_mutex_unlock(&gDataMutex);
 }
 
+void LocationAPI::enableNetworkProvider() {
+    void* libHandle = nullptr;
+    enableProviderGetter* setter = (enableProviderGetter*)dlGetSymFromLib(libHandle,
+            "liblocationservice_glue.so", "enableNetworkProvider");
+    if (setter != nullptr) {
+        (*setter)();
+    } else {
+        LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
+    }
+}
+
+void LocationAPI::disableNetworkProvider() {
+    void* libHandle = nullptr;
+    disableProviderGetter* setter = (disableProviderGetter*)dlGetSymFromLib(libHandle,
+            "liblocationservice_glue.so", "disableNetworkProvider");
+    if (setter != nullptr) {
+        (*setter)();
+    } else {
+        LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
+    }
+}
+
+void LocationAPI::startNetworkLocation(trackingCallback* callback) {
+    void* libHandle = nullptr;
+    getSingleNetworkLocationGetter* setter =
+            (getSingleNetworkLocationGetter*)dlGetSymFromLib(libHandle,
+            "liblocationservice_glue.so", "startNetworkLocation");
+    if (setter != nullptr) {
+        (*setter)(callback);
+    } else {
+        LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
+    }
+}
+
+void LocationAPI::stopNetworkLocation(trackingCallback* callback) {
+    void* libHandle = nullptr;
+    stopNetworkLocationGetter* setter = (stopNetworkLocationGetter*)dlGetSymFromLib(libHandle,
+            "liblocationservice_glue.so", "stopNetworkLocation");
+    if (setter != nullptr) {
+        LOC_LOGe("called");
+        (*setter)(callback);
+    } else {
+        LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
+    }
+}
+
 LocationControlAPI*
 LocationControlAPI::createInstance(LocationControlCallbacks& locationControlCallbacks)
 {
@@ -676,7 +779,7 @@
 }
 
 uint32_t*
-LocationControlAPI::gnssUpdateConfig(GnssConfig config)
+LocationControlAPI::gnssUpdateConfig(const GnssConfig& config)
 {
     uint32_t* ids = NULL;
     pthread_mutex_lock(&gDataMutex);
@@ -724,12 +827,15 @@
     return id;
 }
 
-uint32_t LocationControlAPI::resetConstellationConfig() {
+uint32_t LocationControlAPI::configConstellations(
+        const GnssSvTypeConfig& constellationEnablementConfig,
+        const GnssSvIdConfig&   blacklistSvConfig) {
     uint32_t id = 0;
     pthread_mutex_lock(&gDataMutex);
 
     if (gData.gnssInterface != NULL) {
-        id = gData.gnssInterface->gnssResetSvConfig();
+        id = gData.gnssInterface->gnssUpdateSvConfig(
+                constellationEnablementConfig, blacklistSvConfig);
     } else {
         LOC_LOGe("No gnss interface available for Location Control API");
     }
@@ -738,15 +844,13 @@
     return id;
 }
 
-uint32_t LocationControlAPI::configConstellations(
-        const GnssSvTypeConfig& svTypeConfig,
-        const GnssSvIdConfig&   svIdConfig) {
+uint32_t LocationControlAPI::configConstellationSecondaryBand(
+        const GnssSvTypeConfig& secondaryBandConfig) {
     uint32_t id = 0;
     pthread_mutex_lock(&gDataMutex);
 
     if (gData.gnssInterface != NULL) {
-        id = gData.gnssInterface->gnssUpdateSvConfig(
-                svTypeConfig, svIdConfig);
+        id = gData.gnssInterface->gnssUpdateSecondaryBandConfig(secondaryBandConfig);
     } else {
         LOC_LOGe("No gnss interface available for Location Control API");
     }
@@ -799,3 +903,74 @@
     pthread_mutex_unlock(&gDataMutex);
     return id;
 }
+
+uint32_t LocationControlAPI::configRobustLocation(bool enable, bool enableForE911) {
+    uint32_t id = 0;
+    pthread_mutex_lock(&gDataMutex);
+
+    if (gData.gnssInterface != NULL) {
+        id = gData.gnssInterface->configRobustLocation(enable, enableForE911);
+    } else {
+        LOC_LOGe("No gnss interface available for Location Control API");
+    }
+
+    pthread_mutex_unlock(&gDataMutex);
+    return id;
+}
+
+uint32_t LocationControlAPI::configMinGpsWeek(uint16_t minGpsWeek) {
+    uint32_t id = 0;
+    pthread_mutex_lock(&gDataMutex);
+
+    if (gData.gnssInterface != NULL) {
+        id = gData.gnssInterface->configMinGpsWeek(minGpsWeek);
+    } else {
+        LOC_LOGe("No gnss interface available for Location Control API");
+    }
+
+    pthread_mutex_unlock(&gDataMutex);
+    return id;
+}
+
+uint32_t LocationControlAPI::configDeadReckoningEngineParams(
+        const DeadReckoningEngineConfig& dreConfig) {
+    uint32_t id = 0;
+    pthread_mutex_lock(&gDataMutex);
+
+    if (gData.gnssInterface != NULL) {
+        id = gData.gnssInterface->configDeadReckoningEngineParams(dreConfig);
+    } else {
+        LOC_LOGe("No gnss interface available for Location Control API");
+    }
+
+    pthread_mutex_unlock(&gDataMutex);
+    return id;
+}
+
+uint32_t LocationControlAPI::configEngineRunState(
+        PositioningEngineMask engType, LocEngineRunState engState) {
+    uint32_t id = 0;
+    pthread_mutex_lock(&gDataMutex);
+
+    if (gData.gnssInterface != NULL) {
+        id = gData.gnssInterface->configEngineRunState(engType, engState);
+    } else {
+        LOC_LOGe("No gnss interface available for Location Control API");
+    }
+
+    pthread_mutex_unlock(&gDataMutex);
+    return id;
+}
+
+uint32_t LocationControlAPI::setOptInStatus(bool userConsent) {
+    void* libHandle = nullptr;
+    uint32_t sessionId = 0;
+    setOptInStatusGetter* setter = (setOptInStatusGetter*)dlGetSymFromLib(libHandle,
+            "liblocationservice_glue.so", "setOptInStatus");
+    if (setter != nullptr) {
+        sessionId = (*setter)(userConsent, &gData.controlCallbacks.responseCb);
+    } else {
+        LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
+    }
+    return sessionId;
+}
diff --git a/location/LocationAPI.h b/location/LocationAPI.h
index f70fc2f..7c70506 100644
--- a/location/LocationAPI.h
+++ b/location/LocationAPI.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -178,6 +178,20 @@
                 LOCATION_ERROR_INVALID_PARAMETER if any parameters in GnssNiResponse are invalid
                 LOCATION_ERROR_ID_UNKNOWN if id does not match a gnssNiCallback */
     virtual void gnssNiResponse(uint32_t id, GnssNiResponse response) override;
+
+    /* ================================== NETWORK PROVIDER =========================== */
+
+    /* enableNetworkProvider enables Network Provider */
+    virtual void enableNetworkProvider();
+
+    /* disableNetworkProvider disables Network Provider */
+    virtual void disableNetworkProvider();
+
+    /* startNetworkLocation start a single shot network location request */
+    virtual void startNetworkLocation(trackingCallback* callback);
+
+    /* stopNetworkLocation stop any ongoing network location request */
+    virtual void stopNetworkLocation(trackingCallback* callback);
 };
 
 typedef struct {
@@ -235,8 +249,11 @@
         collectiveResponseCallback returns:
                 LOCATION_ERROR_SUCCESS if session was successful
                 LOCATION_ERROR_INVALID_PARAMETER if any other parameters are invalid
-                LOCATION_ERROR_GENERAL_FAILURE if failure for any other reason */
-    virtual uint32_t* gnssUpdateConfig(GnssConfig config) override;
+                LOCATION_ERROR_GENERAL_FAILURE if failure for any other reason
+
+      PLEASE NOTE: It is caller's resposibility to FREE the memory of the return value.
+                   The memory must be freed by delete [].*/
+    virtual uint32_t* gnssUpdateConfig(const GnssConfig& config) override;
 
     /* gnssGetConfig fetches the current constellation and SV configuration
        on the GNSS engine.
@@ -250,7 +267,10 @@
            LOCATION_ERROR_CALLBACK_MISSING If no gnssConfigCallback
                                            was passed in createInstance
            LOCATION_ERROR_NOT_SUPPORTED If read of requested configuration
-                                        is not supported */
+                                        is not supported
+
+      PLEASE NOTE: It is caller's resposibility to FREE the memory of the return value.
+                   The memory must be freed by delete [].*/
     uint32_t* gnssGetConfig(GnssConfigFlagsMask mask);
 
     /* delete specific gnss aiding data for testing, which returns a session id
@@ -263,27 +283,17 @@
     virtual uint32_t gnssDeleteAidingData(GnssAidingData& data) override;
 
     /** @brief
-        Reset the constellation settings to modem default.
-
-        @param
-        None
-
-        @return
-        A session id that will be returned in responseCallback to
-        match command with response. This effect is global for all
-        clients of LocationAPI responseCallback returns:
-                LOCATION_ERROR_SUCCESS if successful
-                LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
-    */
-    virtual uint32_t resetConstellationConfig() override;
-
-    /** @brief
-        Configure the constellation to be used by the GNSS engine on
+        Configure the constellation and SVs to be used by the GNSS engine on
         modem.
 
         @param
-        constellationConfig: specify the constellation configuration
-        used by GNSS engine.
+        constellationEnablementConfig: configuration to enable/disable SV
+        constellation to be used by SPE engine. When size in
+        constellationEnablementConfig is set to 0, this indicates to reset SV
+        constellation configuration to modem NV default.
+
+        blacklistSvConfig: configuration to blacklist or unblacklist SVs
+        used by SPE engine
 
         @return
         A session id that will be returned in responseCallback to
@@ -293,8 +303,26 @@
                 LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
     */
     virtual uint32_t configConstellations(
-            const GnssSvTypeConfig& svTypeConfig,
-            const GnssSvIdConfig&   svIdConfig) override;
+            const GnssSvTypeConfig& constellationEnablementConfig,
+            const GnssSvIdConfig&   blacklistSvConfig) override;
+
+    /** @brief
+        Configure the secondary band of constellations to be used by
+        the GNSS engine on modem.
+
+        @param
+        secondaryBandConfig: configuration the secondary band usage
+        for SPE engine
+
+        @return
+        A session id that will be returned in responseCallback to
+        match command with response. This effect is global for all
+        clients of LocationAPI responseCallback returns:
+                LOCATION_ERROR_SUCCESS if successful
+                LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+    */
+    virtual uint32_t configConstellationSecondaryBand(
+            const GnssSvTypeConfig& secondaryBandConfig) override;
 
     /** @brief
         Enable or disable the constrained time uncertainty feature.
@@ -374,6 +402,111 @@
                 LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
     */
     virtual uint32_t configLeverArm(const LeverArmConfigInfo& configInfo) override;
+
+    /** @brief
+        Configure the robust location setting.
+
+        @param
+        enable: true to enable robust location and false to disable
+        robust location.
+
+        @param
+        enableForE911: true to enable robust location when device is
+        on E911 session and false to disable on E911 session.
+        This parameter is only valid if robust location is enabled.
+
+        @return
+        A session id that will be returned in responseCallback to
+        match command with response. This effect is global for all
+        clients of LocationAPI responseCallback returns:
+                LOCATION_ERROR_SUCCESS if successful
+                LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+    */
+    virtual uint32_t configRobustLocation(bool enable, bool enableForE911) override;
+
+    /** @brief
+        Config the minimal GPS week used by modem GNSS engine.
+
+        @param
+        minGpsWeek: minimal GPS week to be used by modem GNSS engine.
+
+        @return
+        A session id that will be returned in responseCallback to
+        match command with response. This effect is global for all
+        clients of LocationAPI responseCallback returns:
+                LOCATION_ERROR_SUCCESS if successful
+                LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+    */
+    virtual uint32_t configMinGpsWeek(uint16_t minGpsWeek) override;
+
+    /** @brief
+        Configure the vehicle body-to-Sensor mount parameters and
+        other parameters for dead reckoning position engine.
+
+        @param
+        dreConfig: vehicle body-to-Sensor mount angles and other
+        parameters.
+
+        @return
+        A session id that will be returned in responseCallback to
+        match command with response. This effect is global for all
+        clients of LocationAPI responseCallback returns:
+                LOCATION_ERROR_SUCCESS if successful
+                LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+    */
+    virtual uint32_t configDeadReckoningEngineParams(
+            const DeadReckoningEngineConfig& dreConfig) override;
+
+        /** @brief
+        This API is used to instruct the specified engine to be in
+        the pause/resume state. <br/>
+
+        When the engine is placed in paused state, the engine will
+        stop. If there is an on-going session, engine will no longer
+        produce fixes. In the paused state, calling API to delete
+        aiding data from the paused engine may not have effect.
+        Request to delete Aiding data shall be issued after
+        engine resume. <br/>
+
+        Currently, only DRE engine will support pause/resume
+        request. responseCb() will return not supported when request
+        is made to pause/resume none-DRE engine. <br/>
+
+        Request to pause/resume DRE engine can be made with or
+        without an on-going session. With QDR engine, on resume, GNSS
+        position & heading re-acquisition is needed for DR engine to
+        engage. If DR engine is already in the requested state, the
+        request will be no-op.  <br/>
+
+        @param
+        engType: the engine that is instructed to change its run
+        state. <br/>
+
+        engState: the new engine run state that the engine is
+        instructed to be in. <br/>
+
+        @return
+        A session id that will be returned in responseCallback to
+        match command with response. This effect is global for all
+        clients of LocationAPI responseCallback returns:
+                LOCATION_ERROR_SUCCESS if successful
+                LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+    */
+    virtual uint32_t configEngineRunState(PositioningEngineMask engType,
+                                          LocEngineRunState engState) override;
+
+      /** @brief
+        Set the EULA opt-in status from system user. This is used as consent to
+        use network-based positioning.
+
+        @param
+        userConsnt: user agrees to use GTP service or not.
+
+        @return
+        A session id that will be returned in responseCallback to
+        match command with response.
+    */
+    virtual uint32_t setOptInStatus(bool userConsent);
 };
 
 #endif /* LOCATIONAPI_H */
diff --git a/location/LocationAPIClientBase.cpp b/location/LocationAPIClientBase.cpp
index 5a09712..ea15a76 100644
--- a/location/LocationAPIClientBase.cpp
+++ b/location/LocationAPIClientBase.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017, 2020-2021 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -158,6 +158,7 @@
                 }
                 mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].push(new GnssUpdateConfigRequest(*this));
                 retVal = LOCATION_ERROR_SUCCESS;
+                delete [] idArray;
             }
         }
     }
@@ -180,6 +181,7 @@
             }
             mRequestQueues[CTRL_REQUEST_CONFIG_GET].push(new GnssGetConfigRequest(*this));
             retVal = LOCATION_ERROR_SUCCESS;
+            delete [] idArray;
         }
     }
     pthread_mutex_unlock(&mMutex);
@@ -310,26 +312,45 @@
     pthread_mutex_unlock(&mMutex);
 }
 
-LocationAPIClientBase::~LocationAPIClientBase()
+void LocationAPIClientBase::destroy()
 {
+    LOC_LOGD("LocationAPIClientBase::destroy()");
+
     pthread_mutex_lock(&mMutex);
 
     mGeofenceBreachCallback = nullptr;
 
-    if (mLocationAPI) {
-        mLocationAPI->destroy();
-        mLocationAPI = nullptr;
-    }
-
     for (int i = 0; i < REQUEST_MAX; i++) {
         mRequestQueues[i].reset((uint32_t)0);
     }
 
+    LocationAPI* localHandle = nullptr;
+    if (nullptr != mLocationAPI) {
+        localHandle = mLocationAPI;
+        mLocationAPI = nullptr;
+    }
+
     pthread_mutex_unlock(&mMutex);
 
+    // Invoking destroy has the possibility of destroy complete callback
+    // being invoked right away in the same context, hence no instance
+    // member must be accessed after the destroy call.
+    if (nullptr != localHandle) {
+        localHandle->destroy([this]() {onLocationApiDestroyCompleteCb();});
+    }
+}
+
+LocationAPIClientBase::~LocationAPIClientBase()
+{
     pthread_mutex_destroy(&mMutex);
 }
 
+void LocationAPIClientBase::onLocationApiDestroyCompleteCb()
+{
+    LOC_LOGD("LocationAPIClientBase::onLocationApiDestroyCompleteCb()");
+    delete this;
+}
+
 uint32_t LocationAPIClientBase::locAPIStartTracking(TrackingOptions& options)
 {
     uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
@@ -613,7 +634,7 @@
             }
         }  else {
             retVal = LOCATION_ERROR_ID_UNKNOWN;
-            LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, id);
+            LOC_LOGd("unknown session id: %d, might flush() a stopped session",  id);
         }
     }
     pthread_mutex_unlock(&mMutex);
@@ -799,7 +820,9 @@
 void LocationAPIClientBase::locAPIRemoveAllGeofences()
 {
     std::vector<uint32_t> sessionsVec = mGeofenceBiDict.getAllSessions();
-    locAPIRemoveGeofences(sessionsVec.size(), &sessionsVec[0]);
+    if (sessionsVec.size() > 0) {
+        locAPIRemoveGeofences(sessionsVec.size(), &sessionsVec[0]);
+    }
 }
 
 void LocationAPIClientBase::locAPIGnssNiResponse(uint32_t id, GnssNiResponse response)
diff --git a/location/LocationAPIClientBase.h b/location/LocationAPIClientBase.h
index 098000c..ac1ebe6 100644
--- a/location/LocationAPIClientBase.h
+++ b/location/LocationAPIClientBase.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -200,10 +200,12 @@
 class LocationAPIClientBase {
 public:
     LocationAPIClientBase();
-    virtual ~LocationAPIClientBase();
     LocationAPIClientBase(const LocationAPIClientBase&) = delete;
     LocationAPIClientBase& operator=(const LocationAPIClientBase&) = delete;
 
+    void destroy();
+    void onLocationApiDestroyCompleteCb();
+
     void locAPISetCallbacks(LocationCallbacks& locationCallbacks);
     void removeSession(uint32_t session);
     LocationAPIRequest* getRequestBySession(uint32_t session);
@@ -283,6 +285,9 @@
 
     inline virtual void onLocationSystemInfoCb(LocationSystemInfo /*locationSystemInfo*/) {}
 
+protected:
+    virtual ~LocationAPIClientBase();
+
 private:
     // private inner classes
     typedef struct {
diff --git a/location/LocationDataTypes.h b/location/LocationDataTypes.h
index 65b5e13..b85464a 100644
--- a/location/LocationDataTypes.h
+++ b/location/LocationDataTypes.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -34,10 +34,11 @@
 #include <functional>
 #include <list>
 #include <string.h>
+#include <string>
 
 #define GNSS_NI_REQUESTOR_MAX  (256)
 #define GNSS_NI_MESSAGE_ID_MAX (2048)
-#define GNSS_SV_MAX            (176)
+#define GNSS_SV_MAX            (128)
 #define GNSS_MEASUREMENTS_MAX  (128)
 #define GNSS_UTC_TIME_OFFSET   (3657)
 
@@ -60,7 +61,8 @@
     LOCATION_ERROR_ID_UNKNOWN,
     LOCATION_ERROR_ALREADY_STARTED,
     LOCATION_ERROR_GEOFENCES_AT_MAX,
-    LOCATION_ERROR_NOT_SUPPORTED
+    LOCATION_ERROR_NOT_SUPPORTED,
+    LOCATION_ERROR_TIMEOUT,
 } LocationError;
 
 // Flags to indicate which values are valid in a Location
@@ -75,14 +77,25 @@
     LOCATION_HAS_SPEED_ACCURACY_BIT    = (1<<6), // location has valid speed accuracy
     LOCATION_HAS_BEARING_ACCURACY_BIT  = (1<<7), // location has valid bearing accuracy
     LOCATION_HAS_SPOOF_MASK            = (1<<8), // location has valid spoof mask
+    LOCATION_HAS_ELAPSED_REAL_TIME     = (1<<9), // location has valid elapsed real time
+    LOCATION_HAS_CONFORMITY_INDEX_BIT  = (1<<10), // location has valid conformity index
 } LocationFlagsBits;
 
 typedef uint16_t LocationTechnologyMask;
+// mask indicating location calculations including...
 typedef enum {
-    LOCATION_TECHNOLOGY_GNSS_BIT     = (1<<0), // location was calculated using GNSS
-    LOCATION_TECHNOLOGY_CELL_BIT     = (1<<1), // location was calculated using Cell
-    LOCATION_TECHNOLOGY_WIFI_BIT     = (1<<2), // location was calculated using WiFi
-    LOCATION_TECHNOLOGY_SENSORS_BIT  = (1<<3), // location was calculated using Sensors
+    LOCATION_TECHNOLOGY_GNSS_BIT                     = (1<<0), // using GNSS
+    LOCATION_TECHNOLOGY_CELL_BIT                     = (1<<1), // using Cell
+    LOCATION_TECHNOLOGY_WIFI_BIT                     = (1<<2), // using WiFi
+    LOCATION_TECHNOLOGY_SENSORS_BIT                  = (1<<3), // using Sensors
+    LOCATION_TECHNOLOGY_REFERENCE_LOCATION_BIT       = (1<<4), // using reference location
+    LOCATION_TECHNOLOGY_INJECTED_COARSE_POSITION_BIT = (1<<5), // using CPI
+    LOCATION_TECHNOLOGY_AFLT_BIT                     = (1<<6), // AFLT
+    LOCATION_TECHNOLOGY_HYBRID_BIT                   = (1<<7), // HYBRID
+    LOCATION_TECHNOLOGY_PPE_BIT                      = (1<<8), // PPE
+    LOCATION_TECHNOLOGY_VEH_BIT                      = (1<<9), // using vehicular data
+    LOCATION_TECHNOLOGY_VIS_BIT                      = (1<<10), // using visual data
+    LOCATION_TECHNOLOGY_DGNSS_BIT                    = (1<<11),  // DGNSS
 } LocationTechnologyBits;
 
 typedef uint32_t LocationSpoofMask;
@@ -102,29 +115,26 @@
 
 typedef uint32_t GnssLocationNavSolutionMask;
 typedef enum {
-    LOCATION_SBAS_CORRECTION_IONO_BIT  = (1<<0), // SBAS ionospheric correction is used
-    LOCATION_SBAS_CORRECTION_FAST_BIT  = (1<<1), // SBAS fast correction is used
-    LOCATION_SBAS_CORRECTION_LONG_BIT  = (1<<2), // SBAS long-tem correction is used
-    LOCATION_SBAS_INTEGRITY_BIT        = (1<<3), // SBAS integrity information is used
-    LOCATION_NAV_CORRECTION_DGNSS_BIT  = (1<<4), // Position Report is DGNSS corrected
-    LOCATION_NAV_CORRECTION_RTK_BIT    = (1<<5), // Position Report is RTK corrected
-    LOCATION_NAV_CORRECTION_PPP_BIT    = (1<<6) // Position Report is PPP corrected
+    // SBAS ionospheric correction is used
+    LOCATION_SBAS_CORRECTION_IONO_BIT  = (1<<0),
+    // SBAS fast correction is used
+    LOCATION_SBAS_CORRECTION_FAST_BIT  = (1<<1),
+    // SBAS long-tem correction is used
+    LOCATION_SBAS_CORRECTION_LONG_BIT  = (1<<2),
+    // SBAS integrity information is used
+    LOCATION_SBAS_INTEGRITY_BIT        = (1<<3),
+    // Position Report is DGNSS corrected
+    LOCATION_NAV_CORRECTION_DGNSS_BIT  = (1<<4),
+     // Position Report is RTK corrected
+    LOCATION_NAV_CORRECTION_RTK_BIT    = (1<<5),
+    // Position Report is PPP corrected
+    LOCATION_NAV_CORRECTION_PPP_BIT    = (1<<6),
+    // Posiiton Report is RTF fixed corrected
+    LOCATION_NAV_CORRECTION_RTK_FIXED_BIT  = (1<<7),
+    // Position report is computed with only SBAS corrected SVs.
+    LOCATION_NAV_CORRECTION_ONLY_SBAS_CORRECTED_SV_USED_BIT = (1<<8)
 } GnssLocationNavSolutionBits;
 
-typedef uint32_t GnssLocationPosTechMask;
-typedef enum {
-    LOCATION_POS_TECH_DEFAULT_BIT                  = 0,
-    LOCATION_POS_TECH_SATELLITE_BIT                = (1<<0),
-    LOCATION_POS_TECH_CELLID_BIT                   = (1<<1),
-    LOCATION_POS_TECH_WIFI_BIT                     = (1<<2),
-    LOCATION_POS_TECH_SENSORS_BIT                  = (1<<3),
-    LOCATION_POS_TECH_REFERENCE_LOCATION_BIT       = (1<<4),
-    LOCATION_POS_TECH_INJECTED_COARSE_POSITION_BIT = (1<<5),
-    LOCATION_POS_TECH_AFLT_BIT                     = (1<<6),
-    LOCATION_POS_TECH_HYBRID_BIT                   = (1<<7),
-    LOCATION_POS_TECH_PPE_BIT                      = (1<<8)
-} GnssLocationPosTechBits;
-
 typedef uint32_t GnssLocationPosDataMask;
 typedef enum {
     LOCATION_NAV_DATA_HAS_LONG_ACCEL_BIT  = (1<<0), // Navigation data has Forward Acceleration
@@ -144,39 +154,65 @@
     LOCATION_NAV_DATA_HAS_PITCH_UNC_BIT      = (1<<9)
 } GnssLocationPosDataBits;
 
-typedef uint32_t GnssLocationInfoFlagMask;
+typedef uint32_t GnssLocationPosDataMaskExt;
 typedef enum {
-    GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT      = (1<<0), // valid altitude mean sea level
-    GNSS_LOCATION_INFO_DOP_BIT                          = (1<<1), // valid pdop, hdop, and vdop
-    GNSS_LOCATION_INFO_MAGNETIC_DEVIATION_BIT           = (1<<2), // valid magnetic deviation
-    GNSS_LOCATION_INFO_HOR_RELIABILITY_BIT              = (1<<3), // valid horizontal reliability
-    GNSS_LOCATION_INFO_VER_RELIABILITY_BIT              = (1<<4), // valid vertical reliability
-    GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MAJOR_BIT = (1<<5), // valid elipsode semi major
-    GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MINOR_BIT = (1<<6), // valid elipsode semi minor
-    GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_AZIMUTH_BIT    = (1<<7), // valid accuracy elipsode azimuth
-    GNSS_LOCATION_INFO_GNSS_SV_USED_DATA_BIT            = (1<<8), // valid svUsedInPosition,
-                                                                  //       numOfMeasReceived
-                                                                  //       and measUsageInfo
-    GNSS_LOCATION_INFO_NAV_SOLUTION_MASK_BIT            = (1<<9), // valid navSolutionMask
-    GNSS_LOCATION_INFO_POS_TECH_MASK_BIT                = (1<<10),// valid LocPosTechMask
-    GNSS_LOCATION_INFO_SV_SOURCE_INFO_BIT               = (1<<11),// valid LocSvInfoSource
-    GNSS_LOCATION_INFO_POS_DYNAMICS_DATA_BIT            = (1<<12),// valid position dynamics data
-    GNSS_LOCATION_INFO_EXT_DOP_BIT                      = (1<<13),// valid gdop, tdop
-    GNSS_LOCATION_INFO_NORTH_STD_DEV_BIT                = (1<<14),// valid North standard deviation
-    GNSS_LOCATION_INFO_EAST_STD_DEV_BIT                 = (1<<15),// valid East standard deviation
-    GNSS_LOCATION_INFO_NORTH_VEL_BIT                    = (1<<16),// valid North Velocity
-    GNSS_LOCATION_INFO_EAST_VEL_BIT                     = (1<<17),// valid East Velocity
-    GNSS_LOCATION_INFO_UP_VEL_BIT                       = (1<<18),// valid Up Velocity
-    GNSS_LOCATION_INFO_NORTH_VEL_UNC_BIT                = (1<<19),// valid North Velocity Uncertainty
-    GNSS_LOCATION_INFO_EAST_VEL_UNC_BIT                 = (1<<20),// valid East Velocity Uncertainty
-    GNSS_LOCATION_INFO_UP_VEL_UNC_BIT                   = (1<<21),// valid Up Velocity Uncertainty
-    GNSS_LOCATION_INFO_LEAP_SECONDS_BIT                 = (1<<22),// valid leap seconds
-    GNSS_LOCATION_INFO_TIME_UNC_BIT                     = (1<<23),// valid time uncertainty
-    GNSS_LOCATION_INFO_NUM_SV_USED_IN_POSITION_BIT      = (1<<24), // number of SV used in position
-    GNSS_LOCATION_INFO_CALIBRATION_CONFIDENCE_BIT       = (1<<25), // valid sensor cal confidence
-    GNSS_LOCATION_INFO_CALIBRATION_STATUS_BIT           = (1<<26), // valid sensor cal status
-    GNSS_LOCATION_INFO_OUTPUT_ENG_TYPE_BIT              = (1<<27), // valid output engine type
-    GNSS_LOCATION_INFO_OUTPUT_ENG_MASK_BIT              = (1<<28), // valid output engine mask
+    // Navigation data has pitch rate
+    LOCATION_NAV_DATA_HAS_PITCH_RATE_BIT     = (1<<0),
+    // Navigation data has body pitch rate uncertainty
+    LOCATION_NAV_DATA_HAS_PITCH_RATE_UNC_BIT = (1<<1),
+    // Navigation data has body roll
+    LOCATION_NAV_DATA_HAS_ROLL_BIT           = (1<<2),
+    // Navigation data has body roll uncertainty
+    LOCATION_NAV_DATA_HAS_ROLL_UNC_BIT       = (1<<3),
+    // Navigation data has body rate roll
+    LOCATION_NAV_DATA_HAS_ROLL_RATE_BIT      = (1<<4),
+    // Navigation data has body roll rate uncertainty
+    LOCATION_NAV_DATA_HAS_ROLL_RATE_UNC_BIT  = (1<<5),
+    // Navigation data has body yaw
+    LOCATION_NAV_DATA_HAS_YAW_BIT            = (1<<6),
+    // Navigation data has body roll uncertainty
+    LOCATION_NAV_DATA_HAS_YAW_UNC_BIT        = (1<<7)
+} GnssLocationPosDataBitsExt;
+
+typedef uint64_t GnssLocationInfoFlagMask;
+typedef enum {
+    GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT      = (1<<0),  // altitude mean sea level
+    GNSS_LOCATION_INFO_DOP_BIT                          = (1<<1),  // pdop, hdop, and vdop
+    GNSS_LOCATION_INFO_MAGNETIC_DEVIATION_BIT           = (1<<2),  // magnetic deviation
+    GNSS_LOCATION_INFO_HOR_RELIABILITY_BIT              = (1<<3),  // horizontal reliability
+    GNSS_LOCATION_INFO_VER_RELIABILITY_BIT              = (1<<4),  // vertical reliability
+    GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MAJOR_BIT = (1<<5),  // elipsode semi major
+    GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MINOR_BIT = (1<<6),  // elipsode semi minor
+    GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_AZIMUTH_BIT    = (1<<7),  // accuracy elipsode azimuth
+    GNSS_LOCATION_INFO_GNSS_SV_USED_DATA_BIT            = (1<<8),  // svUsedInPosition,
+                                                                   //       numOfMeasReceived
+                                                                   //       and measUsageInfo
+    GNSS_LOCATION_INFO_NAV_SOLUTION_MASK_BIT            = (1<<9),  // navSolutionMask
+    GNSS_LOCATION_INFO_SV_SOURCE_INFO_BIT               = (1<<10), // LocSvInfoSource
+    GNSS_LOCATION_INFO_POS_DYNAMICS_DATA_BIT            = (1<<11), // position dynamics data &
+                                                                   //       Position Dynamics Ext
+    GNSS_LOCATION_INFO_EXT_DOP_BIT                      = (1<<12), // gdop, tdop
+    GNSS_LOCATION_INFO_NORTH_STD_DEV_BIT                = (1<<13), // North standard deviation
+    GNSS_LOCATION_INFO_EAST_STD_DEV_BIT                 = (1<<14), // East standard deviation
+    GNSS_LOCATION_INFO_NORTH_VEL_BIT                    = (1<<15), // North Velocity
+    GNSS_LOCATION_INFO_EAST_VEL_BIT                     = (1<<16), // East Velocity
+    GNSS_LOCATION_INFO_UP_VEL_BIT                       = (1<<17), // Up Velocity
+    GNSS_LOCATION_INFO_NORTH_VEL_UNC_BIT                = (1<<18), // North Velocity Uncertainty
+    GNSS_LOCATION_INFO_EAST_VEL_UNC_BIT                 = (1<<19), // East Velocity Uncertainty
+    GNSS_LOCATION_INFO_UP_VEL_UNC_BIT                   = (1<<20), // Up Velocity Uncertainty
+    GNSS_LOCATION_INFO_LEAP_SECONDS_BIT                 = (1<<21), // leap seconds
+    GNSS_LOCATION_INFO_TIME_UNC_BIT                     = (1<<22), // time uncertainty
+    GNSS_LOCATION_INFO_NUM_SV_USED_IN_POSITION_BIT      = (1<<23), // number of SV used in position
+    GNSS_LOCATION_INFO_CALIBRATION_CONFIDENCE_BIT       = (1<<24), // sensor cal confidence
+    GNSS_LOCATION_INFO_CALIBRATION_STATUS_BIT           = (1<<25), // sensor cal status
+    GNSS_LOCATION_INFO_OUTPUT_ENG_TYPE_BIT              = (1<<26), // output engine type
+    GNSS_LOCATION_INFO_OUTPUT_ENG_MASK_BIT              = (1<<27), // output engine mask
+    GNSS_LOCATION_INFO_CONFORMITY_INDEX_BIT             = (1<<28), // conformity index
+    GNSS_LOCATION_INFO_LLA_VRP_BASED_BIT                = (1<<29), // VRP-based lat/long/alt
+    GNSS_LOCATION_INFO_ENU_VELOCITY_VRP_BASED_BIT       = (1<<30), // VRP-based east/north/up vel
+    GNSS_LOCATION_INFO_DR_SOLUTION_STATUS_MASK_BIT      = (1ULL<<31), // Valid DR solution status
+    GNSS_LOCATION_INFO_ALTITUDE_ASSUMED_BIT             = (1ULL<<32), // Valid altitude assumed
+    GNSS_LOCATION_INFO_SESSION_STATUS_BIT               = (1ULL<<33), // session status
 } GnssLocationInfoFlagBits;
 
 typedef enum {
@@ -200,7 +236,8 @@
     GEOFENCE_STATUS_AVAILABILE_YES,
 } GeofenceStatusAvailable;
 
-typedef uint32_t LocationCapabilitiesMask;
+// Set of masks for Modem and QWES capabilities.
+typedef uint64_t LocationCapabilitiesMask;
 typedef enum {
     // supports startTracking API with minInterval param
     LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT           = (1<<0),
@@ -228,8 +265,92 @@
     LOCATION_CAPABILITIES_AGPM_BIT                          = (1<<11),
     // support location privacy
     LOCATION_CAPABILITIES_PRIVACY_BIT                       = (1<<12),
+    // support measurement corrections
+    LOCATION_CAPABILITIES_MEASUREMENTS_CORRECTION_BIT       = (1<<13),
+    // support Robust Location
+    LOCATION_CAPABILITIES_CONFORMITY_INDEX_BIT               = (1<<14),
+    // support precise location edgnss
+    LOCATION_CAPABILITIES_EDGNSS_BIT                        = (1<<15),
+    // Modem supports Carrier Phase for Precise Positioning
+    // Measurement Engine (PPME).
+    LOCATION_CAPABILITIES_QWES_CARRIER_PHASE_BIT            = (1<<16),
+    // Modem supports SV Polynomial for tightly coupled external
+    // DR support. This is a Standalone Feature.
+    LOCATION_CAPABILITIES_QWES_SV_POLYNOMIAL_BIT            = (1<<17),
+    // Modem supports SV Ephemeris for tightly coupled external
+    // PPE engines. This is a Standalone Feature.
+    LOCATION_CAPABILITIES_QWES_SV_EPHEMERIS_BIT            = (1<<18),
+    // Modem supports GNSS Single Frequency feature. This is a
+    // Standalone Feature.
+    LOCATION_CAPABILITIES_QWES_GNSS_SINGLE_FREQUENCY        = (1<<19),
+    // Modem supports GNSS Multi Frequency feature. Multi Frequency
+    // enables Single frequency also.
+    LOCATION_CAPABILITIES_QWES_GNSS_MULTI_FREQUENCY         = (1<<20),
+    // This mask indicates VPe license bundle is enabled. VEPP
+    // bundle include Carrier Phase and SV Polynomial features.
+    LOCATION_CAPABILITIES_QWES_VPE                          = (1<<21),
+    // This mask indicates support for CV2X Location basic features.
+    // This bundle includes features for GTS Time & Freq, C-TUNC
+    // (Constrained Time uncertainity.
+    LOCATION_CAPABILITIES_QWES_CV2X_LOCATION_BASIC          = (1<<22),
+    // This mask indicates support for CV2X Location premium features.
+    // This bundle includes features for CV2X Location Basic features,
+    // QDR3 feature, and PACE. (Position Assisted Clock Estimator.
+    LOCATION_CAPABILITIES_QWES_CV2X_LOCATION_PREMIUM         = (1<<23),
+    // This mask indicates that PPE (Precise Positioning Engine)
+    // library is enabled or Precise Positioning Framework (PPF)
+    // is available. This bundle includes features for Carrier
+    // Phase and SV Ephermeris.
+    LOCATION_CAPABILITIES_QWES_PPE                          = (1<<24),
+    // This mask indicates QDR2_C license bundle is enabled. This
+    // bundle includes features for SV Polynomial.
+    LOCATION_CAPABILITIES_QWES_QDR2                         = (1<<25),
+    // This mask indicates QDR3_C license bundle is enabled. This
+    // bundle includes features for SV Polynomial.
+    LOCATION_CAPABILITIES_QWES_QDR3                         = (1<<26),
 } LocationCapabilitiesBits;
 
+typedef uint8_t LocationQwesFeatureType;
+typedef enum {
+    // Modem supports Carrier Phase for Precise Positioning
+    // Measurement Engine (PPME).
+    LOCATION_QWES_FEATURE_TYPE_CARRIER_PHASE                 = 1,
+    // Modem supports SV Polynomial for tightly coupled external
+    // DR support. This is a Standalone Feature.
+    LOCATION_QWES_FEATURE_TYPE_SV_POLYNOMIAL,
+    // Modem supports SV Ephemeris for tightly coupled external
+    // PPE support. This is a Standalone Feature.
+    LOCATION_QWES_FEATURE_TYPE_SV_EPH,
+    // Modem supports GNSS Single Frequency feature. This is a
+    // Standalone Feature.
+    LOCATION_QWES_FEATURE_TYPE_GNSS_SINGLE_FREQUENCY,
+    // Modem supports GNSS Multi Frequency feature. Multi Frequency
+    // enables Single frequency also.
+    LOCATION_QWES_FEATURE_TYPE_GNSS_MULTI_FREQUENCY,
+    // This indicates Time and Frequency status.
+    LOCATION_QWES_FEATURE_TYPE_TIME_FREQUENCY,
+    // This indicates Time Uncertainty  status.
+    LOCATION_QWES_FEATURE_TYPE_TIME_UNCERTAINTY,
+    // This indicates Clock Estimate status.
+    LOCATION_QWES_FEATURE_TYPE_CLOCK_ESTIMATE,
+    // This mask indicates that PPE (Precise Positioning Engine)
+    // library is enabled or Precise Positioning Framework (PPF)
+    // is available. This bundle includes features for Carrier
+    // Phase and SV Ephermeris.
+    LOCATION_QWES_FEATURE_TYPE_PPE,
+    // This indicates QDR2_C license bundle is enabled. This
+    // bundle includes features for SV Polynomial.
+    LOCATION_QWES_FEATURE_TYPE_QDR2,
+    // This indicates QDR3_C license bundle is enabled. This
+    // bundle includes features for SV Polynomial.
+    LOCATION_QWES_FEATURE_TYPE_QDR3,
+    // This indicates VEPP license bundle is enabled. VEPP
+    // bundle include Carrier Phase and SV Polynomial features.
+    LOCATION_QWES_FEATURE_TYPE_VPE,
+    // Max value
+    LOCATION_QWES_FEATURE_TYPE_MAX
+} LocationQwesFeatureTypes;
+
 typedef enum {
     LOCATION_TECHNOLOGY_TYPE_GNSS = 0,
 } LocationTechnologyType;
@@ -252,12 +373,14 @@
 } GnssConfigSuplVersion;
 
 // LTE Positioning Profile
+typedef uint16_t GnssConfigLppProfileMask;
 typedef enum {
-    GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE = 0,              // RRLP on LTE (Default)
-    GNSS_CONFIG_LPP_PROFILE_USER_PLANE,                   // LPP User Plane (UP) on LTE
-    GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE,                // LPP_Control_Plane (CP)
-    GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE, // Both LPP UP and CP
-} GnssConfigLppProfile;
+    GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE = 0,                         // RRLP on LTE (Default)
+    GNSS_CONFIG_LPP_PROFILE_USER_PLANE_BIT                 = (1<<0), // LPP User Plane (UP) on LTE
+    GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_BIT              = (1<<1), // LPP_Control_Plane (CP)
+    GNSS_CONFIG_LPP_PROFILE_USER_PLANE_OVER_NR5G_SA_BIT    = (1<<2), // LPP User Plane (UP) on LTE
+    GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_OVER_NR5G_SA_BIT = (1<<3), // LPP_Control_Plane (CP)
+} GnssConfigLppProfileBits;
 
 // Technology for LPPe Control Plane
 typedef uint16_t GnssConfigLppeControlPlaneMask;
@@ -318,6 +441,10 @@
     GNSS_CONFIG_FLAGS_SUPL_MODE_BIT                        = (1<<9),
     GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT               = (1<<10),
     GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT      = (1<<11),
+    GNSS_CONFIG_FLAGS_ROBUST_LOCATION_BIT                  = (1<<12),
+    GNSS_CONFIG_FLAGS_MIN_GPS_WEEK_BIT                     = (1<<13),
+    GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT                 = (1<<14),
+    GNSS_CONFIG_FLAGS_CONSTELLATION_SECONDARY_BAND_BIT     = (1<<15),
 } GnssConfigFlagsBits;
 
 typedef enum {
@@ -385,6 +512,7 @@
     GNSS_SV_OPTIONS_HAS_ALMANAC_BIT             = (1<<1),
     GNSS_SV_OPTIONS_USED_IN_FIX_BIT             = (1<<2),
     GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT   = (1<<3),
+    GNSS_SV_OPTIONS_HAS_GNSS_SIGNAL_TYPE_BIT    = (1<<4)
 } GnssSvOptionsBits;
 
 typedef enum {
@@ -459,6 +587,11 @@
     GNSS_MEASUREMENTS_DATA_MULTIPATH_INDICATOR_BIT          = (1<<15),
     GNSS_MEASUREMENTS_DATA_SIGNAL_TO_NOISE_RATIO_BIT        = (1<<16),
     GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT       = (1<<17),
+    GNSS_MEASUREMENTS_DATA_FULL_ISB_BIT                     = (1<<18),
+    GNSS_MEASUREMENTS_DATA_FULL_ISB_UNCERTAINTY_BIT         = (1<<19),
+    GNSS_MEASUREMENTS_DATA_SATELLITE_ISB_BIT                = (1<<20),
+    GNSS_MEASUREMENTS_DATA_SATELLITE_ISB_UNCERTAINTY_BIT    = (1<<21),
+    GNSS_MEASUREMENTS_DATA_CYCLE_SLIP_COUNT_BIT             = (1<<22),
 } GnssMeasurementsDataFlagsBits;
 
 typedef uint32_t GnssMeasurementsStateMask;
@@ -483,6 +616,15 @@
     GNSS_MEASUREMENTS_STATE_2ND_CODE_LOCK_BIT         = (1<<16),
 } GnssMeasurementsStateBits;
 
+typedef uint16_t GnssSingleSatCorrectionMask;
+typedef enum {
+    GNSS_MEAS_CORR_UNKNOWN_BIT                     = 0,
+    GNSS_MEAS_CORR_HAS_SAT_IS_LOS_PROBABILITY_BIT  = (1 << 0),
+    GNSS_MEAS_CORR_HAS_EXCESS_PATH_LENGTH_BIT      = (1 << 1),
+    GNSS_MEAS_CORR_HAS_EXCESS_PATH_LENGTH_UNC_BIT  = (1 << 2),
+    GNSS_MEAS_CORR_HAS_REFLECTING_PLANE_BIT        = (1 << 3),
+} GnssSingleSatCorrectionBits;
+
 typedef enum {
     GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_UNKNOWN = 0,
     GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_PRESENT,
@@ -500,6 +642,7 @@
     GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_BIT                        = (1<<6),
     GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_UNCERTAINTY_BIT            = (1<<7),
     GNSS_MEASUREMENTS_CLOCK_FLAGS_HW_CLOCK_DISCONTINUITY_COUNT_BIT = (1<<8),
+    GNSS_MEASUREMENTS_CLOCK_FLAGS_ELAPSED_REAL_TIME_BIT            = (1<<9),
 } GnssMeasurementsClockFlagsBits;
 
 typedef uint32_t GnssAidingDataSvMask;
@@ -527,7 +670,9 @@
     GNSS_AIDING_DATA_SV_TYPE_BEIDOU_BIT   = (1<<3),
     GNSS_AIDING_DATA_SV_TYPE_GALILEO_BIT  = (1<<4),
     GNSS_AIDING_DATA_SV_TYPE_NAVIC_BIT    = (1<<5),
+    GNSS_AIDING_DATA_SV_TYPE_MAX          = (1<<6),
 } GnssAidingDataSvTypeBits;
+#define GNSS_AIDING_DATA_SV_TYPE_MASK_ALL (GNSS_AIDING_DATA_SV_TYPE_MAX-1)
 
 /* Gnss constellation type mask */
 typedef uint16_t GnssConstellationTypeMask;
@@ -538,7 +683,7 @@
     GNSS_CONSTELLATION_TYPE_BEIDOU_BIT   = (1<<3),
     GNSS_CONSTELLATION_TYPE_GALILEO_BIT  = (1<<4),
     GNSS_CONSTELLATION_TYPE_SBAS_BIT     = (1<<5),
-    GNSS_CONSTELLATION_TYPE_NAVIC_BIT    = (1<<6)
+    GNSS_CONSTELLATION_TYPE_NAVIC_BIT    = (1<<6),
 } GnssConstellationTypeBits;
 
 #define GNSS_CONSTELLATION_TYPE_MASK_ALL\
@@ -624,7 +769,7 @@
     GNSS_LOC_SV_SYSTEM_QZSS                   = 6,
     /**< QZSS satellite. */
     GNSS_LOC_SV_SYSTEM_NAVIC                  = 7,
-    /**< QZSS satellite. */
+    /**< NAVIC satellite. */
     GNSS_LOC_SV_SYSTEM_MAX                    = 7,
     /**< Max enum of valid SV system. */
 } Gnss_LocSvSystemEnumType;
@@ -657,10 +802,22 @@
 typedef enum {
     STANDARD_POSITIONING_ENGINE = (1 << 0),
     DEAD_RECKONING_ENGINE       = (1 << 1),
-    PRECISE_POSITIONING_ENGINE  = (1 << 2)
+    PRECISE_POSITIONING_ENGINE  = (1 << 2),
+    VP_POSITIONING_ENGINE  = (1 << 3)
 } PositioningEngineBits;
 #define POSITION_ENGINE_MASK_ALL \
-        (STANDARD_POSITIONING_ENGINE|DEAD_RECKONING_ENGINE|PRECISE_POSITIONING_ENGINE)
+        (STANDARD_POSITIONING_ENGINE|DEAD_RECKONING_ENGINE| \
+        PRECISE_POSITIONING_ENGINE|VP_POSITIONING_ENGINE)
+
+/** Specify the position engine running state. <br/> */
+enum LocEngineRunState {
+    /** Request the position engine to be put into resume state.
+     *  <br/> */
+    LOC_ENGINE_RUN_STATE_PAUSE   = 1,
+    /** Request the position engine to be put into resume state.
+     *  <br/> */
+    LOC_ENGINE_RUN_STATE_RESUME   = 2,
+};
 
 typedef uint64_t GnssDataMask;
 typedef enum {
@@ -710,11 +867,17 @@
     GnssAidingDataCommonMask mask; // bitwise OR of GnssAidingDataCommonBits
 } GnssAidingDataCommon;
 
+typedef uint32_t DrEngineAidingDataMask;
+typedef enum {
+    DR_ENGINE_AIDING_DATA_CALIBRATION_BIT = (1<<0), // Calibration data for DRE engine
+} DrEngineAidingDataBits;
+
 typedef struct {
     bool deleteAll;              // if true, delete all aiding data and ignore other params
     GnssAidingDataSv sv;         // SV specific aiding data
     GnssAidingDataCommon common; // common aiding data
-    PositioningEngineMask posEngineMask; // engines to perform the delete operation on.
+    DrEngineAidingDataMask dreAidingDataMask;// aiding data mask for dr engine
+    PositioningEngineMask posEngineMask;     // engines to perform the delete operation on.
 } GnssAidingData;
 
 typedef uint16_t DrCalibrationStatusMask;
@@ -744,14 +907,18 @@
     float verticalAccuracy;  // in meters
     float speedAccuracy;     // in meters/second
     float bearingAccuracy;   // in degrees (0 to 359.999)
+    float conformityIndex;   // in range [0, 1]
     LocationTechnologyMask techMask;
-    LocationSpoofMask      spoofMask;
+    LocationSpoofMask spoofMask;
+    uint64_t elapsedRealTime;    // in ns
+    uint64_t elapsedRealTimeUnc; // in ns
 } Location;
 
 typedef enum {
     LOC_REQ_ENGINE_FUSED_BIT = (1<<0),
     LOC_REQ_ENGINE_SPE_BIT   = (1<<1),
     LOC_REQ_ENGINE_PPE_BIT   = (1<<2),
+    LOC_REQ_ENGINE_VPE_BIT   = (1<<3)
 } LocReqEngineTypeMask;
 
 typedef enum {
@@ -760,6 +927,7 @@
     LOC_OUTPUT_ENGINE_SPE     = 1,
     /** This is the GNSS fix with correction PPP/RTK correction */
     LOC_OUTPUT_ENGINE_PPE     = 2,
+    LOC_OUTPUT_ENGINE_VPE = 3,
     LOC_OUTPUT_ENGINE_COUNT,
 } LocOutputEngineType;
 
@@ -882,14 +1050,11 @@
     GnssSignalTypeMask gnssSignalType;
    /** Specifies GNSS Constellation Type */
     Gnss_LocSvSystemEnumType gnssConstellation;
-    /**  GNSS SV ID.
-     For GPS:      1 to 32
-     For GLONASS:  65 to 96. When slot-number to SV ID mapping is unknown, set as 255.
-     For SBAS:     120 to 151
-     For QZSS-L1CA:193 to 197
-     For BDS:      201 to 237
-     For GAL:      301 to 336
-     For NAVIC:    401 to 414  */
+    /** Unique SV Identifier.
+     *  For SV Range of supported constellation, please refer to
+     *  the comment section of svId in GnssSv.
+     *  For GLONASS:  When slot-number to SV ID mapping is unknown, set as 255.
+     */
     uint16_t gnssSvId;
 } GnssMeasUsageInfo;
 
@@ -911,6 +1076,18 @@
 } GnssLocationPositionDynamics;
 
 typedef struct {
+    GnssLocationPosDataMaskExt bodyFrameDataMask; // Contains Ext Body frame LocPosDataMask bits
+    float pitchRate;      // Body pitch rate (Radians/second)
+    float pitchRateUnc;   // Uncertainty of pitch rate (Radians/second)
+    float roll;           // Roll of body frame. Clockwise positive. (radian
+    float rollUnc;        // Uncertainty of Roll, 68% confidence level (radian)
+    float rollRate;       // Roll rate of body frame. Clockwise positive. (radian/second)
+    float rollRateUnc;    // Uncertainty of Roll rate, 68% confidence level (radian/second)
+    float yaw;            // Yaw of body frame. Clockwise positive (radian)
+    float yawUnc;         // Uncertainty of Yaw, 68% confidence level (radian)
+} GnssLocationPositionDynamicsExt;
+
+typedef struct {
     /** Validity mask for below fields */
     GnssSystemTimeStructTypeFlags validityMask;
     /** Extended week number at reference tick.
@@ -999,6 +1176,22 @@
     SystemTimeStructUnion u;
 } GnssSystemTime;
 
+typedef uint32_t DrSolutionStatusMask;
+#define VEHICLE_SENSOR_SPEED_INPUT_DETECTED (1<<0)
+#define VEHICLE_SENSOR_SPEED_INPUT_USED     (1<<1)
+
+typedef struct {
+    double latitude;  // in degree
+    double longitude; // in degree
+    float altitude;  // altitude wrt to ellipsoid
+} LLAInfo;
+
+enum loc_sess_status {
+    LOC_SESS_SUCCESS,
+    LOC_SESS_INTERMEDIATE,
+    LOC_SESS_FAILURE
+};
+
 typedef struct {
     uint32_t size;                      // set to sizeof(GnssLocationInfo)
     Location location;                  // basic locaiton info, latitude, longitude, and etc
@@ -1026,7 +1219,6 @@
     uint16_t numSvUsedInPosition;
     GnssLocationSvUsedInPosition svUsedInPosition;// Gnss sv used in position data
     GnssLocationNavSolutionMask navSolutionMask;  // Nav solution mask to indicate sbas corrections
-    GnssLocationPosTechMask posTechMask;          // Position technology used in computing this fix
     GnssLocationPositionDynamics bodyFrameData;   // Body Frame Dynamics: 4wayAcceleration and
                                                   // pitch set with validity
     GnssSystemTime gnssSystemTime;            // GNSS System Time
@@ -1040,12 +1232,27 @@
     // location engine type. When the fix. when the type is set to
     // LOC_ENGINE_SRC_FUSED, the fix is the propagated/aggregated
     // reports from all engines running on the system (e.g.:
-    // DR/SPE/PPE). To check which location engine contributes to
+    // DR/SPE/PPE/VPE). To check which location engine contributes to
     // the fused output, check for locOutputEngMask.
     LocOutputEngineType locOutputEngType;
     // when loc output eng type is set to fused, this field
     // indicates the set of engines contribute to the fix.
     PositioningEngineMask locOutputEngMask;
+    // When robust location is enabled, this field
+    // will how well the various input data considered for
+    // navigation solution conform to expectations.
+    // Range: 0 (least conforming) to 1 (most conforming)
+    float conformityIndex;
+    GnssLocationPositionDynamicsExt bodyFrameDataExt;   // Additional Body Frame Dynamics
+    // VRR-based latitude/longitude/altitude
+    LLAInfo llaVRPBased;
+    // VRR-based east, north, and up velocity
+    float enuVelocityVRPBased[3];
+    DrSolutionStatusMask drSolutionStatusMask;
+    // true: altitude is assumed, false: altitude is calculated
+    bool altitudeAssumed;
+    // location session status
+    loc_sess_status sessionStatus;
 } GnssLocationInfoNotification;
 
 typedef struct {
@@ -1061,16 +1268,49 @@
     char extras[GNSS_NI_MESSAGE_ID_MAX];
 } GnssNiNotification;
 
+// carrier frequency of the signal tracked
+#define GPS_L1CA_CARRIER_FREQUENCY      (1575420000.0)
+#define GPS_L1C_CARRIER_FREQUENCY       (1575420000.0)
+#define GPS_L2C_L_CARRIER_FREQUENCY     (1227600000.0)
+#define GPS_L5_Q_CARRIER_FREQUENCY      (1176450000.0)
+#define GLONASS_G1_CARRIER_FREQUENCY    (1602000000.0)
+#define GLONASS_G2_CARRIER_FREQUENCY    (1246000000.0)
+#define GALILEO_E1_C_CARRIER_FREQUENCY  (1575420000.0)
+#define GALILEO_E5A_Q_CARRIER_FREQUENCY (1176450000.0)
+#define GALILEO_E5B_Q_CARRIER_FREQUENCY (1207140000.0)
+#define BEIDOU_B1_I_CARRIER_FREQUENCY   (1561098000.0)
+#define BEIDOU_B1C_CARRIER_FREQUENCY    (1575420000.0)
+#define BEIDOU_B2_I_CARRIER_FREQUENCY   (1207140000.0)
+#define BEIDOU_B2A_I_CARRIER_FREQUENCY  (1176450000.0)
+#define BEIDOU_B2A_Q_CARRIER_FREQUENCY  (1176450000.0)
+#define QZSS_L1CA_CARRIER_FREQUENCY     (1575420000.0)
+#define QZSS_L1S_CARRIER_FREQUENCY      (1575420000.0)
+#define QZSS_L2C_L_CARRIER_FREQUENCY    (1227600000.0)
+#define QZSS_L5_Q_CARRIER_FREQUENCY     (1176450000.0)
+#define SBAS_L1_CA_CARRIER_FREQUENCY    (1575420000.0)
+#define NAVIC_L5_CARRIER_FREQUENCY      (1176450000.0)
+
 typedef struct {
     uint32_t size;       // set to sizeof(GnssSv)
-    uint16_t svId;     // Unique Identifier
-    GnssSvType type;   // type of SV (GPS, SBAS, GLONASS, QZSS, BEIDOU, GALILEO)
+    // Unique SV Identifier.
+    // SV Range for supported constellation is specified as below:
+    //    - For GPS:     1 to 32
+    //    - For GLONASS: 65 to 96
+    //    - For SBAS:    120 to 158 and 183 to 191
+    //    - For QZSS:    193 to 197
+    //    - For BDS:     201 to 263
+    //    - For GAL:     301 to 336
+    //    - For NAVIC:   401 to 414
+    uint16_t svId;
+    GnssSvType type;   // type of SV (GPS, SBAS, GLONASS, QZSS, BEIDOU, GALILEO, NAVIC)
     float cN0Dbhz;     // signal strength
     float elevation;   // elevation of SV (in degrees)
     float azimuth;     // azimuth of SV (in degrees)
     GnssSvOptionsMask gnssSvOptionsMask; // Bitwise OR of GnssSvOptionsBits
     float carrierFrequencyHz; // carrier frequency of the signal tracked
     GnssSignalTypeMask gnssSignalTypeMask; // Specifies GNSS signal type
+    double basebandCarrierToNoiseDbHz; // baseband signal strength
+    uint16_t  gloFrequency; // GLONASS Frequency channel number
 } GnssSv;
 
 struct GnssConfigSetAssistanceServer {
@@ -1091,8 +1331,13 @@
 };
 
 typedef struct {
-    uint32_t size;                               // set to sizeof(GnssMeasurementsData)
-    GnssMeasurementsDataFlagsMask flags;       // bitwise OR of GnssMeasurementsDataFlagsBits
+    // set to sizeof(GnssMeasurementsData)
+    uint32_t size;
+    // bitwise OR of GnssMeasurementsDataFlagsBits
+    GnssMeasurementsDataFlagsMask flags;
+    // Unique SV Identifier
+    // For SV Range of supported constellation,
+    // please refer to the comment section of svId in GnssSv.
     int16_t svId;
     GnssSvType svType;
     double timeOffsetNs;
@@ -1114,9 +1359,58 @@
     double agcLevelDb;
     GnssMeasurementsCodeType codeType;
     char otherCodeTypeName[GNSS_MAX_NAME_LENGTH];
+    double basebandCarrierToNoiseDbHz;
+    GnssSignalTypeMask gnssSignalType;
+    double fullInterSignalBiasNs;
+    double fullInterSignalBiasUncertaintyNs;
+    double satelliteInterSignalBiasNs;
+    double satelliteInterSignalBiasUncertaintyNs;
+    int16_t gloFrequency;
+    uint8_t cycleSlipCount;
 } GnssMeasurementsData;
 
 typedef struct {
+    GnssSvType svType;
+    float carrierFrequencyHz;
+    GnssMeasurementsCodeType codeType;
+    char otherCodeTypeName[GNSS_MAX_NAME_LENGTH];
+} GnssMeasurementsSignalType;
+
+typedef struct {
+    uint32_t size;                          // set to sizeof(GnssReflectingPlane)
+    double latitudeDegrees;
+    double longitudeDegrees;
+    double altitudeMeters;
+    double azimuthDegrees;
+} GnssReflectingPlane;
+
+typedef struct {
+    uint32_t size;                          // set to sizeof(GnssSingleSatCorrection)
+    GnssSingleSatCorrectionMask flags;
+    GnssSvType svType;
+    uint16_t svId;
+    float carrierFrequencyHz;
+    float probSatIsLos;
+    float excessPathLengthMeters;
+    float excessPathLengthUncertaintyMeters;
+    GnssReflectingPlane reflectingPlane;
+} GnssSingleSatCorrection;
+
+typedef struct {
+    uint32_t size;                          // set to sizeof(GnssMeasurementCorrections)
+    double latitudeDegrees;
+    double longitudeDegrees;
+    double altitudeMeters;
+    double horizontalPositionUncertaintyMeters;
+    double verticalPositionUncertaintyMeters;
+    uint64_t toaGpsNanosecondsOfWeek;
+    std::vector<GnssSingleSatCorrection> satCorrections;
+    bool hasEnvironmentBearing;
+    float environmentBearingDegrees;
+    float environmentBearingUncertaintyDegrees;
+} GnssMeasurementCorrections;
+
+typedef struct {
     uint32_t size;                          // set to sizeof(GnssMeasurementsClock)
     GnssMeasurementsClockFlagsMask flags; // bitwise OR of GnssMeasurementsClockFlagsBits
     int16_t leapSecond;
@@ -1128,6 +1422,9 @@
     double driftNsps;
     double driftUncertaintyNsps;
     uint32_t hwClockDiscontinuityCount;
+    GnssMeasurementsSignalType referenceSignalTypeForIsb;
+    uint64_t elapsedRealTime;    // in ns
+    uint64_t elapsedRealTimeUnc; // in ns
 } GnssMeasurementsClock;
 
 typedef struct {
@@ -1163,7 +1460,9 @@
 struct GnssSvIdSource{
     uint32_t size;              // set to sizeof(GnssSvIdSource)
     GnssSvType constellation;   // constellation for the sv to blacklist
-    GnssSvId svId;             // sv id to blacklist
+    GnssSvId svId;              // Unique SV Identifier,
+                                // For SV Range of supported constellation,
+                                // please refer to the comment section of svId in GnssSv.
 };
 inline bool operator ==(GnssSvIdSource const& left, GnssSvIdSource const& right) {
     return left.size == right.size &&
@@ -1171,7 +1470,7 @@
 }
 
 #define GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK ((uint64_t)0xFFFFFFFFFFFFFFFF)
-typedef struct {
+struct GnssSvIdConfig {
     uint32_t size; // set to sizeof(GnssSvIdConfig)
 
     // GLONASS - SV 65 maps to bit 0
@@ -1196,7 +1495,95 @@
 #define GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH 39
 #define GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID    183
     uint64_t sbasBlacklistSvMask;
-} GnssSvIdConfig;
+
+    //Navic - SV 401 maps to bit 0
+#define GNSS_SV_CONFIG_NAVIC_INITIAL_SV_ID 401
+    uint64_t navicBlacklistSvMask;
+
+    inline bool equals(const GnssSvIdConfig& inConfig) {
+        if ((inConfig.size == size) &&
+                (inConfig.gloBlacklistSvMask == gloBlacklistSvMask) &&
+                (inConfig.bdsBlacklistSvMask == bdsBlacklistSvMask) &&
+                (inConfig.qzssBlacklistSvMask == qzssBlacklistSvMask) &&
+                (inConfig.galBlacklistSvMask == galBlacklistSvMask) &&
+                (inConfig.sbasBlacklistSvMask == sbasBlacklistSvMask) &&
+                (inConfig.navicBlacklistSvMask == navicBlacklistSvMask)) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+};
+
+// Specify the valid mask for robust location configure
+// defined in GnssConfigRobustLocation.
+enum GnssConfigRobustLocationValidMask {
+    // GnssConfigRobustLocation has valid enabled field.
+    GNSS_CONFIG_ROBUST_LOCATION_ENABLED_VALID_BIT          = (1<<0),
+    // GnssConfigRobustLocation has valid enabledForE911 field.
+    GNSS_CONFIG_ROBUST_LOCATION_ENABLED_FOR_E911_VALID_BIT = (1<<1),
+    // GnssConfigRobustLocation has valid version field.
+    GNSS_CONFIG_ROBUST_LOCATION_VERSION_VALID_BIT          = (1<<2),
+};
+
+struct GnssConfigRobustLocationVersion {
+    // Major version number
+    uint8_t major;
+    // Minor version number
+    uint16_t minor;
+    inline bool equals(const GnssConfigRobustLocationVersion& version) const {
+        return (version.major == major && version.minor == minor);
+    }
+};
+
+// specify the robust location configuration used by modem GNSS engine
+struct GnssConfigRobustLocation {
+   GnssConfigRobustLocationValidMask validMask;
+   bool enabled;
+   bool enabledForE911;
+   GnssConfigRobustLocationVersion version;
+
+   inline bool equals(const GnssConfigRobustLocation& config) const {
+        if (config.validMask == validMask &&
+            config.enabled == enabled &&
+            config.enabledForE911 == enabledForE911 &&
+            config.version.equals(version)) {
+            return true;
+        }
+        return false;
+    }
+};
+
+/* Mask indicating enabled or disabled constellations and
+   secondary frequency.*/
+typedef uint64_t GnssSvTypesMask;
+typedef enum {
+    GNSS_SV_TYPES_MASK_GLO_BIT   = (1<<0),
+    GNSS_SV_TYPES_MASK_BDS_BIT   = (1<<1),
+    GNSS_SV_TYPES_MASK_QZSS_BIT  = (1<<2),
+    GNSS_SV_TYPES_MASK_GAL_BIT   = (1<<3),
+    GNSS_SV_TYPES_MASK_NAVIC_BIT = (1<<4),
+    GNSS_SV_TYPES_MASK_GPS_BIT   = (1<<5),
+} GnssSvTypesMaskBits;
+#define GNSS_SV_TYPES_MASK_ALL \
+    (GNSS_SV_TYPES_MASK_GPS_BIT|GNSS_SV_TYPES_MASK_GLO_BIT|GNSS_SV_TYPES_MASK_BDS_BIT|\
+     GNSS_SV_TYPES_MASK_QZSS_BIT|GNSS_SV_TYPES_MASK_GAL_BIT|GNSS_SV_TYPES_MASK_NAVIC_BIT)
+
+/* This SV Type config is injected directly to GNSS Adapter
+ * bypassing Location API */
+struct GnssSvTypeConfig{
+    uint32_t size; // set to sizeof(GnssSvTypeConfig)
+    // Enabled Constellations
+    GnssSvTypesMask enabledSvTypesMask;
+    // Disabled Constellations
+    GnssSvTypesMask blacklistedSvTypesMask;
+
+    inline bool equals (const GnssSvTypeConfig& inConfig) const {
+        return ((inConfig.size == size) &&
+                (inConfig.enabledSvTypesMask == enabledSvTypesMask) &&
+                (inConfig.blacklistedSvTypesMask == blacklistedSvTypesMask));
+    }
+};
 
 struct GnssConfig{
     uint32_t size;  // set to sizeof(GnssConfig)
@@ -1204,7 +1591,7 @@
     GnssConfigGpsLock gpsLock;
     GnssConfigSuplVersion suplVersion;
     GnssConfigSetAssistanceServer assistanceServer;
-    GnssConfigLppProfile lppProfile;
+    GnssConfigLppProfileMask lppProfileMask;
     GnssConfigLppeControlPlaneMask lppeControlPlaneMask;
     GnssConfigLppeUserPlaneMask lppeUserPlaneMask;
     GnssConfigAGlonassPositionProtocolMask aGlonassPositionProtocolMask;
@@ -1213,13 +1600,17 @@
     GnssConfigSuplModeMask suplModeMask; //bitwise OR of GnssConfigSuplModeBits
     std::vector<GnssSvIdSource> blacklistedSvIds;
     uint32_t emergencyExtensionSeconds;
+    GnssConfigRobustLocation robustLocationConfig;
+    uint16_t minGpsWeek;
+    uint8_t minSvElevation;
+    GnssSvTypeConfig secondaryBandConfig;
 
     inline bool equals(const GnssConfig& config) {
         if (flags == config.flags &&
                 gpsLock == config.gpsLock &&
                 suplVersion == config.suplVersion &&
                 assistanceServer.equals(config.assistanceServer) &&
-                lppProfile == config.lppProfile &&
+                lppProfileMask == config.lppProfileMask &&
                 lppeControlPlaneMask == config.lppeControlPlaneMask &&
                 lppeUserPlaneMask == config.lppeUserPlaneMask &&
                 aGlonassPositionProtocolMask == config.aGlonassPositionProtocolMask &&
@@ -1227,7 +1618,11 @@
                 suplEmergencyServices == config.suplEmergencyServices &&
                 suplModeMask == config.suplModeMask  &&
                 blacklistedSvIds == config.blacklistedSvIds &&
-                emergencyExtensionSeconds == config.emergencyExtensionSeconds) {
+                emergencyExtensionSeconds == config.emergencyExtensionSeconds &&
+                robustLocationConfig.equals(config.robustLocationConfig) &&
+                minGpsWeek == config.minGpsWeek &&
+                minSvElevation == config.minSvElevation &&
+                secondaryBandConfig.equals(config.secondaryBandConfig)) {
             return true;
         }
         return false;
@@ -1253,7 +1648,11 @@
 } GnssDebugTime;
 
 typedef struct {
-    uint32_t size;                        // set to sizeof
+    // set to sizeof
+    uint32_t size;
+    // Unique SV Identifier
+    // For SV Range of supported constellation,
+    // please refer to the comment section of svId in GnssSv.
     uint32_t                            svid;
     GnssSvType                          constellation;
     GnssEphemerisType                   mEphemerisType;
@@ -1323,25 +1722,10 @@
     LeapSecondSystemInfo   leapSecondSysInfo;
 };
 
-/* Mask indicating enabled or disabled constellations */
-typedef uint64_t GnssSvTypesMask;
-typedef enum {
-    GNSS_SV_TYPES_MASK_GLO_BIT  = (1<<0),
-    GNSS_SV_TYPES_MASK_BDS_BIT  = (1<<1),
-    GNSS_SV_TYPES_MASK_QZSS_BIT = (1<<2),
-    GNSS_SV_TYPES_MASK_GAL_BIT  = (1<<3),
-    GNSS_SV_TYPES_MASK_NAVIC_BIT  = (1<<4),
-} GnssSvTypesMaskBits;
-
-/* This SV Type config is injected directly to GNSS Adapter
- * bypassing Location API */
-typedef struct {
-    uint32_t size; // set to sizeof(GnssSvTypeConfig)
-    // Enabled Constellations
-    GnssSvTypesMask enabledSvTypesMask;
-    // Disabled Constellations
-    GnssSvTypesMask blacklistedSvTypesMask;
-} GnssSvTypeConfig;
+// Specify the set of terrestrial technologies
+enum TerrestrialTechMask {
+    TERRESTRIAL_TECH_GTP_WWAN = 1 << 0,
+};
 
 // Specify parameters related to lever arm
 struct LeverArmParams {
@@ -1383,6 +1767,103 @@
     LeverArmParams   veppImuToGnss;
 };
 
+// Specify vehicle body-to-Sensor mount parameters to be used
+// by dead reckoning positioning engine.
+struct BodyToSensorMountParams {
+    // The misalignment of the sensor board along the
+    // horizontal plane of the vehicle chassis measured looking
+    // from the vehicle to forward direction. In unit of degree.
+    float rollOffset;
+    // The misalignment along the horizontal plane of the vehicle
+    // chassis measured looking from the vehicle to the right
+    // side. Positive pitch indicates vehicle is inclined such
+    // that forward wheels are at higher elevation than rear
+    // wheels. In unit of degree.
+    float yawOffset;
+    // The angle between the vehicle forward direction and the
+    // sensor axis as seen from the top of the vehicle, and
+    // measured in counterclockwise direction. In unit of degree.
+    float pitchOffset;
+    // Single uncertainty number that may be the largest of the
+    // roll, pitch and yaw offset uncertainties.
+    float offsetUnc;
+};
+
+typedef uint64_t DeadReckoningEngineConfigValidMask;
+// Specify the valid mask for the configuration paramters of
+// dead reckoning position engine.
+enum DeadReckoningEngineConfigValidBit {
+    // DeadReckoningEngineConfig has valid
+    // DeadReckoningEngineConfig::DeadReckoningEngineConfig.
+    BODY_TO_SENSOR_MOUNT_PARAMS_BIT    = (1<<0),
+    // DeadReckoningEngineConfig has valid
+    //  DeadReckoningEngineConfig::vehicleSpeedScaleFactor.
+    VEHICLE_SPEED_SCALE_FACTOR_BIT     = (1<<1),
+    // DeadReckoningEngineConfig has valid
+    //  DeadReckoningEngineConfig::vehicleSpeedScaleFactorUnc.
+    VEHICLE_SPEED_SCALE_FACTOR_UNC_BIT = (1<<2),
+    // DeadReckoningEngineConfig has valid
+    //  DeadReckoningEngineConfig::gyroScaleFactor.
+    GYRO_SCALE_FACTOR_BIT              = (1<<3),
+    // DeadReckoningEngineConfig has valid
+    // DeadReckoningEngineConfig::gyroScaleFactorUnc.
+    GYRO_SCALE_FACTOR_UNC_BIT          = (1<<4),
+};
+
+// Specify the configuration parameters for the dead reckoning
+//  position engine
+struct DeadReckoningEngineConfig{
+    // Specify the valid fields in the config.
+    DeadReckoningEngineConfigValidMask validMask;
+    // Body to sensor mount parameters for use by dead reckoning
+    //  positioning engine
+    BodyToSensorMountParams bodyToSensorMountParams;
+
+    // Vehicle Speed Scale Factor configuration input for the dead
+    // reckoning positioning engine. The multiplicative scale
+    // factor is applied to received Vehicle Speed value (in m/s)
+    // to obtain the true Vehicle Speed.
+    //
+    // Range is [0.9 to 1.1].
+    //
+    // Note: The scale factor is specific to a given vehicle
+    // make & model.
+    float vehicleSpeedScaleFactor;
+    // Vehicle Speed Scale Factor Uncertainty (68% confidence)
+    // configuration input for the dead reckoning positioning
+    // engine.
+    //
+    // Range is [0.0 to 0.1].
+    //
+    // Note: The scale factor unc is specific to a given vehicle
+    // make & model.
+    float vehicleSpeedScaleFactorUnc;
+
+    // Gyroscope Scale Factor configuration input for the dead
+    // reckoning positioning engine. The multiplicative scale
+    // factor is applied to received gyroscope value to obtain the
+    // true value.
+    //
+    // Range is [0.9 to 1.1].
+    //
+    // Note: The scale factor is specific to the Gyroscope sensor
+    // and typically derived from either sensor data-sheet or
+    // from actual calibration.
+    float gyroScaleFactor;
+
+    // Gyroscope Scale Factor uncertainty (68% confidence)
+    // configuration input for the dead reckoning positioning
+    // engine.
+    //
+    // Range is [0.0 to 0.1].
+    // engine.
+    //
+    // Note: The scale factor unc is specific to the make & model
+    // of Gyroscope sensor and typically derived from either
+    // sensor data-sheet or from actual calibration.
+    float gyroScaleFactorUnc;
+};
+
 /* Provides the capabilities of the system
    capabilities callback is called once soon after createInstance is called */
 typedef std::function<void(
@@ -1496,7 +1977,8 @@
 
 /* Provides the current GNSS configuration to the client */
 typedef std::function<void(
-    GnssConfig& config
+    uint32_t session_id,
+    const GnssConfig& config
 )> gnssConfigCallback;
 
 /* LocationSystemInfoCb is for receiving rare occuring location
@@ -1536,4 +2018,53 @@
     engineLocationsInfoCallback engineLocationsInfoCb;     // optional
 } LocationCallbacks;
 
+typedef struct {
+    uint32_t size;                        // set to sizeof
+    double x;
+    double xUncertainty;
+    double y;
+    double yUncertainty;
+    double z;
+    double zUncertainty;
+} GnssCoordinate;
+
+typedef struct {
+    uint32_t size;                        // set to sizeof
+    double carrierFrequencyMHz;
+    GnssCoordinate phaseCenterOffsetCoordinateMillimeters;
+    std::vector<std::vector<double>> phaseCenterVariationCorrectionMillimeters;
+    std::vector<std::vector<double>> phaseCenterVariationCorrectionUncertaintyMillimeters;
+    std::vector<std::vector<double>> signalGainCorrectionDbi;
+    std::vector<std::vector<double>> signalGainCorrectionUncertaintyDbi;
+} GnssAntennaInformation;
+
+typedef struct {
+    uint32_t size;                        // set to sizeof
+    bool requiresNmeaLocation;
+    std::string hostNameOrIp;    // null terminated string
+    std::string mountPoint;      // null terminated string
+    std::string username;        // null terminated string
+    std::string password;        // null terminated string
+    uint32_t port;
+    bool useSSL;
+} GnssNtripConnectionParams;
+
+typedef struct {
+    uint64_t meQtimer1;
+    uint64_t meQtimer2;
+    uint64_t meQtimer3;
+    uint64_t peQtimer1;
+    uint64_t peQtimer2;
+    uint64_t peQtimer3;
+    uint64_t smQtimer1;
+    uint64_t smQtimer2;
+    uint64_t smQtimer3;
+    uint64_t locMwQtimer;
+    uint64_t hlosQtimer1;
+    uint64_t hlosQtimer2;
+    uint64_t hlosQtimer3;
+    uint64_t hlosQtimer4;
+    uint64_t hlosQtimer5;
+} GnssLatencyInfo;
+
 #endif /* LOCATIONDATATYPES_H */
diff --git a/location/Makefile.am b/location/Makefile.am
index fccdf94..6a5a750 100644
--- a/location/Makefile.am
+++ b/location/Makefile.am
@@ -11,6 +11,10 @@
     LocationAPI.cpp \
     LocationAPIClientBase.cpp
 
+if USE_EXTERNAL_AP
+AM_CFLAGS += -DFEATURE_EXTERNAL_AP
+endif
+
 if USE_GLIB
 liblocation_api_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@
 liblocation_api_la_LDFLAGS = -lstdc++ -Wl,-z,defs -lpthread @GLIB_LIBS@ -shared -version-info 1:0:0
diff --git a/location/configure.ac b/location/configure.ac
index 39abb69..f8376f5 100644
--- a/location/configure.ac
+++ b/location/configure.ac
@@ -74,6 +74,19 @@
 
 AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes")
 
+# External AP
+AC_ARG_WITH([external_ap],
+    AC_HELP_STRING([--with-external_ap=@<:@dir@:>@],
+        [Using External Application Processor]),
+    [],
+    with_external_ap=no)
+
+if test "x$with_external_ap" != "xno"; then
+    CPPFLAGS="${CPPFLAGS} -DFEATURE_EXTERNAL_AP"
+fi
+
+AM_CONDITIONAL(USE_EXTERNAL_AP, test "x${with_external_ap}" = "xyes")
+
 AC_CONFIG_FILES([ \
         Makefile \
         location-api.pc \
diff --git a/location/location_interface.h b/location/location_interface.h
index 6edb911..69d4f0c 100644
--- a/location/location_interface.h
+++ b/location/location_interface.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -31,6 +31,7 @@
 
 #include <LocationAPI.h>
 #include <gps_extended_c.h>
+#include <functional>
 
 /* Used for callback to deliver GNSS energy consumed */
 /** @fn
@@ -62,7 +63,7 @@
     void (*setControlCallbacks)(LocationControlCallbacks& controlCallbacks);
     uint32_t (*enable)(LocationTechnologyType techType);
     void (*disable)(uint32_t id);
-    uint32_t* (*gnssUpdateConfig)(GnssConfig config);
+    uint32_t* (*gnssUpdateConfig)(const GnssConfig& config);
     uint32_t* (*gnssGetConfig)(GnssConfigFlagsMask config);
     void (*gnssUpdateSvTypeConfig)(GnssSvTypeConfig& config);
     void (*gnssGetSvTypeConfig)(GnssSvTypeConfigCallback& callback);
@@ -77,24 +78,39 @@
     void (*agpsDataConnFailed)(AGpsExtType agpsType);
     void (*getDebugReport)(GnssDebugReport& report);
     void (*updateConnectionStatus)(bool connected, int8_t type, bool roaming,
-                                   NetworkHandle networkHandle);
-    void (*odcpiInit)(const OdcpiRequestCallback& callback);
+                                   NetworkHandle networkHandle, std::string& apn);
+    void (*odcpiInit)(const OdcpiRequestCallback& callback, OdcpiPrioritytype priority);
     void (*odcpiInject)(const Location& location);
     void (*blockCPI)(double latitude, double longitude, float accuracy,
                      int blockDurationMsec, double latLonDiffThreshold);
     void (*getGnssEnergyConsumed)(GnssEnergyConsumedCallback energyConsumedCb);
     void (*enableNfwLocationAccess)(bool enable);
     void (*nfwInit)(const NfwCbInfo& cbInfo);
-    void (*getPowerStateChanges)(void* powerStateCb);
+    void (*getPowerStateChanges)(std::function<void(bool)> powerStateCb);
     void (*injectLocationExt)(const GnssLocationInfoNotification &locationInfo);
     void (*updateBatteryStatus)(bool charging);
     void (*updateSystemPowerState)(PowerStateType systemPowerState);
     uint32_t (*setConstrainedTunc) (bool enable, float tuncConstraint, uint32_t energyBudget);
     uint32_t (*setPositionAssistedClockEstimator) (bool enable);
-    uint32_t (*gnssUpdateSvConfig)(const GnssSvTypeConfig& svTypeConfig,
-                                   const GnssSvIdConfig& svIdConfig);
-    uint32_t (*gnssResetSvConfig)();
+    uint32_t (*gnssUpdateSvConfig)(const GnssSvTypeConfig& constellationEnablementConfig,
+                                   const GnssSvIdConfig&   blacklistSvConfig);
     uint32_t (*configLeverArm)(const LeverArmConfigInfo& configInfo);
+    bool (*measCorrInit)(const measCorrSetCapabilitiesCb setCapabilitiesCb);
+    bool (*measCorrSetCorrections)(const GnssMeasurementCorrections gnssMeasCorr);
+    void (*measCorrClose)();
+    uint32_t (*antennaInfoInit)(const antennaInfoCb antennaInfoCallback);
+    void (*antennaInfoClose) ();
+    uint32_t (*configRobustLocation)(bool enable, bool enableForE911);
+    uint32_t (*configMinGpsWeek)(uint16_t minGpsWeek);
+    uint32_t (*configDeadReckoningEngineParams)(const DeadReckoningEngineConfig& dreConfig);
+    void (*updateNTRIPGGAConsent)(bool consentAccepted);
+    void (*enablePPENtripStream)(const GnssNtripConnectionParams& params, bool enableRTKEngine);
+    void (*disablePPENtripStream)();
+    uint32_t (*gnssUpdateSecondaryBandConfig)(const GnssSvTypeConfig& secondaryBandConfig);
+    uint32_t (*gnssGetSecondaryBandConfig)();
+    void (*resetNetworkInfo)();
+    uint32_t (*configEngineRunState)(PositioningEngineMask engType,
+                                     LocEngineRunState engState);
 };
 
 struct BatchingInterface {
diff --git a/pla/Android.bp b/pla/Android.bp
new file mode 100644
index 0000000..70904c9
--- /dev/null
+++ b/pla/Android.bp
@@ -0,0 +1,16 @@
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_qcom_sm7250_gps_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-BSD
+    default_applicable_licenses: ["hardware_qcom_sm7250_gps_license"],
+}
+
+cc_library_headers {
+
+    name: "libloc_pla_headers",
+    export_include_dirs: ["android"],
+    vendor: true,
+}
diff --git a/pla/Android.mk b/pla/Android.mk
deleted file mode 100644
index a57861d..0000000
--- a/pla/Android.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-GNSS_CFLAGS := \
-    -Werror \
-    -Wno-error=unused-parameter \
-    -Wno-error=macro-redefined \
-    -Wno-error=reorder \
-    -Wno-error=missing-braces \
-    -Wno-error=self-assign \
-    -Wno-error=enum-conversion \
-    -Wno-error=logical-op-parentheses \
-    -Wno-error=null-arithmetic \
-    -Wno-error=null-conversion \
-    -Wno-error=parentheses-equality \
-    -Wno-error=undefined-bool-conversion \
-    -Wno-error=tautological-compare \
-    -Wno-error=switch \
-    -Wno-error=date-time
-
-ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),)
-ifneq ($(BUILD_TINY_ANDROID),true)
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libloc_pla_headers
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/android
-include $(BUILD_HEADER_LIBRARY)
-
-endif # not BUILD_TINY_ANDROID
-endif # BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE
diff --git a/pla/android/loc_pla.h b/pla/android/loc_pla.h
index 6104bfb..34cb591 100644
--- a/pla/android/loc_pla.h
+++ b/pla/android/loc_pla.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -31,7 +31,8 @@
 
 #ifdef __cplusplus
 #include <utils/SystemClock.h>
-#define uptimeMillis android::uptimeMillis
+#define uptimeMillis() android::uptimeMillis()
+#define elapsedRealtime() android::elapsedRealtime()
 #endif
 
 #ifdef __cplusplus
@@ -58,6 +59,36 @@
 #define LOC_PATH_APDR_CONF_STR     "/vendor/etc/apdr.conf"
 #define LOC_PATH_XTWIFI_CONF_STR   "/vendor/etc/xtwifi.conf"
 #define LOC_PATH_QUIPC_CONF_STR    "/vendor/etc/quipc.conf"
+#define LOC_PATH_ANT_CORR_STR      "/vendor/etc/gnss_antenna_info.conf"
+#define LOC_PATH_SLIM_CONF_STR     "/vendor/etc/slim.conf"
+#define LOC_PATH_VPE_CONF_STR      "/vendor/etc/vpeglue.conf"
+
+/*!
+ * @brief Function for memory block copy
+ *
+ * @param[out] p_Dest     Destination buffer.
+ * @param[in]  q_DestSize Destination buffer size.
+ * @param[in]  p_Src      Source buffer.
+ * @param[in]  q_SrcSize  Source buffer size.
+ *
+ * @return Number of bytes copied.
+ */
+static inline size_t memscpy (void *p_Dest, size_t q_DestSize, const void *p_Src, size_t q_SrcSize)
+{
+    size_t res = (q_DestSize < q_SrcSize) ? q_DestSize : q_SrcSize;
+    if (p_Dest && p_Src && q_DestSize > 0 && q_SrcSize > 0) {
+        memcpy(p_Dest, p_Src, res);
+    } else {
+        res = 0;
+    }
+    return res;
+}
+
+/*API for boot kpi marker prints  */
+inline int loc_boot_kpi_marker(const char * pFmt, ...)
+{
+    return -1;
+}
 
 #ifdef __cplusplus
 }
diff --git a/pla/oe/loc_pla.h b/pla/oe/loc_pla.h
index e795a23..268b6bf 100644
--- a/pla/oe/loc_pla.h
+++ b/pla/oe/loc_pla.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -37,16 +37,39 @@
 #include <sys/time.h>
 #include <time.h>
 
-inline int64_t uptimeMillis()
+#if defined(__GNUC__) && defined(__GNUC_PREREQ)
+#if __GNUC_PREREQ(6,0)
+    #pragma message "GNU C version is above 6"
+#else
+    #pragma message "GNU C version is less than 6"
+    #define NO_UNORDERED_SET_OR_MAP
+#endif
+#endif
+
+// use set/map instead of unordered_set/unordered_map for
+// older GCC versions
+#ifdef NO_UNORDERED_SET_OR_MAP
+#define unordered_set set
+#define unordered_map map
+#endif
+
+inline int64_t sysTimeMillis(int clock)
 {
     struct timespec ts;
     int64_t time_ms = 0;
-    clock_gettime(CLOCK_BOOTTIME, &ts);
+    clock_gettime(clock, &ts);
     time_ms += (ts.tv_sec * 1000000000LL);
     time_ms += ts.tv_nsec + 500000LL;
     return time_ms / 1000000LL;
 }
 
+inline int64_t uptimeMillis() {
+    return sysTimeMillis(CLOCK_MONOTONIC);
+}
+inline int64_t elapsedRealtime() {
+    return sysTimeMillis(CLOCK_BOOTTIME);
+}
+
 extern "C" {
 #endif
 
@@ -54,12 +77,18 @@
 #include <cutils/properties.h>
 #include <cutils/threads.h>
 #include <cutils/sched_policy.h>
+#else
+#define set_sched_policy(a, b)
 #endif /* FEATURE_EXTERNAL_AP */
 #include <pthread.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <string.h>
 #include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#define MAX_COMMAND_STR_LEN (255)
+#define BOOT_KPI_FILE "/sys/kernel/debug/bootkpi/kpi_values"
 #ifndef OFF_TARGET
 #include <glib.h>
 #define strlcat g_strlcat
@@ -82,6 +111,9 @@
 #define LOC_PATH_APDR_CONF_STR     "/etc/apdr.conf"
 #define LOC_PATH_XTWIFI_CONF_STR   "/etc/xtwifi.conf"
 #define LOC_PATH_QUIPC_CONF_STR    "/etc/quipc.conf"
+#define LOC_PATH_ANT_CORR_STR      "/etc/gnss_antenna_info.conf"
+#define LOC_PATH_SLIM_CONF_STR     "/etc/slim.conf"
+#define LOC_PATH_VPE_CONF_STR      "/etc/vpeglue.conf"
 
 #ifdef FEATURE_EXTERNAL_AP
 #define PROPERTY_VALUE_MAX 92
@@ -93,6 +125,49 @@
 }
 #endif /* FEATURE_EXTERNAL_AP */
 
+/*!
+ * @brief Function for memory block copy
+ *
+ * @param[out] p_Dest     Destination buffer.
+ * @param[in]  q_DestSize Destination buffer size.
+ * @param[in]  p_Src      Source buffer.
+ * @param[in]  q_SrcSize  Source buffer size.
+ *
+ * @return Number of bytes copied.
+ */
+static inline size_t memscpy (void *p_Dest, size_t q_DestSize, const void *p_Src, size_t q_SrcSize)
+{
+    size_t res = (q_DestSize < q_SrcSize) ? q_DestSize : q_SrcSize;
+    if (p_Dest && p_Src && q_DestSize > 0 && q_SrcSize > 0) {
+        memcpy(p_Dest, p_Src, res);
+    } else {
+        res = 0;
+    }
+    return res;
+}
+
+/*API for boot kpi marker prints  */
+static inline int loc_boot_kpi_marker(const char * pFmt, ...)
+{
+    int result = 0;
+    FILE *stream = NULL;
+    char data[MAX_COMMAND_STR_LEN] = {};
+    char buf[MAX_COMMAND_STR_LEN] = {};
+
+    va_list ap;
+    va_start(ap, pFmt);
+    vsnprintf(&buf[0], sizeof(buf), pFmt, ap);
+    snprintf(data, sizeof(data), "echo -n %s > %s", buf, BOOT_KPI_FILE);
+    stream = popen(data, "w" );
+    if (NULL == stream) {
+        result = -1;
+    } else {
+        pclose(stream);
+    }
+    va_end(ap);
+    return result;
+}
+
 #ifdef __cplusplus
 }
 #endif /*__cplusplus */
diff --git a/utils/Android.bp b/utils/Android.bp
new file mode 100644
index 0000000..bdaba99
--- /dev/null
+++ b/utils/Android.bp
@@ -0,0 +1,64 @@
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_qcom_sm7250_gps_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-BSD
+    default_applicable_licenses: ["hardware_qcom_sm7250_gps_license"],
+}
+
+cc_library_shared {
+
+    name: "libgps.utils",
+    vendor: true,
+
+
+
+    //# Libs
+    shared_libs: [
+        "libdl",
+        "libutils",
+        "libcutils",
+        "liblog",
+        "libprocessgroup",
+    ],
+
+    srcs: [
+        "loc_log.cpp",
+        "loc_cfg.cpp",
+        "msg_q.c",
+        "linked_list.c",
+        "loc_target.cpp",
+        "LocHeap.cpp",
+        "LocTimer.cpp",
+        "LocThread.cpp",
+        "MsgTask.cpp",
+        "loc_misc_utils.cpp",
+        "loc_nmea.cpp",
+        "LocIpc.cpp",
+        "LogBuffer.cpp",
+    ],
+
+    cflags: [
+        "-fno-short-enums",
+        "-D_ANDROID_",
+    ] + GNSS_CFLAGS,
+
+    //# Includes
+    ldflags: ["-Wl,--export-dynamic"],
+
+    header_libs: [
+        "libutils_headers",
+        "libloc_pla_headers",
+        "liblocation_api_headers",
+    ],
+}
+
+cc_library_headers {
+
+    name: "libgps.utils_headers",
+    export_include_dirs: ["."],
+    vendor: true,
+}
diff --git a/utils/Android.mk b/utils/Android.mk
deleted file mode 100644
index 57d485d..0000000
--- a/utils/Android.mk
+++ /dev/null
@@ -1,69 +0,0 @@
-ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),)
-ifneq ($(BUILD_TINY_ANDROID),true)
-#Compile this library only for builds with the latest modem image
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-
-## Libs
-LOCAL_SHARED_LIBRARIES := \
-    libdl \
-    libutils \
-    libcutils \
-    liblog \
-    libprocessgroup
-
-LOCAL_SRC_FILES += \
-    loc_log.cpp \
-    loc_cfg.cpp \
-    msg_q.c \
-    linked_list.c \
-    loc_target.cpp \
-    LocHeap.cpp \
-    LocTimer.cpp \
-    LocThread.cpp \
-    MsgTask.cpp \
-    loc_misc_utils.cpp \
-    loc_nmea.cpp \
-    LocIpc.cpp \
-    LogBuffer.cpp
-
-# Flag -std=c++11 is not accepted by compiler when LOCAL_CLANG is set to true
-LOCAL_CFLAGS += \
-     -fno-short-enums \
-     -D_ANDROID_
-
-ifeq ($(TARGET_BUILD_VARIANT),user)
-   LOCAL_CFLAGS += -DTARGET_BUILD_VARIANT_USER
-endif
-
-LOCAL_LDFLAGS += -Wl,--export-dynamic
-
-## Includes
-LOCAL_HEADER_LIBRARIES := \
-    libutils_headers \
-    libloc_pla_headers \
-    liblocation_api_headers
-
-LOCAL_MODULE := libgps.utils
-LOCAL_SANITIZE += $(GNSS_SANITIZE)
-# activate the following line for debug purposes only, comment out for production
-#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_PRELINK_MODULE := false
-
-LOCAL_CFLAGS += $(GNSS_CFLAGS)
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libgps.utils_headers
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-include $(BUILD_HEADER_LIBRARY)
-
-endif # not BUILD_TINY_ANDROID
-endif # BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE
diff --git a/utils/LocHeap.cpp b/utils/LocHeap.cpp
index d667f14..4d047e4 100644
--- a/utils/LocHeap.cpp
+++ b/utils/LocHeap.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -28,6 +28,8 @@
  */
 #include <LocHeap.h>
 
+namespace loc_util {
+
 class LocHeapNode {
     friend class LocHeap;
 
@@ -266,6 +268,8 @@
     return locNode;
 }
 
+} // namespace loc_util
+
 #ifdef __LOC_UNIT_TEST__
 bool LocHeap::checkTree() {
     return ((NULL == mTree) || mTree->checkNodes());
@@ -274,81 +278,3 @@
     return (NULL == mTree) ? 0 : mTree->getSize();
 }
 #endif
-
-#ifdef __LOC_DEBUG__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-
-class LocHeapDebug : public LocHeap {
-public:
-    bool checkTree() {
-        return ((NULL == mTree) || mTree->checkNodes());
-    }
-
-    uint32_t getTreeSize() {
-        return (NULL == mTree) ? 0 : (mTree->getSize());
-    }
-};
-
-class LocHeapDebugData : public LocRankable {
-    const int mID;
-public:
-    LocHeapDebugData(int id) : mID(id) {}
-    inline virtual int ranks(LocRankable& rankable) {
-        LocHeapDebugData* testData = dynamic_cast<LocHeapDebugData*>(&rankable);
-        return testData->mID - mID;
-    }
-};
-
-// For Linux command line testing:
-// compilation: g++ -D__LOC_HOST_DEBUG__ -D__LOC_DEBUG__ -g -I. -I../../../../vendor/qcom/proprietary/gps-internal/unit-tests/fakes_for_host -I../../../../system/core/include LocHeap.cpp
-// test: valgrind --leak-check=full ./a.out 100
-int main(int argc, char** argv) {
-    srand(time(NULL));
-    int tries = atoi(argv[1]);
-    int checks = tries >> 3;
-    LocHeapDebug heap;
-    int treeSize = 0;
-
-    for (int i = 0; i < tries; i++) {
-        if (i % checks == 0 && !heap.checkTree()) {
-            printf("tree check failed before %dth op\n", i);
-        }
-        int r = rand();
-
-        if (r & 1) {
-            LocHeapDebugData* data = new LocHeapDebugData(r >> 1);
-            heap.push(dynamic_cast<LocRankable&>(*data));
-            treeSize++;
-        } else {
-            LocRankable* rankable = heap.pop();
-            if (rankable) {
-                delete rankable;
-            }
-            treeSize ? treeSize-- : 0;
-        }
-
-        printf("%s: %d == %d\n", (r&1)?"push":"pop", treeSize, heap.getTreeSize());
-        if (treeSize != heap.getTreeSize()) {
-            printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
-            tries = i+1;
-            break;
-        }
-    }
-
-    if (!heap.checkTree()) {
-        printf("!!!!!!!!!!tree check failed at the end after %d ops!!!!!!!\n", tries);
-    } else {
-        printf("success!\n");
-    }
-
-    for (LocRankable* data = heap.pop(); NULL != data; data = heap.pop()) {
-        delete data;
-    }
-
-    return 0;
-}
-
-#endif
diff --git a/utils/LocHeap.h b/utils/LocHeap.h
index b491948..bb62d6b 100644
--- a/utils/LocHeap.h
+++ b/utils/LocHeap.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -32,6 +32,8 @@
 #include <stddef.h>
 #include <string.h>
 
+namespace loc_util {
+
 // abstract class to be implemented by client to provide a rankable class
 class LocRankable {
 public:
@@ -93,4 +95,6 @@
 #endif
 };
 
+} // namespace loc_util
+
 #endif //__LOC_HEAP__
diff --git a/utils/LocIpc.cpp b/utils/LocIpc.cpp
index e9dbe9d..746ca87 100644
--- a/utils/LocIpc.cpp
+++ b/utils/LocIpc.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -139,8 +139,20 @@
     }
 public:
     inline LocIpcLocalSender(const char* name) : LocIpcSender(),
-            mSock(make_shared<Sock>((nullptr == name) ? -1 : (::socket(AF_UNIX, SOCK_DGRAM, 0)))),
+            mSock(nullptr),
             mAddr({.sun_family = AF_UNIX, {}}) {
+
+        int fd = -1;
+        if (nullptr != name) {
+            fd = ::socket(AF_UNIX, SOCK_DGRAM, 0);
+            if (fd >= 0) {
+                timeval timeout;
+                timeout.tv_sec = 2;
+                timeout.tv_usec = 0;
+                setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
+            }
+        }
+        mSock.reset(new Sock(fd));
         if (mSock != nullptr && mSock->isValid()) {
             snprintf(mAddr.sun_path, sizeof(mAddr.sun_path), "%s", name);
         }
@@ -301,7 +313,7 @@
             mAbortCalled(false),
             mLocIpc(locIpc),
             mIpcRecver(move(ipcRecver)) {}
-    inline bool run() override {
+    inline virtual bool run() override {
         if (mIpcRecver != nullptr) {
             mLocIpc.startBlockingListening(*(mIpcRecver.get()));
             if (!mAbortCalled) {
@@ -311,7 +323,7 @@
         // return false so the calling thread exits while loop
         return false;
     }
-    inline void abort() {
+    inline virtual void interrupt() override {
         mAbortCalled = true;
         if (mIpcRecver != nullptr) {
             mIpcRecver->abort();
@@ -323,8 +335,7 @@
     if (ipcRecver != nullptr && ipcRecver->isRecvable()) {
         std::string threadName("LocIpc-");
         threadName.append(ipcRecver->getName());
-        mRunnable = new LocIpcRunnable(*this, ipcRecver);
-        return mThread.start(threadName.c_str(), mRunnable);
+        return mThread.start(threadName.c_str(), make_shared<LocIpcRunnable>(*this, ipcRecver));
     } else {
         LOC_LOGe("ipcRecver is null OR ipcRecver->recvable() is fasle");
         return false;
@@ -344,10 +355,7 @@
 }
 
 void LocIpc::stopNonBlockingListening() {
-    if (mRunnable) {
-        mRunnable->abort();
-        mRunnable = nullptr;
-    }
+    mThread.stop();
 }
 
 void LocIpc::stopBlockingListening(LocIpcRecver& ipcRecver) {
@@ -376,15 +384,17 @@
     return (nullptr == creator) ? nullptr : creator(service, instance);
 }
 unique_ptr<LocIpcRecver> LocIpc::getLocIpcQrtrRecver(const shared_ptr<ILocIpcListener>& listener,
-                                                     int service, int instance) {
-    typedef unique_ptr<LocIpcRecver> (*creator_t)(const shared_ptr<ILocIpcListener>&, int, int);
+                                                     int service, int instance,
+                                                     const shared_ptr<LocIpcQrtrWatcher>& watcher) {
+    typedef unique_ptr<LocIpcRecver> (*creator_t)(const shared_ptr<ILocIpcListener>&, int, int,
+                                                  const shared_ptr<LocIpcQrtrWatcher>& watcher);
     static creator_t creator = (creator_t)dlGetSymFromLib(sLibQrtrHandle, sLibQrtrName,
 #ifdef USE_GLIB
-            "_ZN8loc_util22createLocIpcQrtrRecverERKSt10shared_ptrINS_15ILocIpcListenerEEii");
+            "_ZN8loc_util22createLocIpcQrtrRecverERKSt10shared_ptrINS_15ILocIpcListenerEEiiRKS0_INS_17LocIpcQrtrWatcherEE");
 #else
-            "_ZN8loc_util22createLocIpcQrtrRecverERKNSt3__110shared_ptrINS_15ILocIpcListenerEEEii");
+            "_ZN8loc_util22createLocIpcQrtrRecverERKNSt3__110shared_ptrINS_15ILocIpcListenerEEEiiRKNS1_INS_17LocIpcQrtrWatcherEEE");
 #endif
-    return (nullptr == creator) ? nullptr : creator(listener, service, instance);
+    return (nullptr == creator) ? nullptr : creator(listener, service, instance, watcher);
 }
 shared_ptr<LocIpcSender> LocIpc::getLocIpcInetTcpSender(const char* serverName, int32_t port) {
     return make_shared<LocIpcInetTcpSender>(serverName, port);
@@ -405,7 +415,13 @@
     typedef pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>> (*creator_t)(const shared_ptr<ILocIpcListener>&, int);
     static void* sLibEmuHandle = nullptr;
     static creator_t creator = (creator_t)dlGetSymFromLib(sLibEmuHandle, "libloc_emu.so",
-            "_ZN13QmiLocService41createLocIpcQmiLocServiceSenderRecverPairERKNSt3__110shared_ptrIN8loc_util15ILocIpcListenerEEEi");
+#ifdef USE_GLIB
+            "_ZN13QmiLocService41createLocIpcQmiLocServiceSenderRecverPair"\
+            "ERKSt10shared_ptrIN8loc_util15ILocIpcListenerEEi");
+#else
+            "_ZN13QmiLocService41createLocIpcQmiLocServiceSenderRecverPair"\
+            "ERKNSt3__110shared_ptrIN8loc_util15ILocIpcListenerEEEi");
+#endif
     return (nullptr == creator) ?
             make_pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>>(nullptr, nullptr) :
             creator(listener, instance);
diff --git a/utils/LocIpc.h b/utils/LocIpc.h
index d6f8d1d..b2586e6 100644
--- a/utils/LocIpc.h
+++ b/utils/LocIpc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -35,16 +35,16 @@
 #include <unistd.h>
 #include <sys/socket.h>
 #include <sys/un.h>
+#include <unordered_set>
+#include <mutex>
 #include <LocThread.h>
 
 using namespace std;
 
 namespace loc_util {
 
-
 class LocIpcRecver;
 class LocIpcSender;
-class LocIpcRunnable;
 
 class ILocIpcListener {
 protected:
@@ -56,10 +56,39 @@
     virtual void onReceive(const char* data, uint32_t len, const LocIpcRecver* recver) = 0;
 };
 
+class LocIpcQrtrWatcher {
+    const unordered_set<int> mServicesToWatch;
+    unordered_set<int> mClientsToWatch;
+    mutex mMutex;
+    inline bool isInWatch(const unordered_set<int>& idsToWatch, int id) {
+        return idsToWatch.find(id) != idsToWatch.end();
+    }
+protected:
+    inline virtual ~LocIpcQrtrWatcher() {}
+    inline LocIpcQrtrWatcher(unordered_set<int> servicesToWatch)
+            : mServicesToWatch(servicesToWatch) {}
+public:
+    enum class ServiceStatus { UP, DOWN };
+    inline bool isServiceInWatch(int serviceId) {
+        return isInWatch(mServicesToWatch, serviceId);
+    }
+    inline bool isClientInWatch(int nodeId) {
+        lock_guard<mutex> lock(mMutex);
+        return isInWatch(mClientsToWatch, nodeId);
+    }
+    inline void addClientToWatch(int nodeId) {
+        lock_guard<mutex> lock(mMutex);
+        mClientsToWatch.emplace(nodeId);
+    }
+    virtual void onServiceStatusChange(int sericeId, int instanceId, ServiceStatus status,
+                                       const LocIpcSender& sender) = 0;
+    inline virtual void onClientGone(int nodeId, int portId) {}
+    inline const unordered_set<int>& getServicesToWatch() { return mServicesToWatch; }
+};
 
 class LocIpc {
 public:
-    inline LocIpc() : mRunnable(nullptr) {}
+    inline LocIpc() = default;
     inline virtual ~LocIpc() {
         stopNonBlockingListening();
     }
@@ -82,9 +111,16 @@
     static unique_ptr<LocIpcRecver>
             getLocIpcInetTcpRecver(const shared_ptr<ILocIpcListener>& listener,
                                    const char* serverName, int32_t port);
+    inline static unique_ptr<LocIpcRecver>
+            getLocIpcQrtrRecver(const shared_ptr<ILocIpcListener>& listener,
+                                int service, int instance) {
+        const shared_ptr<LocIpcQrtrWatcher> qrtrWatcher = nullptr;
+        return getLocIpcQrtrRecver(listener, service, instance, qrtrWatcher);
+    }
     static unique_ptr<LocIpcRecver>
             getLocIpcQrtrRecver(const shared_ptr<ILocIpcListener>& listener,
-                                int service, int instance);
+                                int service, int instance,
+                                const shared_ptr<LocIpcQrtrWatcher>& qrtrWatcher);
 
     static pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>>
             getLocIpcQmiLocServiceSenderRecverPair(const shared_ptr<ILocIpcListener>& listener,
@@ -114,7 +150,6 @@
 
 private:
     LocThread mThread;
-    LocIpcRunnable *mRunnable;
 };
 
 /* this is only when client needs to implement Sender / Recver that are not already provided by
@@ -127,7 +162,6 @@
     virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t msgId) const = 0;
 public:
     virtual ~LocIpcSender() = default;
-    virtual void informRecverRestarted() {}
     inline bool isSendable() const { return isOperable(); }
     inline bool sendData(const uint8_t data[], uint32_t length, int32_t msgId) const {
         return isSendable() && (send(data, length, msgId) > 0);
@@ -135,6 +169,7 @@
     virtual unique_ptr<LocIpcRecver> getRecver(const shared_ptr<ILocIpcListener>& listener) {
         return nullptr;
     }
+    inline virtual void copyDestAddrFrom(const LocIpcSender& otherSender) {}
 };
 
 class LocIpcRecver {
diff --git a/utils/LocLoggerBase.h b/utils/LocLoggerBase.h
new file mode 100644
index 0000000..867b6e2
--- /dev/null
+++ b/utils/LocLoggerBase.h
@@ -0,0 +1,39 @@
+/* Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation, nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef LOC_LOGGER_BASE_H
+#define LOC_LOGGER_BASE_H
+
+namespace loc_util {
+class LocLoggerBase {
+public:
+    virtual void log() {}
+};
+}
+
+#endif
diff --git a/utils/LocSharedLock.h b/utils/LocSharedLock.h
index a7af35e..1ef2c57 100644
--- a/utils/LocSharedLock.h
+++ b/utils/LocSharedLock.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -49,9 +49,11 @@
     volatile std::atomic_int_least32_t* a = (volatile std::atomic_int_least32_t*)addr;
     return std::atomic_fetch_sub_explicit(a, 1, std::memory_order_release);
 }
-
 #endif /* FEATURE_EXTERNAL_AP */
- // This is a utility created for use cases such that there are more than
+
+namespace loc_util {
+
+// This is a utility created for use cases such that there are more than
 // one client who need to share the same lock, but it is not predictable
 // which of these clients is to last to go away. This shared lock deletes
 // itself when the last client calls its drop() method. To add a cient,
@@ -74,4 +76,6 @@
     inline void unlock() { pthread_mutex_unlock(&mMutex); }
 };
 
+} //namespace loc_util
+
 #endif //__LOC_SHARED_LOCK__
diff --git a/utils/LocThread.cpp b/utils/LocThread.cpp
index 568a6bb..3cac1f9 100644
--- a/utils/LocThread.cpp
+++ b/utils/LocThread.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -26,194 +26,75 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  */
+#include <sys/prctl.h>
 #include <LocThread.h>
 #include <string.h>
-#include <pthread.h>
+#include <string>
+#include <thread>
 #include <loc_pla.h>
 
+using std::weak_ptr;
+using std::shared_ptr;
+using std::thread;
+using std::string;
+
+namespace loc_util {
+
 class LocThreadDelegate {
-    LocRunnable* mRunnable;
-    bool mJoinable;
-    pthread_t mThandle;
-    pthread_mutex_t mMutex;
-    int mRefCount;
-    ~LocThreadDelegate();
-    LocThreadDelegate(LocThread::tCreate creator, const char* threadName,
-                      LocRunnable* runnable, bool joinable);
-    void destroy();
+    static const char defaultThreadName[];
+    weak_ptr<LocRunnable> mRunnable;
+    thread mThread;
+    LocThreadDelegate(const string tName, shared_ptr<LocRunnable> r);
 public:
-    static LocThreadDelegate* create(LocThread::tCreate creator,
-            const char* threadName, LocRunnable* runnable, bool joinable);
-    void stop();
-    // bye() is for the parent thread to go away. if joinable,
-    // parent must stop the spawned thread, join, and then
-    // destroy(); if detached, the parent can go straight
-    // ahead to destroy()
-    inline void bye() { mJoinable ? stop() : destroy(); }
-    inline bool isRunning() { return (NULL != mRunnable); }
-    static void* threadMain(void* arg);
+    ~LocThreadDelegate() {
+        shared_ptr<LocRunnable> runnable = mRunnable.lock();
+        if (nullptr != runnable) {
+            runnable->interrupt();
+        }
+    }
+    inline static LocThreadDelegate* create(const char* tName, shared_ptr<LocRunnable> runnable);
 };
 
-// it is important to note that internal members must be
-// initialized to values as if pthread_create succeeds.
-// This is to avoid the race condition between the threads,
-// once the thread is created, some of these values will
-// be check in the spawned thread, and must set correctly
-// then and there.
-// However, upon pthread_create failure, the data members
-// must be set to  indicate failure, e.g. mRunnable, and
-// threashold approprietly for destroy(), e.g. mRefCount.
-LocThreadDelegate::LocThreadDelegate(LocThread::tCreate creator,
-        const char* threadName, LocRunnable* runnable, bool joinable) :
-    mRunnable(runnable), mJoinable(joinable), mThandle((pthread_t)NULL),
-    mMutex(PTHREAD_MUTEX_INITIALIZER), mRefCount(2) {
+const char LocThreadDelegate::defaultThreadName[] = "LocThread";
 
-    // set up thread name, if nothing is passed in
-    if (!threadName) {
-        threadName = "LocThread";
-    }
+LocThreadDelegate* LocThreadDelegate::create(const char* tName, shared_ptr<LocRunnable> runnable) {
+    LocThreadDelegate* threadDelegate = nullptr;
 
-    // create the thread here, then if successful
-    // and a name is given, we set the thread name
-    if (creator) {
-        mThandle = creator(threadName, threadMain, this);
-    } else if (pthread_create(&mThandle, NULL, threadMain, this)) {
-        // pthread_create() failed
-        mThandle = (pthread_t)NULL;
-    }
+    if (nullptr != runnable) {
+        if (!tName) {
+            tName = defaultThreadName;
+        }
 
-    if (mThandle) {
-        // set thread name
         char lname[16];
-        int len = (sizeof(lname) > (strlen(threadName) + 1)) ?
-          (strlen(threadName)):(sizeof(lname) - 1);
-        memcpy(lname, threadName, len);
+        auto nameSize = strlen(tName) + 1;
+        int len = std::min(sizeof(lname), nameSize) - 1;
+        memcpy(lname, tName, len);
         lname[len] = 0;
-        // set the thread name here
-        pthread_setname_np(mThandle, lname);
 
-        // detach, if not joinable
-        if (!joinable) {
-            pthread_detach(mThandle);
-        }
-    } else {
-        // must set these values upon failure
-        mRunnable = NULL;
-        mJoinable = false;
-        mRefCount = 1;
-    }
-}
-
-inline
-LocThreadDelegate::~LocThreadDelegate() {
-    // at this point nothing should need done any more
-}
-
-// factory method so that we could return NULL upon failure
-LocThreadDelegate* LocThreadDelegate::create(LocThread::tCreate creator,
-        const char* threadName, LocRunnable* runnable, bool joinable) {
-    LocThreadDelegate* thread = NULL;
-    if (runnable) {
-        thread = new LocThreadDelegate(creator, threadName, runnable, joinable);
-        if (thread && !thread->isRunning()) {
-            thread->destroy();
-            thread = NULL;
-        }
+        threadDelegate = new LocThreadDelegate(lname, runnable);
     }
 
-    return thread;
+    return threadDelegate;
 }
 
-// The order is importang
-// NULLing mRunnalbe stops the while loop in threadMain()
-// join() if mJoinble must come before destroy() call, as
-// the obj must remain alive at this time so that mThandle
-// remains valud.
-void LocThreadDelegate::stop() {
-    // mRunnable and mJoinable are reset on different triggers.
-    // mRunnable may get nulled on the spawned thread's way out;
-    //           or here.
-    // mJouinable (if ever been true) gets falsed when client
-    //            thread triggers stop, with either a stop()
-    //            call or the client releases thread obj handle.
-    if (mRunnable) {
-        mRunnable = NULL;
-    }
-    if (mJoinable) {
-        mJoinable = false;
-        pthread_join(mThandle, NULL);
-    }
-    // call destroy() to possibly delete the obj
-    destroy();
-}
-
-// method for clients to call to release the obj
-// when it is a detached thread, the client thread
-// and the spawned thread can both try to destroy()
-// asynchronously. And we delete this obj when
-// mRefCount becomes 0.
-void LocThreadDelegate::destroy() {
-    // else case shouldn't happen, unless there is a
-    // leaking obj. But only our code here has such
-    // obj, so if we test our code well, else case
-    // will never happen
-    if (mRefCount > 0) {
-        // we need a flag on the stack
-        bool callDelete = false;
-
-        // critical section between threads
-        pthread_mutex_lock(&mMutex);
-        // last destroy() call
-        callDelete = (1 == mRefCount--);
-        pthread_mutex_unlock(&mMutex);
-
-        // upon last destroy() call we delete this obj
-        if (callDelete) {
-            delete this;
-        }
-    }
-}
-
-void* LocThreadDelegate::threadMain(void* arg) {
-    LocThreadDelegate* locThread = (LocThreadDelegate*)(arg);
-
-    if (locThread) {
-        LocRunnable* runnable = locThread->mRunnable;
-
-        if (runnable) {
-            if (locThread->isRunning()) {
+LocThreadDelegate::LocThreadDelegate(const string tName, shared_ptr<LocRunnable> runnable) :
+        mRunnable(runnable),
+        mThread([tName, runnable] {
+                prctl(PR_SET_NAME, tName.c_str(), 0, 0, 0);
                 runnable->prerun();
-            }
-
-            while (locThread->isRunning() && runnable->run());
-
-            if (locThread->isRunning()) {
+                while (runnable->run());
                 runnable->postrun();
-            }
+            }) {
 
-            // at this time, locThread->mRunnable may or may not be NULL
-            // NULL it just to be safe and clean, as we want the field
-            // in the released memory slot to be NULL.
-            locThread->mRunnable = NULL;
-            delete runnable;
-        }
-        locThread->destroy();
-    }
-
-    return NULL;
+    mThread.detach();
 }
 
-LocThread::~LocThread() {
-    if (mThread) {
-        mThread->bye();
-        mThread = NULL;
-    }
-}
 
-bool LocThread::start(tCreate creator, const char* threadName, LocRunnable* runnable, bool joinable) {
+
+bool LocThread::start(const char* tName, shared_ptr<LocRunnable> runnable) {
     bool success = false;
     if (!mThread) {
-        mThread = LocThreadDelegate::create(creator, threadName, runnable, joinable);
+        mThread = LocThreadDelegate::create(tName, runnable);
         // true only if thread is created successfully
         success = (NULL != mThread);
     }
@@ -221,46 +102,10 @@
 }
 
 void LocThread::stop() {
-    if (mThread) {
-        mThread->stop();
-        mThread = NULL;
+    if (nullptr != mThread) {
+        delete mThread;
+        mThread = nullptr;
     }
 }
 
-#ifdef __LOC_DEBUG__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-class LocRunnableTest1 : public LocRunnable {
-    int mID;
-public:
-    LocRunnableTest1(int id) : LocRunnable(), mID(id) {}
-    virtual bool run() {
-        printf("LocRunnableTest1: %d\n", mID++);
-        sleep(1);
-        return true;
-    }
-};
-
-// on linux command line:
-// compile: g++ -D__LOC_HOST_DEBUG__ -D__LOC_DEBUG__ -g -std=c++0x -I. -I../../../../vendor/qcom/proprietary/gps-internal/unit-tests/fakes_for_host -I../../../../system/core/include -lpthread LocThread.cpp
-// test detached thread: valgrind ./a.out 0
-// test joinable thread: valgrind ./a.out 1
-int main(int argc, char** argv) {
-    LocRunnableTest1 test(10);
-
-    LocThread thread;
-    thread.start("LocThreadTest", test, atoi(argv[1]));
-
-    sleep(10);
-
-    thread.stop();
-
-    sleep(5);
-
-    return 0;
-}
-
-#endif
+} // loc_util
diff --git a/utils/LocThread.h b/utils/LocThread.h
index 2a65d8f..c7ece87 100644
--- a/utils/LocThread.h
+++ b/utils/LocThread.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -30,14 +30,18 @@
 #define __LOC_THREAD__
 
 #include <stddef.h>
-#include <pthread.h>
+#include <memory>
+
+using std::shared_ptr;
+
+namespace loc_util {
 
 // abstract class to be implemented by client to provide a runnable class
 // which gets scheduled by LocThread
 class LocRunnable {
 public:
-    inline LocRunnable() {}
-    inline virtual ~LocRunnable() {}
+    inline LocRunnable() = default;
+    inline virtual ~LocRunnable() = default;
 
     // The method to be implemented by thread clients
     // and be scheduled by LocThread
@@ -52,6 +56,10 @@
     // The method to be run after thread loop (conditionally repeatedly)
     // calls run()
     inline virtual void postrun() {}
+
+    // The method to wake up the potential blocking thread
+    // no op if not applicable
+    inline virtual void interrupt() = 0;
 };
 
 // opaque class to provide service implementation.
@@ -63,12 +71,11 @@
     LocThreadDelegate* mThread;
 public:
     inline LocThread() : mThread(NULL) {}
-    virtual ~LocThread();
+    inline virtual ~LocThread() { stop(); }
 
-    typedef pthread_t (*tCreate)(const char* name, void* (*start)(void*), void* arg);
     // client starts thread with a runnable, which implements
     // the logics to fun in the created thread context.
-    // The thread could be either joinable or detached.
+    // The thread is always detached.
     // runnable is an obj managed by client. Client creates and
     //          frees it (but must be after stop() is called, or
     //          this LocThread obj is deleted).
@@ -76,17 +83,13 @@
     //          returns true. Else it is client's responsibility
     //          to delete the object
     // Returns 0 if success; false if failure.
-    bool start(tCreate creator, const char* threadName, LocRunnable* runnable, bool joinable = true);
-    inline bool start(const char* threadName, LocRunnable* runnable, bool joinable = true) {
-        return start(NULL, threadName, runnable, joinable);
-    }
+    bool start(const char* threadName, shared_ptr<LocRunnable> runnable);
 
-    // NOTE: if this is a joinable thread, this stop may block
-    // for a while until the thread is joined.
     void stop();
 
     // thread status check
     inline bool isRunning() { return NULL != mThread; }
 };
 
+} // loc_util
 #endif //__LOC_THREAD__
diff --git a/utils/LocTimer.cpp b/utils/LocTimer.cpp
index 93775d0..915cf54 100644
--- a/utils/LocTimer.cpp
+++ b/utils/LocTimer.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -48,6 +48,8 @@
 #define CLOCK_BOOTTIME_ALARM CLOCK_MONOTONIC
 #endif
 
+namespace loc_util {
+
 /*
 There are implementations of 5 classes in this file:
 LocTimer, LocTimerDelegate, LocTimerContainer, LocTimerPollTask, LocTimerWrapper
@@ -129,6 +131,21 @@
     void expire();
 };
 
+class TimerRunnable : public LocRunnable {
+    const int mFd;
+public:
+    inline TimerRunnable(const int fd) : mFd(fd) {}
+    // The method to be implemented by thread clients
+    // and be scheduled by LocThread
+    // This method will be repeated called until it returns false; or
+    // until thread is stopped.
+    virtual bool run() override;
+
+    // The method to wake up the potential blocking thread
+    // no op if not applicable
+    inline virtual void interrupt() { close(mFd); }
+};
+
 // This class implements the polling thread that epolls imer / alarm fds.
 // The LocRunnable::run() contains the actual polling.  The other methods
 // will be run in the caller's thread context to add / remove timer / alarm
@@ -140,19 +157,17 @@
 // having 1 fd per container of timer / alarm is such that, we may not need
 // to make a system call each time a timer / alarm is added / removed, unless
 // that changes the "soonest" time out of that of all the timers / alarms.
-class LocTimerPollTask : public LocRunnable {
+class LocTimerPollTask {
     // the epoll fd
     const int mFd;
-    // the thread that calls run() method
-    LocThread* mThread;
-    friend class LocThreadDelegate;
-    // dtor
-    ~LocTimerPollTask();
+    // the thread that calls TimerRunnable::run() method, where
+    // epoll_wait() is blocking and waiting for events..
+    LocThread mThread;
 public:
     // ctor
     LocTimerPollTask();
-    // this obj will be deleted once thread is deleted
-    void destroy();
+    // dtor
+    ~LocTimerPollTask() = default;
     // add a container of timers. Each contain has a unique device fd, i.e.
     // either timer or alarm fd, and a heap of timers / alarms. It is expected
     // that container would have written to the device fd with the soonest
@@ -164,9 +179,6 @@
     // remove a fd that is assciated with a container. The expectation is that
     // the atual timer would have been removed from the container.
     void removePoll(LocTimerContainer& timerContainer);
-    // The polling thread context will call this method. This is where
-    // epoll_wait() is blocking and waiting for events..
-    virtual bool run();
 };
 
 // Internal class of timer obj. It gets born when client calls LocTimer::start();
@@ -257,7 +269,7 @@
 MsgTask* LocTimerContainer::getMsgTaskLocked() {
     // it is cheap to check pointer first than locking mutext unconditionally
     if (!mMsgTask) {
-        mMsgTask = new MsgTask("LocTimerMsgTask", false);
+        mMsgTask = new MsgTask("LocTimerMsgTask");
     }
     return mMsgTask;
 }
@@ -313,7 +325,6 @@
 void LocTimerContainer::add(LocTimerDelegate& timer) {
     struct MsgTimerPush : public LocMsg {
         LocTimerContainer* mTimerContainer;
-        LocHeapNode* mTree;
         LocTimerDelegate* mTimer;
         inline MsgTimerPush(LocTimerContainer& container, LocTimerDelegate& timer) :
             LocMsg(), mTimerContainer(&container), mTimer(&timer) {}
@@ -398,39 +409,19 @@
 
 inline
 LocTimerPollTask::LocTimerPollTask()
-    : mFd(epoll_create(2)), mThread(new LocThread()) {
+    : mFd(epoll_create(2)), mThread() {
     // before a next call returens, a thread will be created. The run() method
     // could already be running in parallel. Also, since each of the objs
     // creates a thread, the container will make sure that there will be only
     // one of such obj for our timer implementation.
-    if (!mThread->start("LocTimerPollTask", this)) {
-        delete mThread;
-        mThread = NULL;
-    }
-}
-
-inline
-LocTimerPollTask::~LocTimerPollTask() {
-    // when fs is closed, epoll_wait() should fail run() should return false
-    // and the spawned thread should exit.
-    close(mFd);
-}
-
-void LocTimerPollTask::destroy() {
-    if (mThread) {
-        LocThread* thread = mThread;
-        mThread = NULL;
-        delete thread;
-    } else {
-        delete this;
-    }
+    mThread.start("LocTimerPollTask", std::make_shared<TimerRunnable>(mFd));
 }
 
 void LocTimerPollTask::addPoll(LocTimerContainer& timerContainer) {
     struct epoll_event ev;
     memset(&ev, 0, sizeof(ev));
 
-    ev.events = EPOLLIN | EPOLLWAKEUP;
+    ev.events = EPOLLIN;
     ev.data.fd = timerContainer.getTimerFd();
     // it is important that we set this context pointer with the input
     // timer container this is how we know which container should handle
@@ -447,7 +438,7 @@
 
 // The polling thread context will call this method. If run() method needs to
 // be repetitvely called, it must return true from the previous call.
-bool LocTimerPollTask::run() {
+bool TimerRunnable::run() {
     struct epoll_event ev[2];
 
     // we have max 2 descriptors to poll from
@@ -621,6 +612,14 @@
     }
 };
 
+} // namespace loc_util
+
+//////////////////////////////////////////////////////////////////////////
+// This section below wraps for the C style APIs
+//////////////////////////////////////////////////////////////////////////
+
+using loc_util::LocTimerWrapper;
+
 pthread_mutex_t LocTimerWrapper::mMutex = PTHREAD_MUTEX_INITIALIZER;
 
 void* loc_timer_start(uint64_t msec, loc_timer_callback cb_func,
@@ -647,107 +646,3 @@
         handle = NULL;
     }
 }
-
-//////////////////////////////////////////////////////////////////////////
-// This section above wraps for the C style APIs
-//////////////////////////////////////////////////////////////////////////
-
-#ifdef __LOC_DEBUG__
-
-double getDeltaSeconds(struct timespec from, struct timespec to) {
-    return (double)to.tv_sec + (double)to.tv_nsec / 1000000000
-        - from.tv_sec - (double)from.tv_nsec / 1000000000;
-}
-
-struct timespec getNow() {
-    struct timespec now;
-    clock_gettime(CLOCK_BOOTTIME, &now);
-    return now;
-}
-
-class LocTimerTest : public LocTimer, public LocRankable {
-    int mTimeOut;
-    const struct timespec mTimeOfBirth;
-    inline struct timespec getTimerWrapper(int timeout) {
-        struct timespec now;
-        clock_gettime(CLOCK_BOOTTIME, &now);
-        now.tv_sec += timeout;
-        return now;
-    }
-public:
-    inline LocTimerTest(int timeout) : LocTimer(), LocRankable(),
-            mTimeOut(timeout), mTimeOfBirth(getTimerWrapper(0)) {}
-    inline virtual int ranks(LocRankable& rankable) {
-        LocTimerTest* timer = dynamic_cast<LocTimerTest*>(&rankable);
-        return timer->mTimeOut - mTimeOut;
-    }
-    inline virtual void timeOutCallback() {
-        printf("timeOutCallback() - ");
-        deviation();
-    }
-    double deviation() {
-        struct timespec now = getTimerWrapper(0);
-        double delta = getDeltaSeconds(mTimeOfBirth, now);
-        printf("%lf: %lf\n", delta, delta * 100 / mTimeOut);
-        return delta / mTimeOut;
-    }
-};
-
-// For Linux command line testing:
-// compilation:
-//     g++ -D__LOC_HOST_DEBUG__ -D__LOC_DEBUG__ -g -I. -I../../../../system/core/include -o LocHeap.o LocHeap.cpp
-//     g++ -D__LOC_HOST_DEBUG__ -D__LOC_DEBUG__ -g -std=c++0x -I. -I../../../../system/core/include -lpthread -o LocThread.o LocThread.cpp
-//     g++ -D__LOC_HOST_DEBUG__ -D__LOC_DEBUG__ -g -I. -I../../../../system/core/include -o LocTimer.o LocTimer.cpp
-int main(int argc, char** argv) {
-    struct timespec timeOfStart=getNow();
-    srand(time(NULL));
-    int tries = atoi(argv[1]);
-    int checks = tries >> 3;
-    LocTimerTest** timerArray = new LocTimerTest*[tries];
-    memset(timerArray, NULL, tries);
-
-    for (int i = 0; i < tries; i++) {
-        int r = rand() % tries;
-        LocTimerTest* timer = new LocTimerTest(r);
-        if (timerArray[r]) {
-            if (!timer->stop()) {
-                printf("%lf:\n", getDeltaSeconds(timeOfStart, getNow()));
-                printf("ERRER: %dth timer, id %d, not running when it should be\n", i, r);
-                exit(0);
-            } else {
-                printf("stop() - %d\n", r);
-                delete timer;
-                timerArray[r] = NULL;
-            }
-        } else {
-            if (!timer->start(r, false)) {
-                printf("%lf:\n", getDeltaSeconds(timeOfStart, getNow()));
-                printf("ERRER: %dth timer, id %d, running when it should not be\n", i, r);
-                exit(0);
-            } else {
-                printf("stop() - %d\n", r);
-                timerArray[r] = timer;
-            }
-        }
-    }
-
-    for (int i = 0; i < tries; i++) {
-        if (timerArray[i]) {
-            if (!timerArray[i]->stop()) {
-                printf("%lf:\n", getDeltaSeconds(timeOfStart, getNow()));
-                printf("ERRER: %dth timer, not running when it should be\n", i);
-                exit(0);
-            } else {
-                printf("stop() - %d\n", i);
-                delete timerArray[i];
-                timerArray[i] = NULL;
-            }
-        }
-    }
-
-    delete[] timerArray;
-
-    return 0;
-}
-
-#endif
diff --git a/utils/LocTimer.h b/utils/LocTimer.h
index abc7f64..c883de2 100644
--- a/utils/LocTimer.h
+++ b/utils/LocTimer.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -33,6 +33,8 @@
 #include <stddef.h>
 #include <loc_pla.h>
 
+namespace loc_util {
+
 // opaque class to provide service implementation.
 class LocTimerDelegate;
 class LocSharedLock;
@@ -71,4 +73,6 @@
     virtual void timeOutCallback() = 0;
 };
 
+} // namespace loc_util
+
 #endif //__LOC_DELAY_H__
diff --git a/utils/LocUnorderedSetMap.h b/utils/LocUnorderedSetMap.h
index 8748134..7b25ad0 100644
--- a/utils/LocUnorderedSetMap.h
+++ b/utils/LocUnorderedSetMap.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2017, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -30,8 +30,15 @@
 #define __LOC_UNORDERDED_SETMAP_H__
 
 #include <algorithm>
-#include <unordered_set>
-#include <unordered_map>
+#include <loc_pla.h>
+
+#ifdef NO_UNORDERED_SET_OR_MAP
+    #include <set>
+    #include <map>
+#else
+    #include <unordered_set>
+    #include <unordered_map>
+#endif
 
 using std::unordered_set;
 using std::unordered_map;
@@ -55,7 +62,7 @@
 // *s1* and *s2* will be left with the intersect removed from them.
 template <typename T>
 static unordered_set<T> removeAndReturnInterset(unordered_set<T>& s1, unordered_set<T>& s2) {
-    unordered_set<T> common(0);
+    unordered_set<T> common = {};
     for (auto b = s2.begin(); b != s2.end(); b++) {
         auto a = find(s1.begin(), s1.end(), *b);
         if (a != s1.end()) {
@@ -73,7 +80,6 @@
 class LocUnorderedSetMap {
     unordered_map<KEY, unordered_set<VAL>> mMap;
 
-
     // Trim the VALs pointed to by *iter*, with everything that also exist in *rVals*.
     // If the set becomes empty, remove the map entry. *goneVals*, if not null, records
     // the trimmed VALs.
@@ -89,7 +95,9 @@
 
 public:
     inline LocUnorderedSetMap() {}
-    inline LocUnorderedSetMap(size_t size) : mMap(size) {}
+    inline LocUnorderedSetMap(size_t size) : LocUnorderedSetMap() {
+        mMap.get_allocator().allocate(size);
+    }
 
     inline bool empty() { return mMap.empty(); }
 
@@ -104,12 +112,12 @@
     // If the entry is not in the map, an empty set will be returned.
     inline unordered_set<VAL> getValSet(const KEY& key) {
         auto entry = mMap.find(key);
-        return (entry != mMap.end()) ? entry->second : unordered_set<VAL>(0);
+        return (entry != mMap.end()) ? entry->second : unordered_set<VAL>{};
     }
 
     // This gets all the KEYs from the map
     inline unordered_set<KEY> getKeys() {
-        unordered_set<KEY> keys(0);
+        unordered_set<KEY> keys = {};
         for (auto entry : mMap) {
             keys.insert(entry.first);
         }
@@ -128,6 +136,7 @@
                              unordered_set<KEY>* goneKeys, unordered_set<VAL>* goneVals) {
         trimOrRemove(keys, rVals, goneKeys, goneVals);
     }
+
     inline void trimOrRemove(unordered_set<KEY>& keys, const unordered_set<VAL>& rVals,
                              unordered_set<KEY>* goneKeys, unordered_set<VAL>* goneVals) {
         for (auto key : keys) {
@@ -161,6 +170,7 @@
                     unordered_set<KEY>* newKeys) {
         add(keys, newVals, newKeys);
     }
+
     inline void add(const unordered_set<KEY>& keys, const unordered_set<VAL>& newVals,
                     unordered_set<KEY>* newKeys) {
         for (auto key : keys) {
@@ -174,8 +184,7 @@
     // in effect removed from the keyed VAL set in the map entry.
     // This call would also remove those same VALs from *newVals*.
     inline unordered_set<VAL> update(const KEY& key, unordered_set<VAL>& newVals) {
-        unordered_set<VAL> goneVals(0);
-
+        unordered_set<VAL> goneVals = {};
         if (newVals.empty()) {
             mMap.erase(key);
         } else {
diff --git a/utils/LogBuffer.cpp b/utils/LogBuffer.cpp
index 1bb6f0f..c280c82 100644
--- a/utils/LogBuffer.cpp
+++ b/utils/LogBuffer.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2019 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2019 - 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -28,8 +28,13 @@
  */
 
 #include "LogBuffer.h"
-#include <utils/Log.h>
+#ifdef USE_GLIB
+#include <execinfo.h>
+#endif
 
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
 #define LOG_TAG "LocSvc_LogBuffer"
 
 namespace loc_util {
@@ -131,7 +136,7 @@
 void LogBuffer::registerSignalHandler() {
     ALOGE("Singal handler registered");
     mNewSigAction.sa_sigaction = &LogBuffer::signalHandler;
-    mNewSigAction.sa_flags = SA_SIGINFO;
+    mNewSigAction.sa_flags = SA_SIGINFO | SA_RESTART;
     sigemptyset(&mNewSigAction.sa_mask);
 
     sigaction(SIGINT, &mNewSigAction, &mOriSigAction[SIGINT]);
@@ -145,6 +150,23 @@
 void LogBuffer::signalHandler(const int code, siginfo_t *const si, void *const sc) {
     ALOGE("[Gnss Log buffer]Singal handler, signal ID: %d", code);
 
+#ifdef USE_GLIB
+    int nptrs;
+    void *buffer[100];
+    char **strings;
+
+    nptrs = backtrace(buffer, sizeof(buffer)/sizeof(*buffer));
+    strings = backtrace_symbols(buffer, nptrs);
+    if (strings != NULL) {
+        timespec tv;
+        clock_gettime(CLOCK_BOOTTIME, &tv);
+        uint64_t elapsedTime = (uint64_t)tv.tv_sec + (uint64_t)tv.tv_nsec/1000000000;
+        for (int i = 0; i < nptrs; i++) {
+            string s(strings[i]);
+            mInstance->append(s, 0, elapsedTime);
+        }
+    }
+#endif
     //Dump the log buffer to adb logcat
     mInstance->dumpToAdbLogcat();
 
diff --git a/utils/Makefile.am b/utils/Makefile.am
index 72c7872..ada504c 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -31,7 +31,8 @@
         loc_gps.h \
         log_util.h \
         LocSharedLock.h \
-        LocUnorderedSetMap.h
+        LocUnorderedSetMap.h\
+        LocLoggerBase.h
 
 libgps_utils_la_c_sources = \
         linked_list.c \
diff --git a/utils/MsgTask.cpp b/utils/MsgTask.cpp
index 73a77fd..6ef689a 100644
--- a/utils/MsgTask.cpp
+++ b/utils/MsgTask.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, 2015, 2017The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, 2015, 2017, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -36,41 +36,33 @@
 #include <loc_log.h>
 #include <loc_pla.h>
 
+namespace loc_util {
+
+class MTRunnable : public LocRunnable {
+    const void* mQ;
+public:
+    inline MTRunnable(const void* q) : mQ(q) {}
+    virtual ~MTRunnable();
+    // Overrides of LocRunnable methods
+    // This method will be repeated called until it returns false; or
+    // until thread is stopped.
+    virtual bool run() override;
+
+    // The method to be run before thread loop (conditionally repeatedly)
+    // calls run()
+    virtual void prerun() override;
+
+    // to interrupt the run() method and come out of that
+    virtual void interrupt() override;
+};
+
 static void LocMsgDestroy(void* msg) {
     delete (LocMsg*)msg;
 }
 
-MsgTask::MsgTask(LocThread::tCreate tCreator,
-                 const char* threadName, bool joinable) :
-    mQ(msg_q_init2()), mThread(new LocThread()) {
-    if (!mThread->start(tCreator, threadName, this, joinable)) {
-        delete mThread;
-        mThread = NULL;
-    }
-}
-
-MsgTask::MsgTask(const char* threadName, bool joinable) :
-    mQ(msg_q_init2()), mThread(new LocThread()) {
-    if (!mThread->start(threadName, this, joinable)) {
-        delete mThread;
-        mThread = NULL;
-    }
-}
-
-MsgTask::~MsgTask() {
-    msg_q_flush((void*)mQ);
-    msg_q_destroy((void**)&mQ);
-}
-
-void MsgTask::destroy() {
-    LocThread* thread = mThread;
-    msg_q_unblock((void*)mQ);
-    if (thread) {
-        mThread = NULL;
-        delete thread;
-    } else {
-        delete this;
-    }
+MsgTask::MsgTask(const char* threadName) :
+    mQ(msg_q_init2()), mThread() {
+    mThread.start(threadName, std::make_shared<MTRunnable>(mQ));
 }
 
 void MsgTask::sendMsg(const LocMsg* msg) const {
@@ -82,14 +74,27 @@
     }
 }
 
-void MsgTask::prerun() {
-#ifndef FEATURE_EXTERNAL_AP
-    // make sure we do not run in background scheduling group
-     set_sched_policy(gettid(), SP_FOREGROUND);
-#endif /* FEATURE_EXTERNAL_AP */
+void MsgTask::sendMsg(const std::function<void()> runnable) const {
+    struct RunMsg : public LocMsg {
+        const std::function<void()> mRunnable;
+    public:
+        inline RunMsg(const std::function<void()> runnable) : mRunnable(runnable) {}
+        ~RunMsg() = default;
+        inline virtual void proc() const override { mRunnable(); }
+    };
+    sendMsg(new RunMsg(runnable));
 }
 
-bool MsgTask::run() {
+void MTRunnable::interrupt() {
+    msg_q_unblock((void*)mQ);
+}
+
+void MTRunnable::prerun() {
+    // make sure we do not run in background scheduling group
+     set_sched_policy(gettid(), SP_FOREGROUND);
+}
+
+bool MTRunnable::run() {
     LocMsg* msg;
     msq_q_err_type result = msg_q_rcv((void*)mQ, (void **)&msg);
     if (eMSG_Q_SUCCESS != result) {
@@ -106,3 +111,10 @@
 
     return true;
 }
+
+MTRunnable::~MTRunnable() {
+    msg_q_flush((void*)mQ);
+    msg_q_destroy((void**)&mQ);
+}
+
+} // namespace loc_util
diff --git a/utils/MsgTask.h b/utils/MsgTask.h
index 9eb1f56..a8cce9e 100644
--- a/utils/MsgTask.h
+++ b/utils/MsgTask.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013,2015 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, 2015, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -29,8 +29,11 @@
 #ifndef __MSG_TASK__
 #define __MSG_TASK__
 
+#include <functional>
 #include <LocThread.h>
 
+namespace loc_util {
+
 struct LocMsg {
     inline LocMsg() {}
     inline virtual ~LocMsg() {}
@@ -38,30 +41,16 @@
     inline virtual void log() const {}
 };
 
-class MsgTask : public LocRunnable {
+class MsgTask {
     const void* mQ;
-    LocThread* mThread;
-    friend class LocThreadDelegate;
-protected:
-    virtual ~MsgTask();
+    LocThread mThread;
 public:
-    MsgTask(LocThread::tCreate tCreator, const char* threadName = NULL, bool joinable = true);
-    MsgTask(const char* threadName = NULL, bool joinable = true);
-    // this obj will be deleted once thread is deleted
-    void destroy();
+    ~MsgTask() = default;
+    MsgTask(const char* threadName = NULL);
     void sendMsg(const LocMsg* msg) const;
-    // Overrides of LocRunnable methods
-    // This method will be repeated called until it returns false; or
-    // until thread is stopped.
-    virtual bool run();
-
-    // The method to be run before thread loop (conditionally repeatedly)
-    // calls run()
-    virtual void prerun();
-
-    // The method to be run after thread loop (conditionally repeatedly)
-    // calls run()
-    inline virtual void postrun() {}
+    void sendMsg(const std::function<void()> runnable) const;
 };
 
+} //
+
 #endif //__MSG_TASK__
diff --git a/utils/gps_extended_c.h b/utils/gps_extended_c.h
index f4ad524..f368975 100644
--- a/utils/gps_extended_c.h
+++ b/utils/gps_extended_c.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -115,6 +115,9 @@
 #define LOC_POS_TECH_MASK_AFLT ((LocPosTechMask)0x00000040)
 #define LOC_POS_TECH_MASK_HYBRID ((LocPosTechMask)0x00000080)
 #define LOC_POS_TECH_MASK_PPE ((LocPosTechMask)0x00000100)
+#define LOC_POS_TECH_MASK_VEH ((LocPosTechMask)0x00000200)
+#define LOC_POS_TECH_MASK_VIS ((LocPosTechMask)0x00000400)
+
 
 enum loc_registration_mask_status {
     LOC_REGISTRATION_MASK_ENABLED,
@@ -132,7 +135,11 @@
     LOC_SUPPORTED_FEATURE_AGPM_V02, /**< Support AGPM feature */
     LOC_SUPPORTED_FEATURE_XTRA_INTEGRITY, /**< Support XTRA integrity */
     LOC_SUPPORTED_FEATURE_FDCL_2, /**< Support FDCL V2 */
-    LOC_SUPPORTED_FEATURE_LOCATION_PRIVACY /**< Support location privacy */
+    LOC_SUPPORTED_FEATURE_LOCATION_PRIVACY, /**< Support location privacy */
+    LOC_SUPPORTED_FEATURE_NAVIC, /**< Support NAVIC constellation */
+    LOC_SUPPORTED_FEATURE_MEASUREMENTS_CORRECTION, /**< Support measurements correction */
+    LOC_SUPPORTED_FEATURE_ROBUST_LOCATION, /**<  Support Robust Location feature */
+    LOC_SUPPORTED_FEATURE_EDGNSS /**< Support precise location dgnss */
 } loc_supported_feature_enum;
 
 typedef struct {
@@ -390,7 +397,30 @@
 #define GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE       0x2000000000
  /** GpsLocationExtended has the engine mask that indicates the
   *     set of engines contribute to the fix. */
-#define GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_MASK       0x4000000000
+#define GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_MASK              0x4000000000
+/** GpsLocationExtended has dgnss correction source */
+#define GPS_LOCATION_EXTENDED_HAS_DGNSS_CORRECTION_SOURCE_TYPE 0x8000000000
+/** GpsLocationExtended has dgnss correction source ID */
+#define GPS_LOCATION_EXTENDED_HAS_DGNSS_CORRECTION_SOURCE_ID   0x10000000000
+/** GpsLocationExtended has dgnss constellation usage   */
+#define GPS_LOCATION_EXTENDED_HAS_DGNSS_CONSTELLATION_USAGE    0x20000000000
+/** GpsLocationExtended has dgnss ref station Id */
+#define GPS_LOCATION_EXTENDED_HAS_DGNSS_REF_STATION_ID         0x40000000000
+/** GpsLocationExtended has dgnss data age */
+#define GPS_LOCATION_EXTENDED_HAS_DGNSS_DATA_AGE               0x80000000000
+ /** GpsLocationExtended has the conformityIndex computed from
+  *  robust location feature. */
+#define GPS_LOCATION_EXTENDED_HAS_CONFORMITY_INDEX            0x100000000000
+ /** GpsLocationExtended has the llaVRPased. */
+#define GPS_LOCATION_EXTENDED_HAS_LLA_VRP_BASED                0x200000000000
+/** GpsLocationExtended has the velocityVRPased. */
+#define GPS_LOCATION_EXTENDED_HAS_ENU_VELOCITY_LLA_VRP_BASED   0x400000000000
+/** GpsLocationExtended has upperTriangleFullCovMatrix. */
+#define GPS_LOCATION_EXTENDED_HAS_UPPER_TRIANGLE_FULL_COV_MATRIX 0x800000000000
+/** GpsLocationExtended has drSolutionStatusMask. */
+#define GPS_LOCATION_EXTENDED_HAS_DR_SOLUTION_STATUS_MASK        0x1000000000000
+/** GpsLocationExtended has altitudeAssumed. */
+#define GPS_LOCATION_EXTENDED_HAS_ALTITUDE_ASSUMED               0x2000000000000
 
 typedef uint32_t LocNavSolutionMask;
 /* Bitmask to specify whether SBAS ionospheric correction is used  */
@@ -409,6 +439,8 @@
 #define LOC_NAV_MASK_PPP_CORRECTION ((LocNavSolutionMask)0x0040)
 /**<  Bitmask to specify whether Position Report is RTK fixed corrected   */
 #define LOC_NAV_MASK_RTK_FIXED_CORRECTION ((LocNavSolutionMask)0x0080)
+/**<  Bitmask specifying whether only SBAS corrected SVs are used for the fix */
+#define LOC_NAV_MASK_ONLY_SBAS_CORRECTED_SV_USED ((LocNavSolutionMask)0x0100)
 
 typedef uint32_t LocPosDataMask;
 /* Bitmask to specify whether Navigation data has Forward Acceleration  */
@@ -442,18 +474,29 @@
 /** GPS PRN Range */
 #define GPS_SV_PRN_MIN      1
 #define GPS_SV_PRN_MAX      32
-#define SBAS_SV_PRN_MIN     33
-#define SBAS_SV_PRN_MAX     64
 #define GLO_SV_PRN_MIN      65
 #define GLO_SV_PRN_MAX      96
+#define SBAS_SV_PRN_MIN     120
+#define SBAS_SV_PRN_MAX     191
 #define QZSS_SV_PRN_MIN     193
 #define QZSS_SV_PRN_MAX     197
 #define BDS_SV_PRN_MIN      201
-#define BDS_SV_PRN_MAX      237
+#define BDS_SV_PRN_MAX      263
 #define GAL_SV_PRN_MIN      301
 #define GAL_SV_PRN_MAX      336
 #define NAVIC_SV_PRN_MIN    401
 #define NAVIC_SV_PRN_MAX    414
+#define GLO_SV_PRN_SLOT_UNKNOWN 255
+
+/* Checking svIdOneBase can be set to the corresponding bit in mask */
+#define svFitsMask(mask, svIdOneBase)                 \
+    ((svIdOneBase) >= 1 && (svIdOneBase) <= (sizeof(mask) << 3))
+/* Setting svIdOneBase specific bit in the mask if the bit offset fits */
+#define setSvMask(mask, svIdOneBase)                  \
+    if (svFitsMask(mask, svIdOneBase)) mask |= (1ULL << ((svIdOneBase) - 1))
+
+#define isValInRangeInclusive(val, min, max) ((val) >= (min) && (val) <= (max))
+#define isGloSlotUnknown(val) ((val) == GLO_SV_PRN_SLOT_UNKNOWN)
 
 typedef enum {
     LOC_RELIABILITY_NOT_SET = 0,
@@ -573,6 +616,13 @@
 #define CARRIER_PHASE_AMBIGUITY_RESOLUTION_FLOAT ((CarrierPhaseAmbiguityType)1)
 #define CARRIER_PHASE_AMBIGUITY_RESOLUTION_FIXED ((CarrierPhaseAmbiguityType)2)
 
+
+typedef enum {
+  LOC_DGNSS_CORR_SOURCE_TYPE_INVALID = 0, /**<  Invalid DGNSS correction source type \n */
+  LOC_DGNSS_CORR_SOURCE_TYPE_RTCM = 1, /**<  DGNSS correction source type RTCM \n */
+  LOC_DGNSS_CORR_SOURCE_TYPE_3GPP = 2, /**<  DGNSS correction source type 3GPP \n */
+}LocDgnssCorrectionSourceType;
+
 typedef uint16_t GnssMeasUsageStatusBitMask;
 /** Used in fix */
 #define GNSS_MEAS_USED_IN_PVT ((GnssMeasUsageStatusBitMask)0x00000001ul)
@@ -613,7 +663,6 @@
 #define GNSS_SV_POLY_DELETE_VALID_V02 ((GnssSvPolyStatusMaskValidity)0x04)
 #define GNSS_SV_POLY_SRC_GAL_FNAV_OR_INAV_VALID_V02 ((GnssSvPolyStatusMaskValidity)0x08)
 
-
 typedef struct {
     /** Specifies GNSS signal type
         Mandatory Field*/
@@ -621,13 +670,15 @@
     /** Specifies GNSS Constellation Type
         Mandatory Field*/
     Gnss_LocSvSystemEnumType gnssConstellation;
-    /**  GNSS SV ID.
-         For GPS:      1 to 32
-         For GLONASS:  65 to 96. When slot-number to SV ID mapping is unknown, set as 255.
-         For SBAS:     120 to 151
-         For QZSS-L1CA:193 to 197
-         For BDS:      201 to 237
-         For GAL:      301 to 336 */
+    /**  Unique SV Identifier.
+     *   SV Range for supported constellation is specified as below:
+     *    - For GPS:     1 to 32
+     *    - For GLONASS: 65 to 96
+     *    - For SBAS:    120 to 158 and 183 to 191
+     *    - For QZSS:    193 to 197
+     *    - For BDS:     201 to 263
+     *    - For GAL:     301 to 336
+     *    - For NAVIC:   401 to 414 */
     uint16_t gnssSvId;
     /** GLONASS frequency number + 7.
         Valid only for a GLONASS system and
@@ -655,7 +706,7 @@
     float carrierPhasAmbiguity;
 } GpsMeasUsageInfo;
 
-
+#define COV_MATRIX_SIZE 12
 /** Represents gps location extended. */
 typedef struct {
     /** set to sizeof(GpsLocationExtended) */
@@ -761,22 +812,74 @@
     /** Sensor calibration confidence percent. Range: 0 - 100 */
     uint8_t calibrationConfidence;
     DrCalibrationStatusMask calibrationStatus;
-    /* location engine type. When the fix. when the type is set to
+    /** location engine type. When the fix. when the type is set to
         LOC_ENGINE_SRC_FUSED, the fix is the propagated/aggregated
         reports from all engines running on the system (e.g.:
         DR/SPE/PPE). To check which location engine contributes to
         the fused output, check for locOutputEngMask. */
     LocOutputEngineType locOutputEngType;
-    /* when loc output eng type is set to fused, this field
+    /** when loc output eng type is set to fused, this field
         indicates the set of engines contribute to the fix. */
     PositioningEngineMask locOutputEngMask;
-} GpsLocationExtended;
 
-enum loc_sess_status {
-    LOC_SESS_SUCCESS,
-    LOC_SESS_INTERMEDIATE,
-    LOC_SESS_FAILURE
-};
+    /**  DGNSS Correction Source for position report: RTCM, 3GPP
+     *   etc. */
+    LocDgnssCorrectionSourceType dgnssCorrectionSourceType;
+
+    /**  If DGNSS is used, the SourceID is a 32bit number identifying
+     *   the DGNSS source ID */
+    uint32_t dgnssCorrectionSourceID;
+
+    /** If DGNSS is used, which constellation was DGNSS used for to
+     *  produce the pos report. */
+    GnssConstellationTypeMask dgnssConstellationUsage;
+
+    /** If DGNSS is used, DGNSS Reference station ID used for
+     *  position report */
+    uint16_t dgnssRefStationId;
+
+    /**  If DGNSS is used, DGNSS data age in milli-seconds  */
+    uint32_t dgnssDataAgeMsec;
+
+    /** When robust location is enabled, this field
+     * will how well the various input data considered for
+     * navigation solution conform to expectations.
+     * Range: 0 (least conforming) to 1 (most conforming) */
+    float conformityIndex;
+    GnssLocationPositionDynamicsExt bodyFrameDataExt;
+    /** VRR-based latitude/longitude/altitude */
+    LLAInfo llaVRPBased;
+    /** VRR-based east, north, and up velocity */
+    float enuVelocityVRPBased[3];
+    /** Upper triangle elements of full matrix of position and
+        velocity estimate in ECEF
+
+         The full covariance matrix of PPE position
+         (x, y, z in ECEF, in the unit of meters) estimate is a 3x3 matrix
+            | px,x  px,y  px,z |
+            | py,x  py,y  py,z |
+            | pz,x  pz,y  pz,z |
+
+         The full covariance matrix of PPE velocity
+         (vx,vy, vz in ECEF, in the unit of m/s) estimate is a 3x3 matrix
+            | pvx,vx  pvx,vy  pvx,vz |
+            | pvy,vx  pvy,vy  pvy,vz |
+            | pvz,vx  pvz,vy  pvz,vz |
+
+        upperTriangleFullCovMatrix =
+          { px,x, px,y, px,z, py,y, py,z, pz,z, pvx,vx, pvx,vy, pvx,vz, pvy,vy, pvy,vz, pvz,vz}
+        Uint: px,x, px,y, px,z, py,y, py,z, pz,z is in meter
+              pvx,vx, pvx,vy, pvx,vz, pvy,vy, pvy,vz, pvz,vz is in meters/seconds
+    */
+    float upperTriangleFullCovMatrix[COV_MATRIX_SIZE];
+    DrSolutionStatusMask drSolutionStatusMask;
+    /** When this field is valid, it will indicates whether altitude
+     *  is assumed or calculated.
+     *  false: Altitude is calculated.
+     *  true:  Altitude is assumed; there may not be enough
+     *         satellites to determine the precise altitude. */
+    bool altitudeAssumed;
+} GpsLocationExtended;
 
 // struct that contains complete position info from engine
 typedef struct {
@@ -818,6 +921,7 @@
 #define LOC_NMEA_MASK_GQGSV_V02 ((NmeaSentenceTypesMask)0x10000000) /**<  Enable GQGSV type  */
 #define LOC_NMEA_MASK_GIGSV_V02 ((NmeaSentenceTypesMask)0x20000000) /**<  Enable GIGSV type  */
 #define LOC_NMEA_MASK_GNDTM_V02 ((NmeaSentenceTypesMask)0x40000000) /**<  Enable GNDTM type  */
+#define LOC_NMEA_MASK_TAGBLOCK_V02 ((NmeaSentenceTypesMask)0x80000000) /**< Enable TAGBLOCK type */
 
 
 // all bitmasks of general supported NMEA sentenses - debug is not part of this
@@ -912,41 +1016,42 @@
     LOC_API_ADAPTER_LOC_SYSTEM_INFO,                   // Location system info event
     LOC_API_ADAPTER_GNSS_NHZ_MEASUREMENT_REPORT,       // GNSS SV nHz measurement report
     LOC_API_ADAPTER_EVENT_REPORT_INFO,                 // Event report info
+    LOC_API_ADAPTER_LATENCY_INFORMATION_REPORT,       // Latency information report
     LOC_API_ADAPTER_EVENT_MAX
 };
 
-#define LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT           (1<<LOC_API_ADAPTER_REPORT_POSITION)
-#define LOC_API_ADAPTER_BIT_SATELLITE_REPORT                 (1<<LOC_API_ADAPTER_REPORT_SATELLITE)
-#define LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT                  (1<<LOC_API_ADAPTER_REPORT_NMEA_1HZ)
-#define LOC_API_ADAPTER_BIT_NMEA_POSITION_REPORT             (1<<LOC_API_ADAPTER_REPORT_NMEA_POSITION)
-#define LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST         (1<<LOC_API_ADAPTER_REQUEST_NI_NOTIFY_VERIFY)
-#define LOC_API_ADAPTER_BIT_ASSISTANCE_DATA_REQUEST          (1<<LOC_API_ADAPTER_REQUEST_ASSISTANCE_DATA)
-#define LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST          (1<<LOC_API_ADAPTER_REQUEST_LOCATION_SERVER)
-#define LOC_API_ADAPTER_BIT_IOCTL_REPORT                     (1<<LOC_API_ADAPTER_REPORT_IOCTL)
-#define LOC_API_ADAPTER_BIT_STATUS_REPORT                    (1<<LOC_API_ADAPTER_REPORT_STATUS)
-#define LOC_API_ADAPTER_BIT_REQUEST_WIFI                     (1<<LOC_API_ADAPTER_REQUEST_WIFI)
-#define LOC_API_ADAPTER_BIT_SENSOR_STATUS                    (1<<LOC_API_ADAPTER_SENSOR_STATUS)
-#define LOC_API_ADAPTER_BIT_REQUEST_TIME_SYNC                (1<<LOC_API_ADAPTER_REQUEST_TIME_SYNC)
-#define LOC_API_ADAPTER_BIT_REPORT_SPI                       (1<<LOC_API_ADAPTER_REPORT_SPI)
-#define LOC_API_ADAPTER_BIT_REPORT_NI_GEOFENCE               (1<<LOC_API_ADAPTER_REPORT_NI_GEOFENCE)
-#define LOC_API_ADAPTER_BIT_GEOFENCE_GEN_ALERT               (1<<LOC_API_ADAPTER_GEOFENCE_GEN_ALERT)
-#define LOC_API_ADAPTER_BIT_REPORT_GENFENCE_BREACH           (1<<LOC_API_ADAPTER_REPORT_GENFENCE_BREACH)
-#define LOC_API_ADAPTER_BIT_BATCHED_GENFENCE_BREACH_REPORT   (1<<LOC_API_ADAPTER_BATCHED_GENFENCE_BREACH_REPORT)
-#define LOC_API_ADAPTER_BIT_PEDOMETER_CTRL                   (1<<LOC_API_ADAPTER_PEDOMETER_CTRL)
-#define LOC_API_ADAPTER_BIT_MOTION_CTRL                      (1<<LOC_API_ADAPTER_MOTION_CTRL)
-#define LOC_API_ADAPTER_BIT_REQUEST_WIFI_AP_DATA             (1<<LOC_API_ADAPTER_REQUEST_WIFI_AP_DATA)
-#define LOC_API_ADAPTER_BIT_BATCH_FULL                       (1<<LOC_API_ADAPTER_BATCH_FULL)
-#define LOC_API_ADAPTER_BIT_BATCHED_POSITION_REPORT          (1<<LOC_API_ADAPTER_BATCHED_POSITION_REPORT)
-#define LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT_REPORT          (1<<LOC_API_ADAPTER_GNSS_MEASUREMENT_REPORT)
-#define LOC_API_ADAPTER_BIT_GNSS_SV_POLYNOMIAL_REPORT        (1<<LOC_API_ADAPTER_GNSS_SV_POLYNOMIAL_REPORT)
-#define LOC_API_ADAPTER_BIT_GDT_UPLOAD_BEGIN_REQ             (1<<LOC_API_ADAPTER_GDT_UPLOAD_BEGIN_REQ)
-#define LOC_API_ADAPTER_BIT_GDT_UPLOAD_END_REQ               (1<<LOC_API_ADAPTER_GDT_UPLOAD_END_REQ)
-#define LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT                 (1<<LOC_API_ADAPTER_GNSS_MEASUREMENT)
-#define LOC_API_ADAPTER_BIT_REQUEST_TIMEZONE                 (1<<LOC_API_ADAPTER_REQUEST_TIMEZONE)
-#define LOC_API_ADAPTER_BIT_REPORT_GENFENCE_DWELL            (1<<LOC_API_ADAPTER_REPORT_GENFENCE_DWELL_REPORT)
-#define LOC_API_ADAPTER_BIT_REQUEST_SRN_DATA                 (1<<LOC_API_ADAPTER_REQUEST_SRN_DATA)
-#define LOC_API_ADAPTER_BIT_POSITION_INJECTION_REQUEST       (1<<LOC_API_ADAPTER_REQUEST_POSITION_INJECTION)
-#define LOC_API_ADAPTER_BIT_BATCH_STATUS                     (1<<LOC_API_ADAPTER_BATCH_STATUS)
+#define LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT           (1ULL<<LOC_API_ADAPTER_REPORT_POSITION)
+#define LOC_API_ADAPTER_BIT_SATELLITE_REPORT                 (1ULL<<LOC_API_ADAPTER_REPORT_SATELLITE)
+#define LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT                  (1ULL<<LOC_API_ADAPTER_REPORT_NMEA_1HZ)
+#define LOC_API_ADAPTER_BIT_NMEA_POSITION_REPORT             (1ULL<<LOC_API_ADAPTER_REPORT_NMEA_POSITION)
+#define LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST         (1ULL<<LOC_API_ADAPTER_REQUEST_NI_NOTIFY_VERIFY)
+#define LOC_API_ADAPTER_BIT_ASSISTANCE_DATA_REQUEST          (1ULL<<LOC_API_ADAPTER_REQUEST_ASSISTANCE_DATA)
+#define LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST          (1ULL<<LOC_API_ADAPTER_REQUEST_LOCATION_SERVER)
+#define LOC_API_ADAPTER_BIT_IOCTL_REPORT                     (1ULL<<LOC_API_ADAPTER_REPORT_IOCTL)
+#define LOC_API_ADAPTER_BIT_STATUS_REPORT                    (1ULL<<LOC_API_ADAPTER_REPORT_STATUS)
+#define LOC_API_ADAPTER_BIT_REQUEST_WIFI                     (1ULL<<LOC_API_ADAPTER_REQUEST_WIFI)
+#define LOC_API_ADAPTER_BIT_SENSOR_STATUS                    (1ULL<<LOC_API_ADAPTER_SENSOR_STATUS)
+#define LOC_API_ADAPTER_BIT_REQUEST_TIME_SYNC                (1ULL<<LOC_API_ADAPTER_REQUEST_TIME_SYNC)
+#define LOC_API_ADAPTER_BIT_REPORT_SPI                       (1ULL<<LOC_API_ADAPTER_REPORT_SPI)
+#define LOC_API_ADAPTER_BIT_REPORT_NI_GEOFENCE               (1ULL<<LOC_API_ADAPTER_REPORT_NI_GEOFENCE)
+#define LOC_API_ADAPTER_BIT_GEOFENCE_GEN_ALERT               (1ULL<<LOC_API_ADAPTER_GEOFENCE_GEN_ALERT)
+#define LOC_API_ADAPTER_BIT_REPORT_GENFENCE_BREACH           (1ULL<<LOC_API_ADAPTER_REPORT_GENFENCE_BREACH)
+#define LOC_API_ADAPTER_BIT_BATCHED_GENFENCE_BREACH_REPORT   (1ULL<<LOC_API_ADAPTER_BATCHED_GENFENCE_BREACH_REPORT)
+#define LOC_API_ADAPTER_BIT_PEDOMETER_CTRL                   (1ULL<<LOC_API_ADAPTER_PEDOMETER_CTRL)
+#define LOC_API_ADAPTER_BIT_MOTION_CTRL                      (1ULL<<LOC_API_ADAPTER_MOTION_CTRL)
+#define LOC_API_ADAPTER_BIT_REQUEST_WIFI_AP_DATA             (1ULL<<LOC_API_ADAPTER_REQUEST_WIFI_AP_DATA)
+#define LOC_API_ADAPTER_BIT_BATCH_FULL                       (1ULL<<LOC_API_ADAPTER_BATCH_FULL)
+#define LOC_API_ADAPTER_BIT_BATCHED_POSITION_REPORT          (1ULL<<LOC_API_ADAPTER_BATCHED_POSITION_REPORT)
+#define LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT_REPORT          (1ULL<<LOC_API_ADAPTER_GNSS_MEASUREMENT_REPORT)
+#define LOC_API_ADAPTER_BIT_GNSS_SV_POLYNOMIAL_REPORT        (1ULL<<LOC_API_ADAPTER_GNSS_SV_POLYNOMIAL_REPORT)
+#define LOC_API_ADAPTER_BIT_GDT_UPLOAD_BEGIN_REQ             (1ULL<<LOC_API_ADAPTER_GDT_UPLOAD_BEGIN_REQ)
+#define LOC_API_ADAPTER_BIT_GDT_UPLOAD_END_REQ               (1ULL<<LOC_API_ADAPTER_GDT_UPLOAD_END_REQ)
+#define LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT                 (1ULL<<LOC_API_ADAPTER_GNSS_MEASUREMENT)
+#define LOC_API_ADAPTER_BIT_REQUEST_TIMEZONE                 (1ULL<<LOC_API_ADAPTER_REQUEST_TIMEZONE)
+#define LOC_API_ADAPTER_BIT_REPORT_GENFENCE_DWELL            (1ULL<<LOC_API_ADAPTER_REPORT_GENFENCE_DWELL_REPORT)
+#define LOC_API_ADAPTER_BIT_REQUEST_SRN_DATA                 (1ULL<<LOC_API_ADAPTER_REQUEST_SRN_DATA)
+#define LOC_API_ADAPTER_BIT_POSITION_INJECTION_REQUEST       (1ULL<<LOC_API_ADAPTER_REQUEST_POSITION_INJECTION)
+#define LOC_API_ADAPTER_BIT_BATCH_STATUS                     (1ULL<<LOC_API_ADAPTER_BATCH_STATUS)
 #define LOC_API_ADAPTER_BIT_FDCL_SERVICE_REQ                 (1ULL<<LOC_API_ADAPTER_FDCL_SERVICE_REQ)
 #define LOC_API_ADAPTER_BIT_PARSED_UNPROPAGATED_POSITION_REPORT (1ULL<<LOC_API_ADAPTER_REPORT_UNPROPAGATED_POSITION)
 #define LOC_API_ADAPTER_BIT_BS_OBS_DATA_SERVICE_REQ          (1ULL<<LOC_API_ADAPTER_BS_OBS_DATA_SERVICE_REQ)
@@ -954,6 +1059,7 @@
 #define LOC_API_ADAPTER_BIT_LOC_SYSTEM_INFO                  (1ULL<<LOC_API_ADAPTER_LOC_SYSTEM_INFO)
 #define LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT             (1ULL<<LOC_API_ADAPTER_GNSS_NHZ_MEASUREMENT_REPORT)
 #define LOC_API_ADAPTER_BIT_EVENT_REPORT_INFO                (1ULL<<LOC_API_ADAPTER_EVENT_REPORT_INFO)
+#define LOC_API_ADAPTER_BIT_LATENCY_INFORMATION              (1ULL<<LOC_API_ADAPTER_LATENCY_INFORMATION_REPORT)
 
 typedef uint64_t LOC_API_ADAPTER_EVENT_MASK_T;
 
@@ -977,11 +1083,11 @@
 #define isGpsLockMT(lock) ((lock) & ((LOC_GPS_LOCK_MASK)2))
 #define isGpsLockAll(lock) (((lock) & ((LOC_GPS_LOCK_MASK)3)) == 3)
 
-/*++ ***********************************************
+/* ***********************************************
 **  Satellite Measurement and Satellite Polynomial
-**  Structure definitions
-**  ***********************************************
---*/
+**  structure definitions
+** ***********************************************
+*/
 #define GNSS_SV_POLY_VELOCITY_COEF_MAX_SIZE         12
 #define GNSS_SV_POLY_XYZ_0_TH_ORDER_COEFF_MAX_SIZE  3
 #define GNSS_SV_POLY_XYZ_N_TH_ORDER_COEFF_MAX_SIZE  9
@@ -1173,20 +1279,26 @@
     /**< Satellite Doppler measured */
     GNSS_LOC_MEAS_STATUS_VELOCITY_FINE           = 0x00000020,
     /**< TRUE: Fine Doppler measured, FALSE: Coarse Doppler measured */
+    GNSS_LOC_MEAS_STATUS_LP_VALID                = 0x00000040,
+    /**<  TRUE/FALSE -- Lock Point is valid/invalid */
+    GNSS_LOC_MEAS_STATUS_LP_POS_VALID            = 0x00000080,
+    /**<  TRUE/FALSE -- Lock Point is positive/negative */
     GNSS_LOC_MEAS_STATUS_FROM_RNG_DIFF           = 0x00000200,
     /**< Range update from Satellite differences */
     GNSS_LOC_MEAS_STATUS_FROM_VE_DIFF            = 0x00000400,
     /**< Doppler update from Satellite differences */
     GNSS_LOC_MEAS_STATUS_DONT_USE_X              = 0x00000800,
     /**< Don't use measurement if bit is set */
-    GNSS_LOC_MEAS_STATUS_DONT_USE_M              = 0x000001000,
+    GNSS_LOC_MEAS_STATUS_DONT_USE_M              = 0x00001000,
     /**< Don't use measurement if bit is set */
-    GNSS_LOC_MEAS_STATUS_DONT_USE_D              = 0x000002000,
+    GNSS_LOC_MEAS_STATUS_DONT_USE_D              = 0x00002000,
     /**< Don't use measurement if bit is set */
-    GNSS_LOC_MEAS_STATUS_DONT_USE_S              = 0x000004000,
+    GNSS_LOC_MEAS_STATUS_DONT_USE_S              = 0x00004000,
     /**< Don't use measurement if bit is set */
-    GNSS_LOC_MEAS_STATUS_DONT_USE_P              = 0x000008000
+    GNSS_LOC_MEAS_STATUS_DONT_USE_P              = 0x00008000,
     /**< Don't use measurement if bit is set */
+    GNSS_LOC_MEAS_STATUS_GNSS_FRESH_MEAS         = 0x08000000
+    /**< TRUE -- Fresh GNSS measurement observed in last second    */
 }Gnss_LocSvMeasStatusMaskType;
 
 typedef struct
@@ -1249,6 +1361,25 @@
     /**< SV is being tracked */
 }Gnss_LocSvSearchStatusEnumT;
 
+typedef uint32_t LocSvDgnssMeasStatusMask;
+#define LOC_MASK_DGNSS_EPOCH_TIME_VALID      0x1  /**<  DGNSS Epoch time is valid  */
+#define LOC_MASK_DGNSS_MEAS_STATUS_PR_VALID  0x2  /**<  Pseudo Range correction is valid  */
+#define LOC_MASK_DGNSS_MEAS_STATUS_PRR_VALID 0x4  /**<  Pseudo Range rate correction is valid  */
+
+typedef struct {
+  LocSvDgnssMeasStatusMask dgnssMeasStatus;
+  /**<   Bitmask indicating the DGNSS SV measurement status. */
+
+  uint32_t diffDataEpochTimeMsec;
+  /**<   Age of differential data in Milli Seconds with respect to the Measurement time. */
+
+  float prCorrMeters;
+  /**<   Pseudo Range correction in meters. */
+
+  float prrCorrMetersPerSec;
+  /**<  Pseudo Range rate correction in meters per second. */
+} Gnss_LocDgnssSVMeasurement;
+
 typedef struct
 {
     uint32_t                          size;
@@ -1256,15 +1387,9 @@
     // 0 signal type mask indicates invalid value
     GnssSignalTypeMask              gnssSignalTypeMask;
     uint16_t                        gnssSvId;
-    /**< GNSS SV ID.
-         \begin{itemize1}
-         \item Range:  \begin{itemize1}
-           \item For GPS:      1 to 32
-           \item For GLONASS:  1 to 32
-           \item For SBAS:     120 to 151
-           \item For BDS:      201 to 237
-         \end{itemize1} \end{itemize1}
-        The GPS and GLONASS SVs can be disambiguated using the system field.
+    /** Unique SV Identifier.
+     *  For SV Range of supported constellation, please refer to the
+     *  comment section of gnssSvId in GpsMeasUsageInfo.
     */
     uint8_t                         gloFrequency;
     /**< GLONASS frequency number + 7 \n
@@ -1388,38 +1513,48 @@
 
     float                           carrierPhaseUnc;
 
-
+    /** < DGNSS Measurements Report for SVs */
+    Gnss_LocDgnssSVMeasurement   dgnssSvMeas;
 } Gnss_SVMeasurementStructType;
 
 
 typedef uint64_t GpsSvMeasHeaderFlags;
-#define GNSS_SV_MEAS_HEADER_HAS_LEAP_SECOND                  0x00000001
-#define GNSS_SV_MEAS_HEADER_HAS_CLOCK_FREQ                   0x00000002
-#define GNSS_SV_MEAS_HEADER_HAS_AP_TIMESTAMP                 0x00000004
-#define GNSS_SV_MEAS_HEADER_HAS_GPS_GLO_INTER_SYSTEM_BIAS    0x00000008
-#define GNSS_SV_MEAS_HEADER_HAS_GPS_BDS_INTER_SYSTEM_BIAS    0x00000010
-#define GNSS_SV_MEAS_HEADER_HAS_GPS_GAL_INTER_SYSTEM_BIAS    0x00000020
-#define GNSS_SV_MEAS_HEADER_HAS_BDS_GLO_INTER_SYSTEM_BIAS    0x00000040
-#define GNSS_SV_MEAS_HEADER_HAS_GAL_GLO_INTER_SYSTEM_BIAS    0x00000080
-#define GNSS_SV_MEAS_HEADER_HAS_GAL_BDS_INTER_SYSTEM_BIAS    0x00000100
-#define GNSS_SV_MEAS_HEADER_HAS_GPS_SYSTEM_TIME              0x00000200
-#define GNSS_SV_MEAS_HEADER_HAS_GAL_SYSTEM_TIME              0x00000400
-#define GNSS_SV_MEAS_HEADER_HAS_BDS_SYSTEM_TIME              0x00000800
-#define GNSS_SV_MEAS_HEADER_HAS_QZSS_SYSTEM_TIME             0x00001000
-#define GNSS_SV_MEAS_HEADER_HAS_GLO_SYSTEM_TIME              0x00002000
-#define GNSS_SV_MEAS_HEADER_HAS_GPS_SYSTEM_TIME_EXT          0x00004000
-#define GNSS_SV_MEAS_HEADER_HAS_GAL_SYSTEM_TIME_EXT          0x00008000
-#define GNSS_SV_MEAS_HEADER_HAS_BDS_SYSTEM_TIME_EXT          0x00010000
-#define GNSS_SV_MEAS_HEADER_HAS_QZSS_SYSTEM_TIME_EXT         0x00020000
-#define GNSS_SV_MEAS_HEADER_HAS_GLO_SYSTEM_TIME_EXT          0x00040000
-#define GNSS_SV_MEAS_HEADER_HAS_GPSL1L5_TIME_BIAS            0x00080000
-#define GNSS_SV_MEAS_HEADER_HAS_GALE1E5A_TIME_BIAS           0x00100000
-#define GNSS_SV_MEAS_HEADER_HAS_GPS_NAVIC_INTER_SYSTEM_BIAS  0x00200000
-#define GNSS_SV_MEAS_HEADER_HAS_GAL_NAVIC_INTER_SYSTEM_BIAS  0x00400000
-#define GNSS_SV_MEAS_HEADER_HAS_GLO_NAVIC_INTER_SYSTEM_BIAS  0x00800000
-#define GNSS_SV_MEAS_HEADER_HAS_BDS_NAVIC_INTER_SYSTEM_BIAS  0x01000000
-#define GNSS_SV_MEAS_HEADER_HAS_NAVIC_SYSTEM_TIME            0x02000000
-#define GNSS_SV_MEAS_HEADER_HAS_NAVIC_SYSTEM_TIME_EXT        0x04000000
+#define GNSS_SV_MEAS_HEADER_HAS_LEAP_SECOND                   0x000000001
+#define GNSS_SV_MEAS_HEADER_HAS_CLOCK_FREQ                    0x000000002
+#define GNSS_SV_MEAS_HEADER_HAS_AP_TIMESTAMP                  0x000000004
+#define GNSS_SV_MEAS_HEADER_HAS_GPS_GLO_INTER_SYSTEM_BIAS     0x000000008
+#define GNSS_SV_MEAS_HEADER_HAS_GPS_BDS_INTER_SYSTEM_BIAS     0x000000010
+#define GNSS_SV_MEAS_HEADER_HAS_GPS_GAL_INTER_SYSTEM_BIAS     0x000000020
+#define GNSS_SV_MEAS_HEADER_HAS_BDS_GLO_INTER_SYSTEM_BIAS     0x000000040
+#define GNSS_SV_MEAS_HEADER_HAS_GAL_GLO_INTER_SYSTEM_BIAS     0x000000080
+#define GNSS_SV_MEAS_HEADER_HAS_GAL_BDS_INTER_SYSTEM_BIAS     0x000000100
+#define GNSS_SV_MEAS_HEADER_HAS_GPS_SYSTEM_TIME               0x000000200
+#define GNSS_SV_MEAS_HEADER_HAS_GAL_SYSTEM_TIME               0x000000400
+#define GNSS_SV_MEAS_HEADER_HAS_BDS_SYSTEM_TIME               0x000000800
+#define GNSS_SV_MEAS_HEADER_HAS_QZSS_SYSTEM_TIME              0x000001000
+#define GNSS_SV_MEAS_HEADER_HAS_GLO_SYSTEM_TIME               0x000002000
+#define GNSS_SV_MEAS_HEADER_HAS_GPS_SYSTEM_TIME_EXT           0x000004000
+#define GNSS_SV_MEAS_HEADER_HAS_GAL_SYSTEM_TIME_EXT           0x000008000
+#define GNSS_SV_MEAS_HEADER_HAS_BDS_SYSTEM_TIME_EXT           0x000010000
+#define GNSS_SV_MEAS_HEADER_HAS_QZSS_SYSTEM_TIME_EXT          0x000020000
+#define GNSS_SV_MEAS_HEADER_HAS_GLO_SYSTEM_TIME_EXT           0x000040000
+#define GNSS_SV_MEAS_HEADER_HAS_GPSL1L5_TIME_BIAS             0x000080000
+#define GNSS_SV_MEAS_HEADER_HAS_GALE1E5A_TIME_BIAS            0x000100000
+#define GNSS_SV_MEAS_HEADER_HAS_BDSB1IB2A_TIME_BIAS           0x000200000
+#define GNSS_SV_MEAS_HEADER_HAS_GPS_NAVIC_INTER_SYSTEM_BIAS   0x000400000
+#define GNSS_SV_MEAS_HEADER_HAS_GAL_NAVIC_INTER_SYSTEM_BIAS   0x000800000
+#define GNSS_SV_MEAS_HEADER_HAS_GLO_NAVIC_INTER_SYSTEM_BIAS   0x001000000
+#define GNSS_SV_MEAS_HEADER_HAS_BDS_NAVIC_INTER_SYSTEM_BIAS   0x002000000
+#define GNSS_SV_MEAS_HEADER_HAS_NAVIC_SYSTEM_TIME             0x004000000
+#define GNSS_SV_MEAS_HEADER_HAS_NAVIC_SYSTEM_TIME_EXT         0x008000000
+#define GNSS_SV_MEAS_HEADER_HAS_DGNSS_CORRECTION_SOURCE_TYPE  0x010000000
+#define GNSS_SV_MEAS_HEADER_HAS_DGNSS_CORRECTION_SOURCE_ID    0x020000000
+#define GNSS_SV_MEAS_HEADER_HAS_DGNSS_REF_STATION_ID          0x040000000
+#define GNSS_SV_MEAS_HEADER_HAS_REF_COUNT_TICKS               0x080000000
+#define GNSS_SV_MEAS_HEADER_HAS_GPSL1L2C_TIME_BIAS            0x100000000
+#define GNSS_SV_MEAS_HEADER_HAS_GLOG1G2_TIME_BIAS             0x200000000
+#define GNSS_SV_MEAS_HEADER_HAS_BDSB1IB1C_TIME_BIAS           0x400000000
+#define GNSS_SV_MEAS_HEADER_HAS_GALE1E5B_TIME_BIAS            0x800000000
 
 typedef struct
 {
@@ -1445,6 +1580,11 @@
     Gnss_InterSystemBiasStructType              bdsNavicInterSystemBias;
     Gnss_InterSystemBiasStructType              gpsL1L5TimeBias;
     Gnss_InterSystemBiasStructType              galE1E5aTimeBias;
+    Gnss_InterSystemBiasStructType              bdsB1iB2aTimeBias;
+    Gnss_InterSystemBiasStructType              gpsL1L2cTimeBias;
+    Gnss_InterSystemBiasStructType              gloG1G2TimeBias;
+    Gnss_InterSystemBiasStructType              bdsB1iB1cTimeBias;
+    Gnss_InterSystemBiasStructType              galE1E5bTimeBias;
 
     GnssSystemTimeStructType                    gpsSystemTime;
     GnssSystemTimeStructType                    galSystemTime;
@@ -1465,6 +1605,21 @@
     Gnss_LocGnssTimeExtStructType               gloSystemTimeExt;
     /** NAVIC system RTC time information. */
     Gnss_LocGnssTimeExtStructType               navicSystemTimeExt;
+
+    /** Receiver tick at frame count */
+    uint64_t                                    refCountTicks;
+
+    /** DGNSS corrections source type RTCM, 3GPP etc, if DGNSS was
+     *  used for these measurements. */
+    LocDgnssCorrectionSourceType                dgnssCorrectionSourceType;
+
+    /** DGNSS SourceID: 32bit number identifying the DGNSS source
+     *  ID, if DGNSS was used for these measurements. */
+    uint32_t                                    dgnssCorrectionSourceID;
+
+    /** DGNSS Ref station ID: 32bit number identifying the DGNSS
+     *  ref station ID, if DGNSS was used for these measurements. */
+    uint16_t                                    dgnssRefStationId;
 } GnssSvMeasurementHeader;
 
 typedef struct {
@@ -1503,19 +1658,17 @@
 
    GNSS_SV_POLY_GLO_STR4                = 0x40
    /**< GLONASS String 4 has been received */
-}Gnss_SvPolyStatusMaskType;
+} Gnss_SvPolyStatusMaskType;
 
-
-typedef struct
-{
+typedef struct {
     uint32_t      size;
     uint16_t     gnssSvId;
-    /* GPS: 1-32, GLO: 65-96, 0: Invalid,
-       SBAS: 120-151, BDS:201-237,GAL:301 to 336
-       All others are reserved
+    /** Unique SV Identifier.
+     *  For SV Range of supported constellation, please refer to the
+     *  comment section of gnssSvId in GpsMeasUsageInfo.
     */
     int8_t      freqNum;
-    /* Freq index, only valid if u_SysInd is GLO */
+    /** Freq index, only valid if u_SysInd is GLO */
 
     GnssSvPolyStatusMaskValidity svPolyStatusMaskValidity;
     GnssSvPolyStatusMask         svPolyStatusMask;
@@ -1585,15 +1738,10 @@
 
 typedef struct {
     uint16_t gnssSvId;
-    /**<   GNSS SV ID.
-      - Type: uint16
-      \begin{itemize1}
-      \item    Range:    \begin{itemize1}
-        \item    For GPS:     1 to 32
-        \item    For QZSS:    193 to 197
-        \item    For BDS:     201 to 237
-        \item    For GAL:     301 to 336
-      \vspace{-0.18in} \end{itemize1} \end{itemize1} */
+    /** Unique SV Identifier.
+     *  For SV Range of supported constellation, please refer to the
+     *  comment section of gnssSvId in GpsMeasUsageInfo.
+     */
 
     GnssEphAction updateAction;
     /**<   Specifies the action and source of ephemeris. \n
@@ -2163,6 +2311,20 @@
     bool                    isCachedLocation;
 } GnssNfwNotification;
 
+typedef uint16_t GnssMeasurementCorrectionsCapabilitiesMask;
+typedef enum {
+    GNSS_MEAS_CORR_LOS_SATS            = 1 << 0,
+    GNSS_MEAS_CORR_EXCESS_PATH_LENGTH  = 1 << 1,
+    GNSS_MEAS_CORR_REFLECTING_PLANE    = 1 << 2,
+} GnssMeasurementCorrectionsCapabilities;
+
+/* Represents GNSS NMEA Report Rate Configuration */
+typedef enum {
+    GNSS_NMEA_REPORT_RATE_UNKNOWN  = 0,
+    GNSS_NMEA_REPORT_RATE_1HZ  = 1,
+    GNSS_NMEA_REPORT_RATE_NHZ  = 2
+} GnssNMEARptRate;
+
 /* ODCPI Request Info */
 enum OdcpiRequestType {
     ODCPI_REQUEST_TYPE_START,
@@ -2177,6 +2339,12 @@
 /* Callback to send ODCPI request to framework */
 typedef std::function<void(const OdcpiRequestInfo& request)> OdcpiRequestCallback;
 
+/* ODCPI callback priorities*/
+enum OdcpiPrioritytype {
+    ODCPI_HANDLER_PRIORITY_LOW,
+    ODCPI_HANDLER_PRIORITY_HIGH
+};
+
 /*
  * Callback with AGNSS(IpV4) status information.
  *
@@ -2185,11 +2353,29 @@
 typedef void (*AgnssStatusIpV4Cb)(AGnssExtStatusIpV4 status);
 
 /*
+* Callback with AGNSS(IpV6) status information.
+*
+* @param status Will be of type AGnssExtStatusIpV6.
+*/
+typedef void (*AgnssStatusIpV6Cb)(AGnssExtStatusIpV6 status);
+
+/*
 * Callback with NFW information.
 */
 typedef void(*NfwStatusCb)(GnssNfwNotification notification);
 typedef bool(*IsInEmergencySession)(void);
 
+enum AntennaInfoStatus {
+    ANTENNA_INFO_SUCCESS = 0,
+    ANTENNA_INFO_ERROR_ALREADY_INIT = 1,
+    ANTENNA_INFO_ERROR_GENERIC = 2
+};
+
+/*
+* Callback with Measurement corrections information.
+*/
+typedef void(*measCorrSetCapabilitiesCb)(GnssMeasurementCorrectionsCapabilitiesMask capabilities);
+
 /*
  * Callback with AGNSS(IpV6) status information.
  *
@@ -2197,6 +2383,11 @@
  */
 typedef void (*AgnssStatusIpV6Cb)(AGnssExtStatusIpV6 status);
 
+/*
+* Callback with Antenna information.
+*/
+typedef void(*antennaInfoCb)(std::vector<GnssAntennaInformation> gnssAntennaInformations);
+
 /* Constructs for interaction with loc_net_iface library */
 typedef void (*LocAgpsOpenResultCb)(bool isSuccess, AGpsExtType agpsType, const char* apn,
         AGpsBearerType bearerType, void* userDataPtr);
@@ -2222,7 +2413,10 @@
 #define EAP_LOC_CLIENT_DIR             "/data/vendor/location/extap_locclient/"
 
 #define LOC_CLIENT_NAME_PREFIX         "toclient"
-#define LOC_INTAPI_NAME_PREFIX         "toIntapiClient"
+// Please note that the socket name for all location hal daemon client need
+// to start with LOC_CLIENT_NAME_PREFIX so that upon hal daemon restarts,
+// every client can get the notification that hal daemon has restarted.
+#define LOC_INTAPI_NAME_PREFIX         LOC_CLIENT_NAME_PREFIX "_intapi"
 
 typedef uint64_t NetworkHandle;
 #define NETWORK_HANDLE_UNKNOWN  ~0
diff --git a/utils/loc_cfg.cpp b/utils/loc_cfg.cpp
index 432095e..a1e6b83 100644
--- a/utils/loc_cfg.cpp
+++ b/utils/loc_cfg.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2015, 2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2015, 2018-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -89,6 +89,9 @@
 const char LOC_PATH_APDR_CONF[] = LOC_PATH_APDR_CONF_STR;
 const char LOC_PATH_XTWIFI_CONF[] = LOC_PATH_XTWIFI_CONF_STR;
 const char LOC_PATH_QUIPC_CONF[] = LOC_PATH_QUIPC_CONF_STR;
+const char LOC_PATH_ANT_CORR[] = LOC_PATH_ANT_CORR_STR;
+const char LOC_PATH_SLIM_CONF[] = LOC_PATH_SLIM_CONF_STR;
+const char LOC_PATH_VPE_CONF[] = LOC_PATH_VPE_CONF_STR;
 
 bool isVendorEnhanced() {
     return sVendorEnhanced;
@@ -141,7 +144,9 @@
 SIDE EFFECTS
    N/A
 ===========================================================================*/
-int loc_set_config_entry(const loc_param_s_type* config_entry, loc_param_v_type* config_value)
+int loc_set_config_entry(const loc_param_s_type* config_entry,
+                        loc_param_v_type* config_value,
+                        uint16_t string_len = LOC_MAX_PARAM_STRING)
 {
     int ret=-1;
     if(NULL == config_entry || NULL == config_value)
@@ -163,7 +168,7 @@
             else {
                 strlcpy((char*) config_entry->param_ptr,
                         config_value->param_str_value,
-                        LOC_MAX_PARAM_STRING);
+                        string_len);
             }
             /* Log INI values */
             LOC_LOGD("%s: PARAM %s = %s", __FUNCTION__,
@@ -230,7 +235,8 @@
    N/A
 ===========================================================================*/
 int loc_fill_conf_item(char* input_buf,
-                       const loc_param_s_type* config_table, uint32_t table_length)
+                       const loc_param_s_type* config_table,
+                       uint32_t table_length, uint16_t string_len = LOC_MAX_PARAM_STRING)
 {
     int ret = 0;
 
@@ -243,7 +249,7 @@
         config_value.param_name = strtok_r(input_buf, "=", &lasts);
         /* skip lines that do not contain "=" */
         if (config_value.param_name) {
-            config_value.param_str_value = strtok_r(NULL, "=", &lasts);
+            config_value.param_str_value = strtok_r(NULL, "\0", &lasts);
 
             /* skip lines that do not contain two operands */
             if (config_value.param_str_value) {
@@ -267,7 +273,7 @@
 
                 for(uint32_t i = 0; NULL != config_table && i < table_length; i++)
                 {
-                    if(!loc_set_config_entry(&config_table[i], &config_value)) {
+                    if(!loc_set_config_entry(&config_table[i], &config_value, string_len)) {
                         ret += 1;
                     }
                 }
@@ -279,7 +285,7 @@
 }
 
 /*===========================================================================
-FUNCTION loc_read_conf_r (repetitive)
+FUNCTION loc_read_conf_r_long (repetitive)
 
 DESCRIPTION
    Reads the specified configuration file and sets defined values based on
@@ -307,11 +313,13 @@
 SIDE EFFECTS
    N/A
 ===========================================================================*/
-int loc_read_conf_r(FILE *conf_fp, const loc_param_s_type* config_table, uint32_t table_length)
+int loc_read_conf_r_long(FILE *conf_fp, const loc_param_s_type* config_table,
+                         uint32_t table_length, uint16_t string_len)
 {
     int ret=0;
-
+    char input_buf[string_len];  /* declare a char array */
     unsigned int num_params=table_length;
+
     if(conf_fp == NULL) {
         LOC_LOGE("%s:%d]: ERROR: File pointer is NULL\n", __func__, __LINE__);
         ret = -1;
@@ -327,17 +335,15 @@
         }
     }
 
-    char input_buf[LOC_MAX_PARAM_LINE];  /* declare a char array */
-
     LOC_LOGD("%s:%d]: num_params: %d\n", __func__, __LINE__, num_params);
     while(num_params)
     {
-        if(!fgets(input_buf, LOC_MAX_PARAM_LINE, conf_fp)) {
+        if(!fgets(input_buf, string_len, conf_fp)) {
             LOC_LOGD("%s:%d]: fgets returned NULL\n", __func__, __LINE__);
             break;
         }
 
-        num_params -= loc_fill_conf_item(input_buf, config_table, table_length);
+        num_params -= loc_fill_conf_item(input_buf, config_table, table_length, string_len);
     }
 
 err:
@@ -345,7 +351,7 @@
 }
 
 /*===========================================================================
-FUNCTION loc_udpate_conf
+FUNCTION loc_update_conf_long
 
 DESCRIPTION
    Parses the passed in buffer for configuration items, and update the table
@@ -370,8 +376,9 @@
 SIDE EFFECTS
    N/A
 ===========================================================================*/
-int loc_update_conf(const char* conf_data, int32_t length,
-                    const loc_param_s_type* config_table, uint32_t table_length)
+int loc_update_conf_long(const char* conf_data, int32_t length,
+                         const loc_param_s_type* config_table,
+                         uint32_t table_length, uint16_t string_len)
 {
     int ret = -1;
 
@@ -394,7 +401,8 @@
             LOC_LOGD("%s:%d]: num_params: %d\n", __func__, __LINE__, num_params);
             while(num_params && input_buf) {
                 ret++;
-                num_params -= loc_fill_conf_item(input_buf, config_table, table_length);
+                num_params -=
+                        loc_fill_conf_item(input_buf, config_table, table_length, string_len);
                 input_buf = strtok_r(NULL, "\n", &saveptr);
             }
             free(conf_copy);
@@ -405,7 +413,7 @@
 }
 
 /*===========================================================================
-FUNCTION loc_read_conf
+FUNCTION loc_read_conf_long
 
 DESCRIPTION
    Reads the specified configuration file and sets defined values based on
@@ -426,8 +434,8 @@
 SIDE EFFECTS
    N/A
 ===========================================================================*/
-void loc_read_conf(const char* conf_file_name, const loc_param_s_type* config_table,
-                   uint32_t table_length)
+void loc_read_conf_long(const char* conf_file_name, const loc_param_s_type* config_table,
+                        uint32_t table_length, uint16_t string_len)
 {
     FILE *conf_fp = NULL;
 
@@ -436,15 +444,16 @@
     {
         LOC_LOGD("%s: using %s", __FUNCTION__, conf_file_name);
         if(table_length && config_table) {
-            loc_read_conf_r(conf_fp, config_table, table_length);
+            loc_read_conf_r_long(conf_fp, config_table, table_length, string_len);
             rewind(conf_fp);
         }
-        loc_read_conf_r(conf_fp, loc_param_table, loc_param_num);
+        loc_read_conf_r_long(conf_fp, loc_param_table, loc_param_num, string_len);
         fclose(conf_fp);
     }
     /* Initialize logging mechanism with parsed data */
     loc_logger_init(DEBUG_LEVEL, TIMESTAMP);
     log_buffer_init(sLogBufferEnabled);
+    log_tag_level_map_init();
 }
 
 /*=============================================================================
@@ -617,14 +626,18 @@
     UTIL_READ_CONF(conf_file_name, loc_feature_conf_table);
 
     //Set service mask for GTP_MODE
-    if(strcmp(conf.feature_gtp_mode, "DISABLED") == 0) {
+    if (strcmp(conf.feature_gtp_mode, "DISABLED") == 0) {
         LOC_LOGD("%s:%d]: GTP MODE DISABLED", __func__, __LINE__);
     }
-    else if(strcmp(conf.feature_gtp_mode, "LEGACY_WWAN") == 0) {
+    else if (strcmp(conf.feature_gtp_mode, "LEGACY_WWAN") == 0) {
         LOC_LOGD("%s:%d]: Setting GTP MODE to mode: LEGACY_WWAN", __func__, __LINE__);
         loc_service_mask |= LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC;
     }
-    else if(strcmp(conf.feature_gtp_mode, "SDK") == 0) {
+    else if (strcmp(conf.feature_gtp_mode, "SDK") == 0) {
+        LOC_LOGD("%s:%d]: Setting GTP MODE to mode: SDK", __func__, __LINE__);
+        loc_service_mask |= LOC_FEATURE_MASK_GTP_WIFI_BASIC;
+    }
+    else if (strcmp(conf.feature_gtp_mode, "SDK_WIFI") == 0) {
         LOC_LOGD("%s:%d]: Setting GTP MODE to mode: SDK", __func__, __LINE__);
         loc_service_mask |= LOC_FEATURE_MASK_GTP_WIFI_BASIC;
     }
@@ -634,11 +647,11 @@
                  " Setting GTP WIFI to default mode: DISABLED", __func__, __LINE__);
     }
     //Set service mask for GTP_WAA
-    if(strcmp(conf.feature_gtp_waa, "BASIC") == 0) {
+    if (strcmp(conf.feature_gtp_waa, "BASIC") == 0) {
       LOC_LOGD("%s:%d]: Setting GTP WAA to mode: BASIC", __func__, __LINE__);
       loc_service_mask |= LOC_FEATURE_MASK_GTP_WAA_BASIC;
     }
-    else if(strcmp(conf.feature_gtp_waa, "DISABLED") == 0) {
+    else if (strcmp(conf.feature_gtp_waa, "DISABLED") == 0) {
       LOC_LOGD("%s:%d]: GTP WAA DISABLED", __func__, __LINE__);
     }
     //conf file has a garbage value
@@ -648,19 +661,26 @@
     }
 
     //Set service mask for SAP
-    if(strcmp(conf.feature_sap, "PREMIUM") == 0) {
+    if(strcmp(conf.feature_sap, "PREMIUM") == 0 ||
+       strcmp(conf.feature_sap, "PREMIUM_ENV_AIDING") == 0) {
         LOC_LOGD("%s:%d]: Setting SAP to mode: PREMIUM", __func__, __LINE__);
         loc_service_mask |= LOC_FEATURE_MASK_SAP_PREMIUM;
     }
-    else if(strcmp(conf.feature_sap, "BASIC") == 0) {
+    else if (strcmp(conf.feature_sap, "BASIC") == 0) {
         LOC_LOGD("%s:%d]: Setting SAP to mode: BASIC", __func__, __LINE__);
         loc_service_mask |= LOC_FEATURE_MASK_SAP_BASIC;
     }
-    else if(strcmp(conf.feature_sap, "MODEM_DEFAULT") == 0) {
+    else if (strcmp(conf.feature_sap, "MODEM_DEFAULT") == 0) {
         LOC_LOGD("%s:%d]: Setting SAP to mode: MODEM_DEFAULT", __func__, __LINE__);
+        loc_service_mask |= LOC_FEATURE_MASK_SAP_BASIC;
     }
-    else if(strcmp(conf.feature_sap, "DISABLED") == 0) {
+    else if (strcmp(conf.feature_sap, "DISABLED") == 0) {
+#ifdef USE_GLIB
+        /* Enable slim_daemon even when SAP is set to DISABLED*/
+        loc_service_mask |= LOC_FEATURE_MASK_SAP_BASIC;
+#else
         LOC_LOGD("%s:%d]: Setting SAP to mode: DISABLED", __func__, __LINE__);
+#endif
     }
     else {
        LOC_LOGE("%s:%d]: Unrecognized value for SAP Mode."\
@@ -669,56 +689,56 @@
     }
 
     // Set service mask for ODCPI
-    if(strcmp(conf.feature_odcpi, "BASIC") == 0) {
+    if (strcmp(conf.feature_odcpi, "BASIC") == 0) {
         LOC_LOGD("%s:%d]: Setting ODCPI to mode: BASIC", __func__, __LINE__);
         loc_service_mask |= LOC_FEATURE_MASK_ODCPI;
     }
-    else if(strcmp(conf.feature_odcpi, "DISABLED") == 0) {
+    else if (strcmp(conf.feature_odcpi, "DISABLED") == 0) {
         LOC_LOGD("%s:%d]: Setting ODCPI to mode: DISABLED", __func__, __LINE__);
     }
-    else if(strcmp(conf.feature_odcpi, "PREMIUM") == 0) {
+    else if (strcmp(conf.feature_odcpi, "PREMIUM") == 0) {
         LOC_LOGD("%s:%d]: Unrecognized value for ODCPI mode."\
             "Setting ODCPI to default mode: BASIC", __func__, __LINE__);
         loc_service_mask |= LOC_FEATURE_MASK_ODCPI;
     }
 
     // Set service mask for FREE_WIFI_SCAN_INJECT
-    if(strcmp(conf.feature_free_wifi_scan_inject, "BASIC") == 0) {
+    if (strcmp(conf.feature_free_wifi_scan_inject, "BASIC") == 0) {
         LOC_LOGD("%s:%d]: Setting FREE_WIFI_SCAN_INJECT to mode: BASIC", __func__, __LINE__);
         loc_service_mask |= LOC_FEATURE_MASK_FREE_WIFI_SCAN_INJECT;
     }
-    else if(strcmp(conf.feature_free_wifi_scan_inject, "DISABLED") == 0) {
+    else if (strcmp(conf.feature_free_wifi_scan_inject, "DISABLED") == 0) {
         LOC_LOGD("%s:%d]: Setting FREE_WIFI_SCAN_INJECT to mode: DISABLED", __func__, __LINE__);
     }
-    else if(strcmp(conf.feature_free_wifi_scan_inject, "PREMIUM") == 0) {
+    else if (strcmp(conf.feature_free_wifi_scan_inject, "PREMIUM") == 0) {
         LOC_LOGD("%s:%d]: Unrecognized value for FREE_WIFI_SCAN_INJECT mode."\
             "Setting FREE_WIFI_SCAN_INJECT to default mode: BASIC", __func__, __LINE__);
         loc_service_mask |= LOC_FEATURE_MASK_FREE_WIFI_SCAN_INJECT;
     }
 
     // Set service mask for SUPL_WIFI
-    if(strcmp(conf.feature_supl_wifi, "BASIC") == 0) {
+    if (strcmp(conf.feature_supl_wifi, "BASIC") == 0) {
         LOC_LOGD("%s:%d]: Setting SUPL_WIFI to mode: BASIC", __func__, __LINE__);
         loc_service_mask |= LOC_FEATURE_MASK_SUPL_WIFI;
     }
-    else if(strcmp(conf.feature_supl_wifi, "DISABLED") == 0) {
+    else if (strcmp(conf.feature_supl_wifi, "DISABLED") == 0) {
         LOC_LOGD("%s:%d]: Setting SUPL_WIFI to mode: DISABLED", __func__, __LINE__);
     }
-    else if(strcmp(conf.feature_supl_wifi, "PREMIUM") == 0) {
+    else if (strcmp(conf.feature_supl_wifi, "PREMIUM") == 0) {
         LOC_LOGD("%s:%d]: Unrecognized value for SUPL_WIFI mode."\
             "Setting SUPL_WIFI to default mode: BASIC", __func__, __LINE__);
         loc_service_mask |= LOC_FEATURE_MASK_SUPL_WIFI;
     }
 
     // Set service mask for WIFI_SUPPLICANT_INFO
-    if(strcmp(conf.feature_wifi_supplicant_info, "BASIC") == 0) {
+    if (strcmp(conf.feature_wifi_supplicant_info, "BASIC") == 0) {
         LOC_LOGD("%s:%d]: Setting WIFI_SUPPLICANT_INFO to mode: BASIC", __func__, __LINE__);
         loc_service_mask |= LOC_FEATURE_MASK_WIFI_SUPPLICANT_INFO;
     }
-    else if(strcmp(conf.feature_wifi_supplicant_info, "DISABLED") == 0) {
+    else if (strcmp(conf.feature_wifi_supplicant_info, "DISABLED") == 0) {
         LOC_LOGD("%s:%d]: Setting WIFI_SUPPLICANT_INFO to mode: DISABLED", __func__, __LINE__);
     }
-    else if(strcmp(conf.feature_wifi_supplicant_info, "PREMIUM") == 0) {
+    else if (strcmp(conf.feature_wifi_supplicant_info, "PREMIUM") == 0) {
         LOC_LOGD("%s:%d]: Unrecognized value for WIFI_SUPPLICANT_INFO mode."\
             "Setting LOC_FEATURE_MASK_WIFI_SUPPLICANT_INFO to default mode: BASIC", __func__, __LINE__);
         loc_service_mask |= LOC_FEATURE_MASK_WIFI_SUPPLICANT_INFO;
@@ -801,13 +821,13 @@
             continue;
         }
 
-        if(strcmp(conf.proc_status, "DISABLED") == 0) {
+        if (strcmp(conf.proc_status, "DISABLED") == 0) {
             LOC_LOGD("%s:%d]: Process %s is disabled in conf file",
                      __func__, __LINE__, conf.proc_name);
             child_proc[j].proc_status = DISABLED_FROM_CONF;
             continue;
         }
-        else if(strcmp(conf.proc_status, "ENABLED") == 0) {
+        else if (strcmp(conf.proc_status, "ENABLED") == 0) {
             LOC_LOGD("%s:%d]: Process %s is enabled in conf file",
                      __func__, __LINE__, conf.proc_name);
         }
@@ -832,7 +852,7 @@
         }
 
         nstrings = loc_util_split_string(conf.platform_list, split_strings, MAX_NUM_STRINGS, ' ');
-        if(strcmp("all", split_strings[0]) == 0) {
+        if (strcmp("all", split_strings[0]) == 0) {
             if (nstrings == 1 || (nstrings == 2 && (strcmp("exclude", split_strings[1]) == 0))) {
                 LOC_LOGD("%s:%d]: Enabled for all targets\n", __func__, __LINE__);
                 config_mask |= CONFIG_MASK_TARGET_ALL;
@@ -840,7 +860,7 @@
             else if (nstrings > 2 && (strcmp("exclude", split_strings[1]) == 0)) {
                 config_mask |= CONFIG_MASK_TARGET_FOUND;
                 for (i=2; i<nstrings; i++) {
-                    if(strcmp(platform_name, split_strings[i]) == 0) {
+                    if (strcmp(platform_name, split_strings[i]) == 0) {
                         LOC_LOGD("%s:%d]: Disabled platform %s\n", __func__, __LINE__, platform_name);
                         config_mask &= ~CONFIG_MASK_TARGET_FOUND;
                         break;
@@ -850,7 +870,7 @@
         }
         else {
             for(i=0; i<nstrings; i++) {
-                if(strcmp(platform_name, split_strings[i]) == 0) {
+                if (strcmp(platform_name, split_strings[i]) == 0) {
                     LOC_LOGD("%s:%d]: Matched platform: %s\n",
                              __func__, __LINE__, split_strings[i]);
                     config_mask |= CONFIG_MASK_TARGET_FOUND;
@@ -888,7 +908,7 @@
         }
 
         nstrings = loc_util_split_string(conf.baseband, split_strings, MAX_NUM_STRINGS, ' ');
-        if(strcmp("all", split_strings[0]) == 0) {
+        if (strcmp("all", split_strings[0]) == 0) {
             if (nstrings == 1 || (nstrings == 2 && (strcmp("exclude", split_strings[1]) == 0))) {
                 LOC_LOGD("%s:%d]: Enabled for all basebands\n", __func__, __LINE__);
                 config_mask |= CONFIG_MASK_BASEBAND_ALL;
@@ -896,7 +916,7 @@
             else if (nstrings > 2 && (strcmp("exclude", split_strings[1]) == 0)) {
                 config_mask |= CONFIG_MASK_BASEBAND_FOUND;
                 for (i=2; i<nstrings; i++) {
-                    if(strcmp(baseband_name, split_strings[i]) == 0) {
+                    if (strcmp(baseband_name, split_strings[i]) == 0) {
                         LOC_LOGD("%s:%d]: Disabled band %s\n", __func__, __LINE__, baseband_name);
                         config_mask &= ~CONFIG_MASK_BASEBAND_FOUND;
                         break;
@@ -906,7 +926,7 @@
         }
         else {
             for(i=0; i<nstrings; i++) {
-                if(strcmp(baseband_name, split_strings[i]) == 0) {
+                if (strcmp(baseband_name, split_strings[i]) == 0) {
                     LOC_LOGD("%s:%d]: Matched baseband: %s\n",
                              __func__, __LINE__, split_strings[i]);
                     config_mask |= CONFIG_MASK_BASEBAND_FOUND;
@@ -924,13 +944,13 @@
         }
 
         nstrings = loc_util_split_string(conf.auto_platform, split_strings, MAX_NUM_STRINGS, ' ');
-        if(strcmp("all", split_strings[0]) == 0) {
+        if (strcmp("all", split_strings[0]) == 0) {
             LOC_LOGD("%s:%d]: Enabled for all auto platforms\n", __func__, __LINE__);
             config_mask |= CONFIG_MASK_AUTOPLATFORM_ALL;
         }
         else {
             for(i=0; i<nstrings; i++) {
-                if(strcmp(autoplatform_name, split_strings[i]) == 0) {
+                if (strcmp(autoplatform_name, split_strings[i]) == 0) {
                     LOC_LOGD("%s:%d]: Matched auto platform: %s\n",
                              __func__, __LINE__, split_strings[i]);
                     config_mask |= CONFIG_MASK_AUTOPLATFORM_FOUND;
@@ -961,7 +981,7 @@
             i = 0;
             char* temp_arg = ('/' == child_proc[j].name[0][0]) ?
                 (strrchr(child_proc[j].name[0], '/') + 1) : child_proc[j].name[0];
-            strlcpy (child_proc[j].args[i++], temp_arg, sizeof (child_proc[j].args[i++]));
+            strlcpy (child_proc[j].args[i++], temp_arg, sizeof (child_proc[j].args[0]));
 
             if(conf.premium_feature) {
                if(conf.loc_feature_mask & loc_service_mask) {
diff --git a/utils/loc_cfg.h b/utils/loc_cfg.h
index 5c77dc6..e87d632 100644
--- a/utils/loc_cfg.h
+++ b/utils/loc_cfg.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2015, 2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2015, 2018, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -56,14 +56,18 @@
 #define LOC_PROCESS_MAX_ARG_STR_LENGTH 32
 
 #define UTIL_UPDATE_CONF(conf_data, len, config_table) \
-    loc_update_conf((conf_data), (len), (config_table), \
+    loc_update_conf((conf_data), (len), (&config_table[0]), \
                     sizeof(config_table) / sizeof(config_table[0]))
 
 #define UTIL_READ_CONF_DEFAULT(filename) \
     loc_read_conf((filename), NULL, 0);
 
 #define UTIL_READ_CONF(filename, config_table) \
-    loc_read_conf((filename), (config_table), sizeof(config_table) / sizeof(config_table[0]))
+    loc_read_conf((filename), (&config_table[0]), sizeof(config_table) / sizeof(config_table[0]))
+
+#define UTIL_READ_CONF_LONG(filename, config_table, rec_len) \
+    loc_read_conf_long((filename), (&config_table[0]), \
+            sizeof(config_table) / sizeof(config_table[0]), (rec_len))
 
 /*=============================================================================
  *
@@ -115,13 +119,30 @@
  *============================================================================*/
 bool isVendorEnhanced();
 void setVendorEnhanced(bool vendorEnhanced);
-void loc_read_conf(const char* conf_file_name,
-                   const loc_param_s_type* config_table,
-                   uint32_t table_length);
-int loc_read_conf_r(FILE *conf_fp, const loc_param_s_type* config_table,
-                    uint32_t table_length);
-int loc_update_conf(const char* conf_data, int32_t length,
-                    const loc_param_s_type* config_table, uint32_t table_length);
+void loc_read_conf_long(const char* conf_file_name,
+                        const loc_param_s_type* config_table,
+                        uint32_t table_length, uint16_t string_len);
+int loc_read_conf_r_long(FILE *conf_fp, const loc_param_s_type* config_table,
+                         uint32_t table_length, uint16_t string_len);
+int loc_update_conf_long(const char* conf_data, int32_t length,
+                         const loc_param_s_type* config_table, uint32_t table_length,
+                         uint16_t string_len);
+
+inline void loc_read_conf(const char* conf_file_name,
+                          const loc_param_s_type* config_table, uint32_t table_length) {
+    loc_read_conf_long(conf_file_name, config_table, table_length, LOC_MAX_PARAM_STRING);
+}
+
+inline int loc_read_conf_r(FILE *conf_fp, const loc_param_s_type* config_table,
+                    uint32_t table_length) {
+    return (loc_read_conf_r_long(conf_fp, config_table, table_length, LOC_MAX_PARAM_STRING));
+}
+
+inline int loc_update_conf(const char* conf_data, int32_t length,
+                    const loc_param_s_type* config_table, uint32_t table_length) {
+    return (loc_update_conf_long(
+                    conf_data, length, config_table, table_length, LOC_MAX_PARAM_STRING));
+}
 
 // Below are the location conf file paths
 extern const char LOC_PATH_GPS_CONF[];
@@ -132,6 +153,9 @@
 extern const char LOC_PATH_APDR_CONF[];
 extern const char LOC_PATH_XTWIFI_CONF[];
 extern const char LOC_PATH_QUIPC_CONF[];
+extern const char LOC_PATH_ANT_CORR[];
+extern const char LOC_PATH_SLIM_CONF[];
+extern const char LOC_PATH_VPE_CONF[];
 
 int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_ptr,
                           loc_process_info_s_type** process_info_table_ptr);
diff --git a/utils/loc_gps.h b/utils/loc_gps.h
index eae7383..90541c4 100644
--- a/utils/loc_gps.h
+++ b/utils/loc_gps.h
@@ -106,6 +106,8 @@
 #define LOC_GPS_LOCATION_HAS_SPEED_ACCURACY   0x0100
 /** LocGpsLocation has valid bearing accuracy */
 #define LOC_GPS_LOCATION_HAS_BEARING_ACCURACY 0x0200
+/** LocGpsLocation has valid Real Time and Real Time Uncertainty */
+#define LOC_GPS_LOCATION_HAS_ELAPSED_REAL_TIME 0x0400
 
 /** Spoof mask in LocGpsLocation */
 typedef uint32_t LocGpsSpoofMask;
@@ -570,7 +572,11 @@
     /** Represents the expected vertical uncertainity in meters*/
     float           vertUncertainity;
     /** Timestamp for the location fix. */
-    LocGpsUtcTime      timestamp;
+    LocGpsUtcTime   timestamp;
+    /** Elapsed RealTime in nanosends */
+    uint64_t        elapsedRealTime;
+    /** Elapsed Real Time Uncertainty in nanosends */
+    uint64_t        elapsedRealTimeUnc;
 } LocGpsLocation;
 
 /** Represents the status. */
diff --git a/utils/loc_log.cpp b/utils/loc_log.cpp
index 2c6a3fa..2110683 100644
--- a/utils/loc_log.cpp
+++ b/utils/loc_log.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2012, 2015, 2020, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -38,8 +38,13 @@
 #include "msg_q.h"
 #include <loc_pla.h>
 #include "LogBuffer.h"
-
+#include <unordered_map>
+#include <fstream>
+#include <algorithm>
+#include <string>
+#include <cctype>
 #define  BUFFER_SIZE  120
+#define  LOG_TAG_LEVEL_CONF_FILE_PATH "/data/vendor/location/gps.prop"
 
 // Logging Improvements
 const char *loc_logger_boolStr[]={"False","True"};
@@ -52,38 +57,49 @@
 const char ENTRY_TAG[]  = "Entering";
 const char EXIT_ERROR_TAG[]  = "Exiting with error";
 
+int build_type_prop = BUILD_TYPE_PROP_NA;
+
+const string gEmptyStr = "";
+const string gUnknownStr = "UNKNOWN";
 /* Logging Mechanism */
 loc_logger_s_type loc_logger;
 
-/* Get names from value */
-const char* loc_get_name_from_mask(const loc_name_val_s_type table[], size_t table_size, long mask)
-{
-   size_t i;
-   for (i = 0; i < table_size; i++)
-   {
-      if (table[i].val & (long) mask)
-      {
-         return table[i].name;
-      }
-   }
-   return UNKNOWN_STR;
+/* tag base logging control map*/
+static std::unordered_map<std::string, uint8_t> tag_level_map;
+static bool tag_map_inited = false;
+
+/* returns the least signification bit that is set in the mask
+   Param
+      mask -        bit mask.
+      clearTheBit - if true, mask gets modified upon return.
+   returns 0 if mask is 0.
+*/
+uint64_t loc_get_least_bit(uint64_t& mask, bool clearTheBit) {
+    uint64_t bit = 0;
+
+    if (mask > 0) {
+        uint64_t less1 = mask - 1;
+        bit = mask & ~(less1);
+        if (clearTheBit) {
+            mask &= less1;
+        }
+    }
+
+    return bit;
 }
 
-/* Get names from value */
-const char* loc_get_name_from_val(const loc_name_val_s_type table[], size_t table_size, long value)
-{
-   size_t i;
-   for (i = 0; i < table_size; i++)
-   {
-      if (table[i].val == (long) value)
-      {
-         return table[i].name;
-      }
-   }
-   return UNKNOWN_STR;
+string loc_get_bit_defs(uint64_t mask, const NameValTbl& tbl) {
+    string out;
+    while (mask > 0) {
+        out += loc_get_name_from_tbl(tbl, loc_get_least_bit(mask));
+        if (mask > 0) {
+            out += " | ";
+        }
+    }
+    return out;
 }
 
-static const loc_name_val_s_type loc_msg_q_status[] =
+DECLARE_TBL(loc_msg_q_status) =
 {
     NAME_VAL( eMSG_Q_SUCCESS ),
     NAME_VAL( eMSG_Q_FAILURE_GENERAL ),
@@ -92,21 +108,15 @@
     NAME_VAL( eMSG_Q_UNAVAILABLE_RESOURCE ),
     NAME_VAL( eMSG_Q_INSUFFICIENT_BUFFER )
 };
-static const size_t loc_msg_q_status_num = LOC_TABLE_SIZE(loc_msg_q_status);
 
 /* Find msg_q status name */
 const char* loc_get_msg_q_status(int status)
 {
-   return loc_get_name_from_val(loc_msg_q_status, loc_msg_q_status_num, (long) status);
-}
-
-const char* log_succ_fail_string(int is_succ)
-{
-   return is_succ? "successful" : "failed";
+   return loc_get_name_from_val(loc_msg_q_status_tbl, (int64_t) status);
 }
 
 //Target names
-static const loc_name_val_s_type target_name[] =
+DECLARE_TBL(target_name) =
 {
     NAME_VAL(GNSS_NONE),
     NAME_VAL(GNSS_MSM),
@@ -116,8 +126,6 @@
     NAME_VAL(GNSS_UNKNOWN)
 };
 
-static const size_t target_name_num = LOC_TABLE_SIZE(target_name);
-
 /*===========================================================================
 
 FUNCTION loc_get_target_name
@@ -133,21 +141,13 @@
 ===========================================================================*/
 const char *loc_get_target_name(unsigned int target)
 {
-    int index = 0;
+    int64_t index = 0;
     static char ret[BUFFER_SIZE];
 
-    index =  getTargetGnssType(target);
-    if( index < 0 || (unsigned)index >= target_name_num )
-        index = target_name_num - 1;
+    snprintf(ret, sizeof(ret), " %s with%s SSC",
+             loc_get_name_from_val(target_name_tbl, getTargetGnssType(target)),
+             ((target & HAS_SSC) == HAS_SSC) ? gEmptyStr.c_str() : "out");
 
-    if( (target & HAS_SSC) == HAS_SSC ) {
-        snprintf(ret, sizeof(ret), " %s with SSC",
-           loc_get_name_from_val(target_name, target_name_num, (long)index) );
-    }
-    else {
-       snprintf(ret, sizeof(ret), " %s  without SSC",
-           loc_get_name_from_val(target_name, target_name_num, (long)index) );
-    }
     return ret;
 }
 
@@ -228,3 +228,55 @@
     string ss = str;
     loc_util::LogBuffer::getInstance()->append(ss, level, elapsedTime);
 }
+
+void log_tag_level_map_init()
+{
+    if (tag_map_inited) {
+        return;
+    }
+
+    std::string filename = LOG_TAG_LEVEL_CONF_FILE_PATH;
+
+    std::ifstream s(filename);
+    if (!s.is_open()) {
+        ALOGE("cannot open file:%s", LOG_TAG_LEVEL_CONF_FILE_PATH);
+    } else {
+        std::string line;
+        while (std::getline(s, line)) {
+            line.erase(std::remove(line.begin(), line.end(), ' '), line.end());
+            int pos = line.find('=');
+            if (pos <= 0 || pos >= (line.size() - 1)) {
+                ALOGE("wrong format in gps.prop");
+                continue;
+            }
+            std::string tag = line.substr(0, pos);
+            std::string level = line.substr(pos+1, 1);
+            if (!std::isdigit(*(level.begin()))) {
+                ALOGE("wrong format in gps.prop");
+                continue;
+            }
+            tag_level_map[tag] = (uint8_t)std::stoul(level);
+        }
+    }
+    tag_map_inited = true;
+}
+
+int get_tag_log_level(const char* tag)
+{
+    if (!tag_map_inited) {
+        return -1;
+    }
+
+    // in case LOG_TAG isn't defined in a source file, use the global log level
+    if (tag == NULL) {
+        return loc_logger.DEBUG_LEVEL;
+    }
+    int log_level;
+    auto search = tag_level_map.find(std::string(tag));
+    if (tag_level_map.end() != search) {
+        log_level = search->second;
+    } else {
+        log_level = loc_logger.DEBUG_LEVEL;
+    }
+    return log_level;
+}
diff --git a/utils/loc_log.h b/utils/loc_log.h
index be492b1..b750932 100644
--- a/utils/loc_log.h
+++ b/utils/loc_log.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, 2015 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2012, 2015, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -30,42 +30,93 @@
 #ifndef LOC_LOG_H
 #define LOC_LOG_H
 
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
 #include <ctype.h>
 #include <stdlib.h>
+#include <unordered_map>
+#include <string>
 #include "loc_target.h"
+#include "loc_misc_utils.h"
 
-typedef struct
-{
-   const char *name;
-   long        val;
-} loc_name_val_s_type;
+using std::string;
+using std::unordered_map;
 
-#define NAME_VAL(x) {"" #x "", x }
+typedef unordered_map<int64_t, string> NameValTbl;
 
-#define UNKNOWN_STR "UNKNOWN"
+#define NAME_VAL(x) {x, "" #x ""}
+#define DECLARE_TBL(T) static const NameValTbl T##_tbl
+
+extern const string gEmptyStr;
+extern const string gUnknownStr;
 
 #define CHECK_MASK(type, value, mask_var, mask) \
    (((mask_var) & (mask)) ? (type) (value) : (type) (-1))
 
 #define LOC_TABLE_SIZE(table) (sizeof(table)/sizeof((table)[0]))
 
+#define FIELDVAL_DEC(field) \
+        loc_put_tag_val(#field, to_string(field))
+#define FIELDVAL_DEC_ARR(field) \
+        loc_put_tag_val(#field, \
+                        loc_parenthesize(loc_prim_arr_to_string(field, \
+                                                                sizeof(field)/sizeof(field[0]))))
+#define FIELDVAL_HEX(field) \
+        loc_put_tag_val(#field, to_string_hex(field))
+#define FIELDVAL_HEX_ARR(field) \
+        loc_put_tag_val(#field, \
+                        loc_parenthesize(loc_prim_arr_to_string(field, \
+                                                                sizeof(field)/sizeof(field[0]), \
+                                                                false)))
+#define FIELDVAL_ENUM(field, tbl) \
+        loc_put_tag_val(#field, \
+                        loc_get_name_from_tbl(tbl, field, gUnknownStr))
+#define FIELDVAL_MASK(field, tbl) \
+        loc_put_tag_val(#field, \
+                        to_string_hex((uint64_t)field) + " " + \
+                                loc_parenthesize(loc_get_bit_defs(field, tbl)))
+
+/* get from a table of strings with index */
+/* tbl - map of <int, string> entries
+   key - key to the matching entry
+   defalt - default pointer in case of incorrect parameters
+ */
+inline static const string& loc_get_name_from_tbl(const NameValTbl& tbl, int64_t key,
+                                    const string& defalt = gEmptyStr) {
+    auto item = tbl.find(key);
+    if (item != tbl.end()) {
+        return item->second;
+    } else {
+        return defalt;
+    }
+}
+
+/* puts to string formatted "TAG: VAL" with option ending string, default to newline */
+inline string loc_put_tag_val(const string& tag, const string& val, const string& eol = "\n") {
+    return tag + ": " + val + eol;
+}
+
+inline string loc_parenthesize(const string& str) {
+    return "(" + str + ")";
+}
+
 /* Get names from value */
-const char* loc_get_name_from_mask(const loc_name_val_s_type table[], size_t table_size, long mask);
-const char* loc_get_name_from_val(const loc_name_val_s_type table[], size_t table_size, long value);
+inline const char* loc_get_name_from_val(const NameValTbl& table, int64_t value) {
+    return loc_get_name_from_tbl(table, value, gUnknownStr).c_str();
+}
+
+inline const char* log_succ_fail_string(int is_succ) {
+    return is_succ? "successful" : "failed";
+}
+
+/* prints mask into a string with bit definitions from tbl */
+/* mask - bit mask, to be expanded into " BIT_NAMEx | BIT_NAMEy ... "
+   tbl - a table with defs for each bit, defined as <bit, name> entries
+         {{bit0, "BIT0_NAME"}, {bit1, "BIT1_NAME"}, .... {bitn, "BITn_NAME"} }
+   entries - number of strings in the table
+ */
+string loc_get_bit_defs(uint64_t mask, const NameValTbl& tbl);
+uint64_t loc_get_least_bit(uint64_t& mask, bool clearThebit = true);
 const char* loc_get_msg_q_status(int status);
 const char* loc_get_target_name(unsigned int target);
-
-extern const char* log_succ_fail_string(int is_succ);
-
-extern char *loc_get_time(char *time_string, size_t buf_size);
-
-#ifdef __cplusplus
-}
-#endif
+char *loc_get_time(char *time_string, size_t buf_size);
 
 #endif /* LOC_LOG_H */
diff --git a/utils/loc_misc_utils.cpp b/utils/loc_misc_utils.cpp
index 70fdbc3..fbcaef4 100644
--- a/utils/loc_misc_utils.cpp
+++ b/utils/loc_misc_utils.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -30,11 +30,19 @@
 #define LOG_TAG "LocSvc_misc_utils"
 #include <stdio.h>
 #include <string.h>
+#include <inttypes.h>
 #include <dlfcn.h>
+#include <math.h>
 #include <log_util.h>
 #include <loc_misc_utils.h>
 #include <ctype.h>
+#include <fcntl.h>
+#include <inttypes.h>
 
+#ifndef MSEC_IN_ONE_SEC
+#define MSEC_IN_ONE_SEC 1000ULL
+#endif
+#define GET_MSEC_FROM_TS(ts) ((ts.tv_sec * MSEC_IN_ONE_SEC) + (ts.tv_nsec + 500000)/1000000)
 
 int loc_util_split_string(char *raw_string, char **split_strings_ptr,
                           int max_num_substrings, char delimiter)
@@ -57,8 +65,10 @@
             end_string=1;
         if((raw_string[raw_string_index] == delimiter) || end_string) {
             raw_string[raw_string_index] = '\0';
-            LOC_LOGD("%s:%d]: split string: %s\n",
-                     __func__, __LINE__, split_strings_ptr[num_split_strings]);
+            if (num_split_strings < max_num_substrings) {
+                LOC_LOGD("%s:%d]: split string: %s\n",
+                         __func__, __LINE__, split_strings_ptr[num_split_strings]);
+            }
             num_split_strings++;
             if(((raw_string_index + 1) < raw_string_length) &&
                (num_split_strings < max_num_substrings)) {
@@ -143,3 +153,199 @@
 
     return sym;
 }
+
+uint64_t getQTimerTickCount()
+{
+    uint64_t qTimerCount = 0;
+#if __aarch64__
+    asm volatile("mrs %0, cntvct_el0" : "=r" (qTimerCount));
+#elif defined (__i386__) || defined (__x86_64__)
+    /* Qtimer not supported in x86 architecture */
+    qTimerCount = 0;
+#else
+    asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (qTimerCount));
+#endif
+
+    return qTimerCount;
+}
+
+uint64_t getQTimerDeltaNanos()
+{
+    char qtimer_val_string[100];
+    char *temp;
+    uint64_t local_qtimer = 0, remote_qtimer = 0;
+    int mdm_fd = -1, wlan_fd = -1, ret = 0;
+    uint64_t delta = 0;
+
+    memset(qtimer_val_string, '\0', sizeof(qtimer_val_string));
+
+    char devNode[] = "/sys/bus/mhi/devices/0306_00.01.00/time_us";
+    for (; devNode[27] < 3 && mdm_fd < 0; devNode[27]++) {
+        mdm_fd = ::open(devNode, O_RDONLY);
+        if (mdm_fd < 0) {
+            LOC_LOGe("MDM open file: %s error: %s", devNode, strerror(errno));
+        }
+    }
+    if (mdm_fd > 0) {
+        ret = read(mdm_fd, qtimer_val_string, sizeof(qtimer_val_string)-1);
+        ::close(mdm_fd);
+        if (ret < 0) {
+            LOC_LOGe("MDM read time_us file error: %s", strerror(errno));
+        } else {
+            temp = qtimer_val_string;
+            temp = strchr(temp, ':');
+            temp = temp + 2;
+            local_qtimer = atoll(temp);
+
+            temp = strchr(temp, ':');
+            temp = temp + 2;
+            remote_qtimer = atoll(temp);
+
+            if (local_qtimer >= remote_qtimer) {
+                delta = (local_qtimer - remote_qtimer) * 1000;
+            }
+            LOC_LOGv("qtimer values in microseconds: local:%" PRIi64 " remote:%" PRIi64 ""
+                     " delta in nanoseconds:%" PRIi64 "",
+                     local_qtimer, remote_qtimer, delta);
+        }
+    }
+    return delta;
+}
+
+uint64_t getQTimerFreq()
+{
+#if __aarch64__
+    uint64_t val = 0;
+    asm volatile("mrs %0, cntfrq_el0" : "=r" (val));
+#elif defined (__i386__) || defined (__x86_64__)
+    /* Qtimer not supported in x86 architecture */
+    uint64_t val = 0;
+#else
+    uint32_t val = 0;
+    asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val));
+#endif
+    return val;
+}
+
+uint64_t getBootTimeMilliSec()
+{
+    struct timespec curTs;
+    clock_gettime(CLOCK_BOOTTIME, &curTs);
+    return (uint64_t)GET_MSEC_FROM_TS(curTs);
+}
+
+// Used for convert position/velocity from GSNS antenna based to VRP based
+void Matrix_MxV(float a[3][3],  float b[3], float c[3]) {
+    int i, j;
+
+    for (i=0; i<3; i++) {
+        c[i] = 0.0f;
+        for (j=0; j<3; j++)
+            c[i] += a[i][j] * b[j];
+    }
+}
+
+// Used for convert position/velocity from GNSS antenna based to VRP based
+void Matrix_Skew(float a[3], float c[3][3]) {
+    c[0][0] = 0.0f;
+    c[0][1] = -a[2];
+    c[0][2] = a[1];
+    c[1][0] = a[2];
+    c[1][1] = 0.0f;
+    c[1][2] = -a[0];
+    c[2][0] = -a[1];
+    c[2][1] = a[0];
+    c[2][2] = 0.0f;
+}
+
+// Used for convert position/velocity from GNSS antenna based to VRP based
+void Euler2Dcm(float euler[3], float dcm[3][3]) {
+    float cr = 0.0, sr = 0.0, cp = 0.0, sp = 0.0, ch = 0.0, sh = 0.0;
+
+    cr = cosf(euler[0]);
+    sr = sinf(euler[0]);
+    cp = cosf(euler[1]);
+    sp = sinf(euler[1]);
+    ch = cosf(euler[2]);
+    sh = sinf(euler[2]);
+
+    dcm[0][0] = cp * ch;
+    dcm[0][1] = (sp*sr*ch) - (cr*sh);
+    dcm[0][2] = (cr*sp*ch) + (sh*sr);
+
+    dcm[1][0] = cp * sh;
+    dcm[1][1] = (sr*sp*sh) + (cr*ch);
+    dcm[1][2] = (cr*sp*sh) - (sr*ch);
+
+    dcm[2][0] = -sp;
+    dcm[2][1] = sr * cp;
+    dcm[2][2] = cr * cp;
+}
+
+// Used for convert position from GSNS based to VRP based
+// The converted position will be stored in the llaInfo parameter.
+#define A6DOF_WGS_A (6378137.0f)
+#define A6DOF_WGS_B (6335439.0f)
+#define A6DOF_WGS_E2 (0.00669437999014f)
+void loc_convert_lla_gnss_to_vrp(double lla[3], float rollPitchYaw[3],
+                                 float leverArm[3]) {
+    LOC_LOGv("lla: %f, %f, %f, lever arm: %f %f %f, "
+             "rollpitchyaw: %f %f %f",
+             lla[0], lla[1], lla[2],
+             leverArm[0], leverArm[1], leverArm[2],
+             rollPitchYaw[0], rollPitchYaw[1], rollPitchYaw[2]);
+
+    float cnb[3][3];
+    memset(cnb, 0, sizeof(cnb));
+    Euler2Dcm(rollPitchYaw, cnb);
+
+    float sl = sin(lla[0]);
+    float cl = cos(lla[0]);
+    float sf = 1.0f / (1.0f - A6DOF_WGS_E2 * sl* sl);
+    float sfr = sqrtf(sf);
+
+    float rn = A6DOF_WGS_B * sf * sfr + lla[2];
+    float re = A6DOF_WGS_A * sfr + lla[2];
+
+    float deltaNEU[3];
+
+    // gps_pos_lla = imu_pos_lla + Cbn*la_b .* [1/geo.Rn; 1/(geo.Re*geo.cL); -1];
+    Matrix_MxV(cnb, leverArm, deltaNEU);
+
+    // NED to lla conversion
+    lla[0] = lla[0] + deltaNEU[0] / rn;
+    lla[1] = lla[1] + deltaNEU[1] / (re * cl);
+    lla[2] = lla[2] + deltaNEU[2];
+}
+
+// Used for convert velocity from GSNS based to VRP based
+// The converted velocity will be stored in the enuVelocity parameter.
+void loc_convert_velocity_gnss_to_vrp(float enuVelocity[3], float rollPitchYaw[3],
+                                      float rollPitchYawRate[3], float leverArm[3]) {
+
+    LOC_LOGv("enu velocity: %f, %f, %f, lever arm: %f %f %f, roll pitch yaw: %f %f %f,"
+             "rollpitchyawRate: %f %f %f",
+             enuVelocity[0], enuVelocity[1], enuVelocity[2],
+             leverArm[0], leverArm[1], leverArm[2],
+             rollPitchYaw[0], rollPitchYaw[1], rollPitchYaw[2],
+             rollPitchYawRate[0], rollPitchYawRate[1], rollPitchYawRate[2]);
+
+    float cnb[3][3];
+    memset(cnb, 0, sizeof(cnb));
+    Euler2Dcm(rollPitchYaw, cnb);
+
+    float skewLA[3][3];
+    memset(skewLA, 0, sizeof(skewLA));
+    Matrix_Skew(leverArm, skewLA);
+
+    float tmp[3];
+    float deltaEnuVelocity[3];
+    memset(tmp, 0, sizeof(tmp));
+    memset(deltaEnuVelocity, 0, sizeof(deltaEnuVelocity));
+    Matrix_MxV(skewLA, rollPitchYawRate, tmp);
+    Matrix_MxV(cnb, tmp, deltaEnuVelocity);
+
+    enuVelocity[0] = enuVelocity[0] - deltaEnuVelocity[0];
+    enuVelocity[1] = enuVelocity[1] - deltaEnuVelocity[1];
+    enuVelocity[2] = enuVelocity[2] - deltaEnuVelocity[2];
+}
diff --git a/utils/loc_misc_utils.h b/utils/loc_misc_utils.h
index fad1b6d..2335e57 100644
--- a/utils/loc_misc_utils.h
+++ b/utils/loc_misc_utils.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -28,11 +28,16 @@
  */
 #ifndef _LOC_MISC_UTILS_H_
 #define _LOC_MISC_UTILS_H_
+#include <stdint.h>
+#include <ios>
+#include <string>
+#include <sstream>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
-
+#include <stddef.h>
+#include <stdint.h>
 /*===========================================================================
 FUNCTION loc_split_string
 
@@ -120,8 +125,197 @@
 ===========================================================================*/
 void* dlGetSymFromLib(void*& libHandle, const char* libName, const char* symName);
 
+/*===========================================================================
+FUNCTION getQTimerTickCount
+
+DESCRIPTION
+   This function is used to read the QTimer ticks count. This value is globally maintained and
+   must be the same across all processors on a target.
+
+DEPENDENCIES
+   N/A
+
+RETURN VALUE
+    uint64_t QTimer tick count
+
+SIDE EFFECTS
+   N/A
+===========================================================================*/
+uint64_t getQTimerTickCount();
+
+/*===========================================================================
+FUNCTION getQTimerDeltaNanos
+
+DESCRIPTION
+This function is used to read the the difference in nanoseconds between
+Qtimer on AP side and Qtimer on MP side for dual-SoC architectures such as Kona
+
+DEPENDENCIES
+N/A
+
+RETURN VALUE
+uint64_t QTimer difference in nanoseconds
+
+SIDE EFFECTS
+N/A
+===========================================================================*/
+uint64_t getQTimerDeltaNanos();
+
+/*===========================================================================
+FUNCTION getQTimerFreq
+
+DESCRIPTION
+   This function is used to read the QTimer frequency in hz. This value is globally maintained and
+   must be the same across all processors on a target.
+
+DEPENDENCIES
+   N/A
+
+RETURN VALUE
+    uint64_t QTimer frequency
+
+SIDE EFFECTS
+   N/A
+===========================================================================*/
+uint64_t getQTimerFreq();
+
+/*===========================================================================
+FUNCTION getBootTimeMilliSec
+
+DESCRIPTION
+   This function is used to get boot time in milliseconds.
+
+DEPENDENCIES
+   N/A
+
+RETURN VALUE
+    uint64_t boot time in milliseconds
+
+SIDE EFFECTS
+   N/A
+===========================================================================*/
+uint64_t getBootTimeMilliSec();
+
 #ifdef __cplusplus
 }
 #endif
 
+using std::hex;
+using std::string;
+using std::stringstream;
+
+/*===========================================================================
+FUNCTION to_string_hex
+
+DESCRIPTION
+   This function works similar to std::to_string, but puts only in hex format.
+
+DEPENDENCIES
+   N/A
+
+RETURN VALUE
+   string, of input val in hex format
+
+SIDE EFFECTS
+   N/A
+===========================================================================*/
+template <typename T>
+string to_string_hex(T val) {
+    stringstream ss;
+    if (val < 0) {
+        val = -val;
+        ss << "-";
+    }
+    ss << hex << "0x" << val;
+    return ss.str();
+}
+
+/*===========================================================================
+FUNCTION loc_prim_arr_to_string
+
+DESCRIPTION
+   This function puts out primitive array in DEC or EHX format.
+
+DEPENDENCIES
+   N/A
+
+RETURN VALUE
+    string, space separated string of values in the input array, either
+            in decimal or hex format, depending on the value of decIfTrue
+
+SIDE EFFECTS
+   N/A
+===========================================================================*/
+template <typename T>
+static string loc_prim_arr_to_string(T* arr, uint32_t size, bool decIfTrue = true) {
+    stringstream ss;
+    for (uint32_t i = 0; i < size; i++) {
+        ss << (decIfTrue ? to_string(arr[i]) : to_string_hex(arr[i]));
+        if (i != size - 1) {
+            ss << " ";
+        }
+    }
+    return ss.str();
+}
+
+/*===========================================================================
+FUNCTION qTimerTicksToNanos
+
+DESCRIPTION
+    Transform from ticks to nanoseconds, clock is 19.2 MHz
+    so the formula would be qtimer(ns) = (ticks * 1000000000) / 19200000
+    or simplified qtimer(ns) = (ticks * 10000) / 192.
+
+DEPENDENCIES
+    N/A
+
+RETURN VALUE
+    Qtimer value in nanoseconds
+
+SIDE EFFECTS
+    N/A
+===========================================================================*/
+inline uint64_t qTimerTicksToNanos(double qTimer) {
+    return (uint64_t((qTimer * double(10000ull)) / (double)192ull));
+}
+
+/*===========================================================================
+FUNCTION loc_convert_lla_gnss_to_vrp
+
+DESCRIPTION
+   This function converts lat/long/altitude from GNSS antenna based
+   to vehicle reference point based.
+
+DEPENDENCIES
+   N/A
+
+RETURN VALUE
+    The converted lat/long/altitude will be stored in the parameter of llaInfo.
+
+SIDE EFFECTS
+   N/A
+===========================================================================*/
+void loc_convert_lla_gnss_to_vrp(double lla[3], float rollPitchYaw[3],
+                                 float leverArm[3]);
+
+/*===========================================================================
+FUNCTION loc_convert_velocity_gnss_to_vrp
+
+DESCRIPTION
+   This function converts east/north/up velocity from GNSS antenna based
+   to vehicle reference point based.
+
+DEPENDENCIES
+   N/A
+
+RETURN VALUE
+    The converted east/north/up velocity will be stored in the parameter of
+    enuVelocity.
+
+SIDE EFFECTS
+   N/A
+===========================================================================*/
+void loc_convert_velocity_gnss_to_vrp(float enuVelocity[3], float rollPitchYaw[3],
+                                      float rollPitchYawRate[3], float leverArm[3]);
+
 #endif //_LOC_MISC_UTILS_H_
diff --git a/utils/loc_nmea.cpp b/utils/loc_nmea.cpp
index 9ee2716..3cd31cd 100644
--- a/utils/loc_nmea.cpp
+++ b/utils/loc_nmea.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -36,11 +36,16 @@
 #include <loc_cfg.h>
 
 #define GLONASS_SV_ID_OFFSET 64
-#define QZSS_SV_ID_OFFSET    (-192)
+#define SBAS_SV_ID_OFFSET    (87)
+#define QZSS_SV_ID_OFFSET    (192)
+#define BDS_SV_ID_OFFSET     (200)
+#define GALILEO_SV_ID_OFFSET (300)
+#define NAVIC_SV_ID_OFFSET   (400)
 #define MAX_SV_COUNT_SUPPORTED_IN_ONE_CONSTELLATION  64
 #define MAX_SATELLITES_IN_USE 12
 #define MSEC_IN_ONE_WEEK      604800000ULL
 #define UTC_GPS_OFFSET_MSECS  315964800000ULL
+#define MAX_TAG_BLOCK_GROUP_CODE  (99999)
 
 // GNSS system id according to NMEA spec
 #define SYSTEM_ID_GPS          1
@@ -110,7 +115,7 @@
 typedef struct loc_nmea_sv_meta_s
 {
     char talker[3];
-    LocGnssConstellationType svType;
+    uint32_t svTypeMask;
     uint64_t mask;
     uint32_t svCount;
     uint32_t totalSvUsedCount;
@@ -128,14 +133,18 @@
     uint64_t bds_used_mask;
     uint64_t navic_used_mask;
     uint32_t gps_l1_count;
+    uint32_t gps_l2_count;
     uint32_t gps_l5_count;
     uint32_t glo_g1_count;
     uint32_t glo_g2_count;
     uint32_t gal_e1_count;
     uint32_t gal_e5_count;
+    uint32_t gal_e5b_count;
     uint32_t qzss_l1_count;
+    uint32_t qzss_l2_count;
     uint32_t qzss_l5_count;
-    uint32_t bds_b1_count;
+    uint32_t bds_b1i_count;
+    uint32_t bds_b1c_count;
     uint32_t bds_b2_count;
     uint32_t navic_l5_count;
     float hdop;
@@ -285,6 +294,7 @@
 
     switch (signalType) {
         case GNSS_SIGNAL_GPS_L1CA:
+        case GNSS_SIGNAL_SBAS_L1:
             signalId = SIGNAL_ID_GPS_L1CA;
             break;
         case GNSS_SIGNAL_GPS_L2:
@@ -397,7 +407,7 @@
                                                bool needCombine)
 {
     memset(&sv_meta, 0, sizeof(sv_meta));
-    sv_meta.svType = svType;
+    sv_meta.svTypeMask = (1 << svType);
 
     switch (svType)
     {
@@ -406,10 +416,17 @@
             sv_meta.talker[1] = 'P';
             sv_meta.mask = sv_cache_info.gps_used_mask;
             sv_meta.systemId = SYSTEM_ID_GPS;
-            if (GNSS_SIGNAL_GPS_L1CA == signalType) {
-                sv_meta.svCount = sv_cache_info.gps_l1_count;
-            } else if (GNSS_SIGNAL_GPS_L5 == signalType) {
-                sv_meta.svCount = sv_cache_info.gps_l5_count;
+            sv_meta.svTypeMask |= (1 << GNSS_SV_TYPE_SBAS);
+            switch (signalType) {
+                case GNSS_SIGNAL_GPS_L1CA:
+                    sv_meta.svCount = sv_cache_info.gps_l1_count;
+                    break;
+                case GNSS_SIGNAL_GPS_L5:
+                    sv_meta.svCount = sv_cache_info.gps_l5_count;
+                    break;
+                case GNSS_SIGNAL_GPS_L2:
+                    sv_meta.svCount = sv_cache_info.gps_l2_count;
+                    break;
             }
             break;
         case GNSS_SV_TYPE_GLONASS:
@@ -419,56 +436,83 @@
             // GLONASS SV ids are from 65-96
             sv_meta.svIdOffset = GLONASS_SV_ID_OFFSET;
             sv_meta.systemId = SYSTEM_ID_GLONASS;
-            if (GNSS_SIGNAL_GLONASS_G1 == signalType) {
-                sv_meta.svCount = sv_cache_info.glo_g1_count;
-            } else if (GNSS_SIGNAL_GLONASS_G2 == signalType) {
-                sv_meta.svCount = sv_cache_info.glo_g2_count;
+            switch (signalType) {
+                case GNSS_SIGNAL_GLONASS_G1:
+                    sv_meta.svCount = sv_cache_info.glo_g1_count;
+                    break;
+                case GNSS_SIGNAL_GLONASS_G2:
+                    sv_meta.svCount = sv_cache_info.glo_g2_count;
+                    break;
             }
             break;
         case GNSS_SV_TYPE_GALILEO:
             sv_meta.talker[0] = 'G';
             sv_meta.talker[1] = 'A';
             sv_meta.mask = sv_cache_info.gal_used_mask;
+            // GALILEO SV ids are from 301-336, So keep svIdOffset 300
+            sv_meta.svIdOffset = GALILEO_SV_ID_OFFSET;
             sv_meta.systemId = SYSTEM_ID_GALILEO;
-            if (GNSS_SIGNAL_GALILEO_E1 == signalType) {
-                sv_meta.svCount = sv_cache_info.gal_e1_count;
-            } else if (GNSS_SIGNAL_GALILEO_E5A == signalType) {
-                sv_meta.svCount = sv_cache_info.gal_e5_count;
+            switch (signalType) {
+                case GNSS_SIGNAL_GALILEO_E1:
+                    sv_meta.svCount = sv_cache_info.gal_e1_count;
+                    break;
+                case GNSS_SIGNAL_GALILEO_E5A:
+                    sv_meta.svCount = sv_cache_info.gal_e5_count;
+                    break;
+                case GNSS_SIGNAL_GALILEO_E5B:
+                    sv_meta.svCount = sv_cache_info.gal_e5b_count;
+                    break;
             }
             break;
         case GNSS_SV_TYPE_QZSS:
             sv_meta.talker[0] = 'G';
             sv_meta.talker[1] = 'Q';
             sv_meta.mask = sv_cache_info.qzss_used_mask;
-            // QZSS SV ids are from 193-199. So keep svIdOffset -192
+            // QZSS SV ids are from 193-199. So keep svIdOffset 192
             sv_meta.svIdOffset = QZSS_SV_ID_OFFSET;
             sv_meta.systemId = SYSTEM_ID_QZSS;
-            if (GNSS_SIGNAL_QZSS_L1CA == signalType) {
-                sv_meta.svCount = sv_cache_info.qzss_l1_count;
-            } else if (GNSS_SIGNAL_QZSS_L5 == signalType) {
-                sv_meta.svCount = sv_cache_info.qzss_l5_count;
+            switch (signalType) {
+                case GNSS_SIGNAL_QZSS_L1CA:
+                    sv_meta.svCount = sv_cache_info.qzss_l1_count;
+                    break;
+                case GNSS_SIGNAL_QZSS_L2:
+                    sv_meta.svCount = sv_cache_info.qzss_l2_count;
+                    break;
+                case GNSS_SIGNAL_QZSS_L5:
+                    sv_meta.svCount = sv_cache_info.qzss_l5_count;
+                    break;
             }
             break;
         case GNSS_SV_TYPE_BEIDOU:
             sv_meta.talker[0] = 'G';
             sv_meta.talker[1] = 'B';
             sv_meta.mask = sv_cache_info.bds_used_mask;
-            // BDS SV ids are from 201-235. So keep svIdOffset 0
+            // BDS SV ids are from 201-237. So keep svIdOffset 200
+            sv_meta.svIdOffset = BDS_SV_ID_OFFSET;
             sv_meta.systemId = SYSTEM_ID_BDS;
-            if (GNSS_SIGNAL_BEIDOU_B1I == signalType) {
-                sv_meta.svCount = sv_cache_info.bds_b1_count;
-            } else if (GNSS_SIGNAL_BEIDOU_B2AI == signalType) {
-                sv_meta.svCount = sv_cache_info.bds_b2_count;
+            switch (signalType) {
+                case GNSS_SIGNAL_BEIDOU_B1I:
+                    sv_meta.svCount = sv_cache_info.bds_b1i_count;
+                    break;
+                case GNSS_SIGNAL_BEIDOU_B1C:
+                    sv_meta.svCount = sv_cache_info.bds_b1c_count;
+                    break;
+                case GNSS_SIGNAL_BEIDOU_B2AI:
+                    sv_meta.svCount = sv_cache_info.bds_b2_count;
+                    break;
             }
             break;
         case GNSS_SV_TYPE_NAVIC:
             sv_meta.talker[0] = 'G';
             sv_meta.talker[1] = 'I';
             sv_meta.mask = sv_cache_info.navic_used_mask;
-            // NAVIC SV ids are from 401-414. So keep svIdOffset 0
+            // NAVIC SV ids are from 401-414. So keep svIdOffset 400
+            sv_meta.svIdOffset = NAVIC_SV_ID_OFFSET;
             sv_meta.systemId = SYSTEM_ID_NAVIC;
-            if (GNSS_SIGNAL_NAVIC_L5 == signalType) {
-                sv_meta.svCount = sv_cache_info.navic_l5_count;
+            switch (signalType) {
+                case GNSS_SIGNAL_NAVIC_L5:
+                    sv_meta.svCount = sv_cache_info.navic_l5_count;
+                    break;
             }
             break;
         default:
@@ -523,23 +567,28 @@
    N/A
 
 ===========================================================================*/
-static int loc_nmea_put_checksum(char *pNmea, int maxSize)
+static int loc_nmea_put_checksum(char *pNmea, int maxSize, bool isTagBlock)
 {
     uint8_t checksum = 0;
     int length = 0;
+    int checksumLength = 0;
     if(NULL == pNmea)
         return 0;
 
-    pNmea++; //skip the $
+    pNmea++; //skip the $ or / for Tag Block
     while (*pNmea != '\0')
     {
         checksum ^= *pNmea++;
         length++;
     }
 
-    // length now contains nmea sentence string length not including $ sign.
-    int checksumLength = snprintf(pNmea,(maxSize-length-1),"*%02X\r\n", checksum);
-
+    if (isTagBlock) {
+        // length now contains tag block sentence string length not including / sign.
+        checksumLength = snprintf(pNmea, (maxSize-length-1), "*%02X\\", checksum);
+    } else {
+        // length now contains nmea sentence string length not including $ sign.
+        checksumLength = snprintf(pNmea, (maxSize-length-1), "*%02X\r\n", checksum);
+    }
     // total length of nmea sentence is length of nmea sentence inc $ sign plus
     // length of checksum (+1 is to cover the $ character in the length).
     return (length + checksumLength + 1);
@@ -570,7 +619,8 @@
                               char* sentence,
                               int bufSize,
                               loc_nmea_sv_meta* sv_meta_p,
-                              std::vector<std::string> &nmeaArraystr)
+                              std::vector<std::string> &nmeaArraystr,
+                              bool isTagBlockGroupingEnabled)
 {
     if (!sentence || bufSize <= 0 || !sv_meta_p)
     {
@@ -581,9 +631,14 @@
     char* pMarker = sentence;
     int lengthRemaining = bufSize;
     int length = 0;
+    int lengthTagBlock = 0;
 
     uint32_t svUsedCount = 0;
     uint32_t svUsedList[64] = {0};
+    uint32_t sentenceCount = 0;
+    uint32_t sentenceNumber = 1;
+    size_t svNumber = 1;
+    static uint32_t code = 1;
 
     char fixType = '\0';
 
@@ -591,7 +646,7 @@
     uint32_t svIdOffset = sv_meta_p->svIdOffset;
     uint64_t mask = sv_meta_p->mask;
 
-    if(sv_meta_p->svType != GNSS_SV_TYPE_GLONASS) {
+    if (!(sv_meta_p->svTypeMask & (1 << GNSS_SV_TYPE_GLONASS))) {
         svIdOffset = 0;
     }
 
@@ -602,77 +657,98 @@
         mask = mask >> 1;
     }
 
-    if (svUsedCount == 0)
+    if (svUsedCount == 0) {
         return 0;
-
-    if (sv_meta_p->totalSvUsedCount == 0)
-        fixType = '1'; // no fix
-    else if (sv_meta_p->totalSvUsedCount <= 3)
-        fixType = '2'; // 2D fix
-    else
-        fixType = '3'; // 3D fix
-
-    // Start printing the sentence
-    // Format: $--GSA,a,x,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,p.p,h.h,v.v,s*cc
-    // a : Mode  : A : Automatic, allowed to automatically switch 2D/3D
-    // x : Fixtype : 1 (no fix), 2 (2D fix), 3 (3D fix)
-    // xx : 12 SV ID
-    // p.p : Position DOP (Dilution of Precision)
-    // h.h : Horizontal DOP
-    // v.v : Vertical DOP
-    // s : GNSS System Id
-    // cc : Checksum value
-    length = snprintf(pMarker, lengthRemaining, "$%sGSA,A,%c,", talker, fixType);
-
-    if (length < 0 || length >= lengthRemaining)
-    {
-        LOC_LOGE("NMEA Error in string formatting");
-        return 0;
+    } else {
+        sentenceNumber = 1;
+        sentenceCount = svUsedCount / 12 + (svUsedCount % 12 != 0);
+        svNumber = 1;
     }
-    pMarker += length;
-    lengthRemaining -= length;
-
-    // Add first 12 satellite IDs
-    for (uint8_t i = 0; i < 12; i++)
-    {
-        if (i < svUsedCount)
-            length = snprintf(pMarker, lengthRemaining, "%02d,", svUsedList[i]);
+    while (sentenceNumber <= sentenceCount) {
+        pMarker = sentence;
+        lengthRemaining = bufSize;
+        if (svUsedCount > 12 && isTagBlockGroupingEnabled) {
+            lengthTagBlock = snprintf(pMarker, lengthRemaining, "\\g:%d-%d-%d", sentenceNumber,
+                     sentenceCount, code);
+            if (MAX_TAG_BLOCK_GROUP_CODE == code) {
+                code = 1;
+            }
+            lengthTagBlock = loc_nmea_put_checksum(sentence, bufSize, true);
+            pMarker += lengthTagBlock;
+            lengthRemaining -= lengthTagBlock;
+        }
+        if (sv_meta_p->totalSvUsedCount == 0)
+            fixType = '1'; // no fix
+        else if (sv_meta_p->totalSvUsedCount <= 3)
+            fixType = '2'; // 2D fix
         else
-            length = snprintf(pMarker, lengthRemaining, ",");
+            fixType = '3'; // 3D fix
 
-        if (length < 0 || length >= lengthRemaining)
-        {
+        // Start printing the sentence
+        // Format: $--GSA,a,x,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,p.p,h.h,v.v,s*cc
+        // a : Mode  : A : Automatic, allowed to automatically switch 2D/3D
+        // x : Fixtype : 1 (no fix), 2 (2D fix), 3 (3D fix)
+        // xx : 12 SV ID
+        // p.p : Position DOP (Dilution of Precision)
+        // h.h : Horizontal DOP
+        // v.v : Vertical DOP
+        // s : GNSS System Id
+        // cc : Checksum value
+        length = snprintf(pMarker, lengthRemaining, "$%sGSA,A,%c,", talker, fixType);
+        if (length < 0 || length >= lengthRemaining) {
             LOC_LOGE("NMEA Error in string formatting");
             return 0;
         }
         pMarker += length;
         lengthRemaining -= length;
+
+        // Add 12 satellite IDs
+        for (uint8_t i = 0; i < 12; i++, svNumber++)
+        {
+            if (svNumber <= svUsedCount)
+                length = snprintf(pMarker, lengthRemaining, "%02d,", svUsedList[svNumber - 1]);
+            else
+                length = snprintf(pMarker, lengthRemaining, ",");
+
+            if (length < 0 || length >= lengthRemaining) {
+                LOC_LOGE("NMEA Error in string formatting");
+                return 0;
+            }
+            pMarker += length;
+            lengthRemaining -= length;
+        }
+
+        // Add the position/horizontal/vertical DOP values
+        if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP)
+        {
+            length = snprintf(pMarker, lengthRemaining, "%.1f,%.1f,%.1f,",
+                    locationExtended.pdop,
+                    locationExtended.hdop,
+                    locationExtended.vdop);
+        }
+        else
+        {   // no dop
+            length = snprintf(pMarker, lengthRemaining, ",,,");
+        }
+        pMarker += length;
+        lengthRemaining -= length;
+
+        // system id
+        length = snprintf(pMarker, lengthRemaining, "%d", sv_meta_p->systemId);
+        pMarker += length;
+        lengthRemaining -= length;
+
+        /* Sentence is ready, add checksum and broadcast */
+        length = loc_nmea_put_checksum(sentence + lengthTagBlock, bufSize - lengthTagBlock, false);
+        nmeaArraystr.push_back(sentence);
+        sentenceNumber++;
+        if (!isTagBlockGroupingEnabled) {
+            break;
+        }
     }
-
-    // Add the position/horizontal/vertical DOP values
-    if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP)
-    {
-        length = snprintf(pMarker, lengthRemaining, "%.1f,%.1f,%.1f,",
-                locationExtended.pdop,
-                locationExtended.hdop,
-                locationExtended.vdop);
+    if (svUsedCount > 12 && isTagBlockGroupingEnabled) {
+        code++;
     }
-    else
-    {   // no dop
-        length = snprintf(pMarker, lengthRemaining, ",,,");
-    }
-    pMarker += length;
-    lengthRemaining -= length;
-
-    // system id
-    length = snprintf(pMarker, lengthRemaining, "%d", sv_meta_p->systemId);
-    pMarker += length;
-    lengthRemaining -= length;
-
-    /* Sentence is ready, add checksum and broadcast */
-    length = loc_nmea_put_checksum(sentence, bufSize);
-    nmeaArraystr.push_back(sentence);
-
     return svUsedCount;
 }
 
@@ -724,6 +800,9 @@
         return;
     }
 
+    if ((1 << GNSS_SV_TYPE_GLONASS) & sv_meta_p->svTypeMask) {
+        svIdOffset = 0;
+    }
     svNumber = 1;
     sentenceNumber = 1;
     sentenceCount = svCount / 4 + (svCount % 4 != 0);
@@ -779,19 +858,23 @@
                 }
             }
 
-            if (sv_meta_p->svType == svNotify.gnssSvs[svNumber - 1].type &&
+            if ((sv_meta_p->svTypeMask & (1 << svNotify.gnssSvs[svNumber - 1].type)) &&
                     sv_meta_p->signalId == convert_signalType_to_signalId(signalType))
             {
-                uint16_t svId = svNotify.gnssSvs[svNumber - 1].svId;
-                // For QZSS we adjusted SV id's in GnssAdapter, we need to re-adjust here
-                if (GNSS_SV_TYPE_QZSS == svNotify.gnssSvs[svNumber - 1].type) {
-                    svId = svId - (QZSS_SV_PRN_MIN - 1);
+                if (GNSS_SV_TYPE_SBAS == svNotify.gnssSvs[svNumber - 1].type) {
+                    svIdOffset = SBAS_SV_ID_OFFSET;
                 }
-                length = snprintf(pMarker, lengthRemaining,",%02d,%02d,%03d,",
-                        svId + svIdOffset,
+                if (GNSS_SV_TYPE_GLONASS == svNotify.gnssSvs[svNumber - 1].type &&
+                    GLO_SV_PRN_SLOT_UNKNOWN == svNotify.gnssSvs[svNumber - 1].svId) {
+                    length = snprintf(pMarker, lengthRemaining, ",,%02d,%03d,",
                         (int)(0.5 + svNotify.gnssSvs[svNumber - 1].elevation), //float to int
                         (int)(0.5 + svNotify.gnssSvs[svNumber - 1].azimuth)); //float to int
-
+                } else {
+                    length = snprintf(pMarker, lengthRemaining, ",%02d,%02d,%03d,",
+                        svNotify.gnssSvs[svNumber - 1].svId - svIdOffset,
+                        (int)(0.5 + svNotify.gnssSvs[svNumber - 1].elevation), //float to int
+                        (int)(0.5 + svNotify.gnssSvs[svNumber - 1].azimuth)); //float to int
+                }
                 if (length < 0 || length >= lengthRemaining)
                 {
                     LOC_LOGE("NMEA Error in string formatting");
@@ -824,7 +907,7 @@
         pMarker += length;
         lengthRemaining -= length;
 
-        length = loc_nmea_put_checksum(sentence, bufSize);
+        length = loc_nmea_put_checksum(sentence, bufSize, false);
         nmeaArraystr.push_back(sentence);
         sentenceNumber++;
 
@@ -857,7 +940,7 @@
     int lengthRemaining = bufSize;
     int length = 0;
     int datum_type;
-    char ref_datum[4] = {0};
+    char ref_datum[4] = {'W', '8', '4', '\0'};
     char local_datum[4] = {0};
     double lla_offset[3] = {0};
     char latHem, longHem;
@@ -868,21 +951,15 @@
     datum_type = loc_get_datum_type();
     switch (datum_type) {
         case LOC_GNSS_DATUM_WGS84:
-            ref_datum[0] = 'W';
-            ref_datum[1] = '8';
-            ref_datum[2] = '4';
-            local_datum[0] = 'P';
-            local_datum[1] = '9';
-            local_datum[2] = '0';
-            break;
-        case LOC_GNSS_DATUM_PZ90:
-            ref_datum[0] = 'P';
-            ref_datum[1] = '9';
-            ref_datum[2] = '0';
             local_datum[0] = 'W';
             local_datum[1] = '8';
             local_datum[2] = '4';
             break;
+        case LOC_GNSS_DATUM_PZ90:
+            local_datum[0] = 'P';
+            local_datum[1] = '9';
+            local_datum[2] = '0';
+            break;
         default:
             break;
     }
@@ -902,7 +979,7 @@
         lla_offset[1] -= 360.0;
     }
     lla_offset[2] = local_lla.alt - ref_lla.alt;
-    if (lla_offset[0] > 0.0) {
+    if (lla_offset[0] >= 0.0) {
         latHem = 'N';
     } else {
         latHem = 'S';
@@ -933,7 +1010,7 @@
     pMarker += length;
     lengthRemaining -= length;
 
-    length = loc_nmea_put_checksum(sentence, bufSize);
+    length = loc_nmea_put_checksum(sentence, bufSize, false);
 }
 
 /*===========================================================================
@@ -1036,24 +1113,15 @@
                                      bool custom_gga_fix_quality,
                                      char ggaGpsQuality[3],
                                      char & rmcModeIndicator,
-                                     char & vtgModeIndicator) {
+                                     char & vtgModeIndicator,
+                                     char gnsModeIndicator[7]) {
 
     ggaGpsQuality[0] = '0'; // 0 means no fix
     rmcModeIndicator = 'N'; // N means no fix
     vtgModeIndicator = 'N'; // N means no fix
-
+    memset(gnsModeIndicator, 'N', 6); // N means no fix
+    gnsModeIndicator[6] = '\0';
     do {
-        // GGA fix quality is defined in NMEA spec as below:
-        // https://www.trimble.com/OEM_ReceiverHelp/V4.44/en/NMEA-0183messages_GGA.html
-        // Fix quality: 0 = invalid
-        //              1 = GPS fix (SPS)
-        //              2 = DGPS fix
-        //              3 = PPS fix
-        //              4 = Real Time Kinematic
-        //              5 = Float RTK
-        //              6 = estimated (dead reckoning) (2.3 feature)
-        //              7 = Manual input mode
-        //              8 = Simulation mode
         if (!(location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG)){
             break;
         }
@@ -1063,28 +1131,88 @@
                 ggaGpsQuality[0] = '2';    // 2 means DGPS fix
                 rmcModeIndicator = 'P'; // P means precise
                 vtgModeIndicator = 'P'; // P means precise
+                if (locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[0] = 'P'; // P means precise
+                if (locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[1] = 'P'; // P means precise
+                if (locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[2] = 'P'; // P means precise
+                if (locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[3] = 'P'; // P means precise
+                if (locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[4] = 'P'; // P means precise
+                if (locationExtended.gnss_sv_used_ids.navic_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[5] = 'P'; // P means precise
                 break;
             } else if (LOC_NAV_MASK_RTK_FIXED_CORRECTION & locationExtended.navSolutionMask){
                 ggaGpsQuality[0] = '4';    // 4 means RTK Fixed fix
                 rmcModeIndicator = 'R'; // use R (RTK fixed)
                 vtgModeIndicator = 'D'; // use D (differential) as
                                         // no RTK fixed defined for VTG in NMEA 183 spec
+                if (locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[0] = 'R'; // R means RTK fixed
+                if (locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[1] = 'R'; // R means RTK fixed
+                if (locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[2] = 'R'; // R means RTK fixed
+                if (locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[3] = 'R'; // R means RTK fixed
+                if (locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[4] = 'R'; // R means RTK fixed
+                if (locationExtended.gnss_sv_used_ids.navic_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[5] = 'R'; // R means RTK fixed
                 break;
             } else if (LOC_NAV_MASK_RTK_CORRECTION & locationExtended.navSolutionMask){
                 ggaGpsQuality[0] = '5';    // 5 means RTK float fix
                 rmcModeIndicator = 'F'; // F means RTK float fix
                 vtgModeIndicator = 'D'; // use D (differential) as
                                         // no RTK float defined for VTG in NMEA 183 spec
+                if (locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[0] = 'F'; // F means RTK float fix
+                if (locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[1] = 'F'; // F means RTK float fix
+                if (locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[2] = 'F'; // F means RTK float fix
+                if (locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[3] = 'F'; // F means RTK float fix
+                if (locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[4] = 'F'; // F means RTK float fix
+                if (locationExtended.gnss_sv_used_ids.navic_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[5] = 'F'; // F means RTK float fix
                 break;
             } else if (LOC_NAV_MASK_DGNSS_CORRECTION & locationExtended.navSolutionMask){
                 ggaGpsQuality[0] = '2';    // 2 means DGPS fix
                 rmcModeIndicator = 'D'; // D means differential
                 vtgModeIndicator = 'D'; // D means differential
+                if (locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[0] = 'D'; // D means differential
+                if (locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[1] = 'D'; // D means differential
+                if (locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[2] = 'D'; // D means differential
+                if (locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[3] = 'D'; // D means differential
+                if (locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[4] = 'D'; // D means differential
+                if (locationExtended.gnss_sv_used_ids.navic_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[5] = 'D'; // D means differential
                 break;
             } else if (LOC_NAV_MASK_SBAS_CORRECTION_IONO & locationExtended.navSolutionMask){
                 ggaGpsQuality[0] = '2';    // 2 means DGPS fix
                 rmcModeIndicator = 'D'; // D means differential
                 vtgModeIndicator = 'D'; // D means differential
+                if (locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[0] = 'D'; // D means differential
+                if (locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[1] = 'D'; // D means differential
+                if (locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[2] = 'D'; // D means differential
+                if (locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[3] = 'D'; // D means differential
+                if (locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[4] = 'D'; // D means differential
+                if (locationExtended.gnss_sv_used_ids.navic_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[5] = 'D'; // D means differential
                 break;
             }
         }
@@ -1094,11 +1222,24 @@
                 ggaGpsQuality[0] = '1'; // 1 means GPS
                 rmcModeIndicator = 'A'; // A means autonomous
                 vtgModeIndicator = 'A'; // A means autonomous
+                if (locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[0] = 'A'; // A means autonomous
+                if (locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[1] = 'A'; // A means autonomous
+                if (locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[2] = 'A'; // A means autonomous
+                if (locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[3] = 'A'; // A means autonomous
+                if (locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[4] = 'A'; // A means autonomous
+                if (locationExtended.gnss_sv_used_ids.navic_sv_used_ids_mask ? 1 : 0)
+                    gnsModeIndicator[5] = 'A'; // A means autonomous
                 break;
             } else if (LOC_POS_TECH_MASK_SENSORS & locationExtended.tech_mask){
                 ggaGpsQuality[0] = '6'; // 6 means estimated (dead reckoning)
                 rmcModeIndicator = 'E'; // E means estimated (dead reckoning)
                 vtgModeIndicator = 'E'; // E means estimated (dead reckoning)
+                memset(gnsModeIndicator, 'E', 6); // E means estimated (dead reckoning)
                 break;
             }
         }
@@ -1184,10 +1325,13 @@
                                const LocationSystemInfo &systemInfo,
                                unsigned char generate_nmea,
                                bool custom_gga_fix_quality,
-                               std::vector<std::string> &nmeaArraystr)
+                               std::vector<std::string> &nmeaArraystr,
+                               int& indexOfGGA,
+                               bool isTagBlockGroupingEnabled)
 {
     ENTRY_LOG();
 
+    indexOfGGA = -1;
     LocGpsUtcTime utcPosTimestamp = 0;
     bool inLsTransition = false;
 
@@ -1255,7 +1399,6 @@
 
     if (generate_nmea) {
         char talker[3] = {'G', 'P', '\0'};
-        char modeIndicator[7] = {0};
         uint32_t svUsedCount = 0;
         uint32_t count = 0;
         loc_nmea_sv_meta sv_meta;
@@ -1265,7 +1408,7 @@
 
         count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence),
                         loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GPS,
-                        GNSS_SIGNAL_GPS_L1CA, true), nmeaArraystr);
+                        GNSS_SIGNAL_GPS_L1CA, true), nmeaArraystr, isTagBlockGroupingEnabled);
         if (count > 0)
         {
             svUsedCount += count;
@@ -1279,7 +1422,7 @@
 
         count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence),
                         loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GLONASS,
-                        GNSS_SIGNAL_GLONASS_G1, true), nmeaArraystr);
+                        GNSS_SIGNAL_GLONASS_G1, true), nmeaArraystr, isTagBlockGroupingEnabled);
         if (count > 0)
         {
             svUsedCount += count;
@@ -1293,7 +1436,7 @@
 
         count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence),
                         loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GALILEO,
-                        GNSS_SIGNAL_GALILEO_E1, true), nmeaArraystr);
+                        GNSS_SIGNAL_GALILEO_E1, true), nmeaArraystr, isTagBlockGroupingEnabled);
         if (count > 0)
         {
             svUsedCount += count;
@@ -1306,7 +1449,7 @@
         // ----------------------------
         count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence),
                         loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_BEIDOU,
-                        GNSS_SIGNAL_BEIDOU_B1I, true), nmeaArraystr);
+                        GNSS_SIGNAL_BEIDOU_B1I, true), nmeaArraystr, isTagBlockGroupingEnabled);
         if (count > 0)
         {
             svUsedCount += count;
@@ -1320,7 +1463,7 @@
 
         count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence),
                         loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_QZSS,
-                        GNSS_SIGNAL_QZSS_L1CA, true), nmeaArraystr);
+                        GNSS_SIGNAL_QZSS_L1CA, true), nmeaArraystr, isTagBlockGroupingEnabled);
         if (count > 0)
         {
             svUsedCount += count;
@@ -1332,15 +1475,16 @@
         // in this case, generate an empty GSA sentence
         if (svUsedCount == 0) {
             strlcpy(sentence, "$GPGSA,A,1,,,,,,,,,,,,,,,,", sizeof(sentence));
-            length = loc_nmea_put_checksum(sentence, sizeof(sentence));
+            length = loc_nmea_put_checksum(sentence, sizeof(sentence), false);
             nmeaArraystr.push_back(sentence);
         }
 
         char ggaGpsQuality[3] = {'0', '\0', '\0'};
         char rmcModeIndicator = 'N';
         char vtgModeIndicator = 'N';
+        char gnsModeIndicator[7] = {'N', 'N', 'N', 'N', 'N', 'N', '\0'};
         loc_nmea_get_fix_quality(location, locationExtended, custom_gga_fix_quality,
-                                 ggaGpsQuality, rmcModeIndicator, vtgModeIndicator);
+                                 ggaGpsQuality, rmcModeIndicator, vtgModeIndicator, gnsModeIndicator);
 
         // -------------------
         // ------$--VTG-------
@@ -1354,7 +1498,7 @@
             float magTrack = location.gpsLocation.bearing;
             if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_MAG_DEV)
             {
-                float magTrack = location.gpsLocation.bearing - locationExtended.magneticDeviation;
+                magTrack = location.gpsLocation.bearing - locationExtended.magneticDeviation;
                 if (magTrack < 0.0)
                     magTrack += 360.0;
                 else if (magTrack > 360.0)
@@ -1398,7 +1542,7 @@
 
         length = snprintf(pMarker, lengthRemaining, "%c", vtgModeIndicator);
 
-        length = loc_nmea_put_checksum(sentence, sizeof(sentence));
+        length = loc_nmea_put_checksum(sentence, sizeof(sentence), false);
         nmeaArraystr.push_back(sentence);
 
         memset(&ecef_w84, 0, sizeof(ecef_w84));
@@ -1415,23 +1559,21 @@
         convert_WGS84_to_PZ90(ecef_w84, ecef_p90);
         convert_Ecef_to_Lla(ecef_p90, lla_p90);
 
+        ref_lla.lat = location.gpsLocation.latitude;
+        ref_lla.lon = location.gpsLocation.longitude;
+        ref_lla.alt = location.gpsLocation.altitude;
+
         switch (datum_type) {
             case LOC_GNSS_DATUM_WGS84:
-                ref_lla.lat = location.gpsLocation.latitude;
-                ref_lla.lon = location.gpsLocation.longitude;
-                ref_lla.alt = location.gpsLocation.altitude;
-                local_lla.lat = lla_p90.lat / M_PI * 180.0;
-                local_lla.lon = lla_p90.lon / M_PI * 180.0;
-                local_lla.alt = lla_p90.alt;
-                break;
-            case LOC_GNSS_DATUM_PZ90:
-                ref_lla.lat = lla_p90.lat / M_PI * 180.0;
-                ref_lla.lon = lla_p90.lon / M_PI * 180.0;
-                ref_lla.alt = lla_p90.alt;
                 local_lla.lat = location.gpsLocation.latitude;
                 local_lla.lon = location.gpsLocation.longitude;
                 local_lla.alt = location.gpsLocation.altitude;
                 break;
+            case LOC_GNSS_DATUM_PZ90:
+                local_lla.lat = lla_p90.lat / M_PI * 180.0;
+                local_lla.lon = lla_p90.lon / M_PI * 180.0;
+                local_lla.alt = lla_p90.alt;
+                break;
             default:
                 break;
         }
@@ -1602,7 +1744,7 @@
         // hardcode Navigation Status field to 'V'
         length = snprintf(pMarker, lengthRemaining, ",%c", 'V');
 
-        length = loc_nmea_put_checksum(sentence_RMC, sizeof(sentence_RMC));
+        length = loc_nmea_put_checksum(sentence_RMC, sizeof(sentence_RMC), false);
 
         // -------------------
         // ------$--GNS-------
@@ -1671,49 +1813,7 @@
         pMarker += length;
         lengthRemaining -= length;
 
-        if(!(sv_cache_info.gps_used_mask ? 1 : 0))
-            modeIndicator[0] = 'N';
-        else if (LOC_NAV_MASK_SBAS_CORRECTION_IONO & locationExtended.navSolutionMask)
-            modeIndicator[0] = 'D';
-        else if (LOC_POS_TECH_MASK_SENSORS == locationExtended.tech_mask)
-            modeIndicator[0] = 'E';
-        else
-            modeIndicator[0] = 'A';
-        if(!(sv_cache_info.glo_used_mask ? 1 : 0))
-            modeIndicator[1] = 'N';
-        else if (LOC_POS_TECH_MASK_SENSORS == locationExtended.tech_mask)
-            modeIndicator[1] = 'E';
-        else
-            modeIndicator[1] = 'A';
-        if(!(sv_cache_info.gal_used_mask ? 1 : 0))
-            modeIndicator[2] = 'N';
-        else if (LOC_POS_TECH_MASK_SENSORS == locationExtended.tech_mask)
-            modeIndicator[2] = 'E';
-        else
-            modeIndicator[2] = 'A';
-        if(!(sv_cache_info.bds_used_mask ? 1 : 0))
-            modeIndicator[3] = 'N';
-        else if (LOC_POS_TECH_MASK_SENSORS == locationExtended.tech_mask)
-            modeIndicator[3] = 'E';
-        else
-            modeIndicator[3] = 'A';
-        if(!(sv_cache_info.qzss_used_mask ? 1 : 0))
-            modeIndicator[4] = 'N';
-        else if (LOC_POS_TECH_MASK_SENSORS == locationExtended.tech_mask)
-            modeIndicator[4] = 'E';
-        else
-            modeIndicator[4] = 'A';
-        if(!(sv_cache_info.navic_used_mask ? 1 : 0))
-            modeIndicator[5] = 'N';
-        else if (LOC_POS_TECH_MASK_SENSORS == locationExtended.tech_mask)
-            modeIndicator[5] = 'E';
-        else
-            modeIndicator[5] = 'A';
-        modeIndicator[6] = '\0';
-        for(int index = 5; index > 0 && 'N' == modeIndicator[index]; index--) {
-            modeIndicator[index] = '\0';
-        }
-        length = snprintf(pMarker, lengthRemaining,"%s,", modeIndicator);
+        length = snprintf(pMarker, lengthRemaining, "%s,", gnsModeIndicator);
 
         pMarker += length;
         lengthRemaining -= length;
@@ -1756,24 +1856,57 @@
         if ((location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_ALTITUDE) &&
             (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL))
         {
-            length = snprintf(pMarker, lengthRemaining, "%.1lf,,",
+            length = snprintf(pMarker, lengthRemaining, "%.1lf,",
                               ref_lla.alt - locationExtended.altitudeMeanSeaLevel);
         }
         else
         {
-            length = snprintf(pMarker, lengthRemaining,",,");
+            length = snprintf(pMarker, lengthRemaining, ",");
         }
-
+        if (length < 0 || length >= lengthRemaining)
+        {
+            LOC_LOGE("NMEA Error in string formatting");
+            return;
+        }
         pMarker += length;
         lengthRemaining -= length;
 
+        if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DGNSS_DATA_AGE)
+        {
+            length = snprintf(pMarker, lengthRemaining, "%.1f,",
+                              (float)locationExtended.dgnssDataAgeMsec / 1000);
+        }
+        else
+        {
+            length = snprintf(pMarker, lengthRemaining, ",");
+        }
+        if (length < 0 || length >= lengthRemaining)
+        {
+            LOC_LOGE("NMEA Error in string formatting");
+            return;
+        }
+        pMarker += length;
+        lengthRemaining -= length;
+
+        if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DGNSS_REF_STATION_ID)
+        {
+            length = snprintf(pMarker, lengthRemaining, "%04d",
+                              locationExtended.dgnssRefStationId);
+            if (length < 0 || length >= lengthRemaining)
+            {
+                LOC_LOGE("NMEA Error in string formatting");
+                return;
+            }
+            pMarker += length;
+            lengthRemaining -= length;
+        }
+
         // hardcode Navigation Status field to 'V'
         length = snprintf(pMarker, lengthRemaining, ",%c", 'V');
         pMarker += length;
         lengthRemaining -= length;
 
-        length = loc_nmea_put_checksum(sentence_GNS, sizeof(sentence_GNS));
-
+        length = loc_nmea_put_checksum(sentence_GNS, sizeof(sentence_GNS), false);
 
         // -------------------
         // ------$--GGA-------
@@ -1885,15 +2018,52 @@
         if ((location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_ALTITUDE) &&
             (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL))
         {
-            length = snprintf(pMarker, lengthRemaining, "%.1lf,M,,",
+            length = snprintf(pMarker, lengthRemaining, "%.1lf,M,",
                               ref_lla.alt - locationExtended.altitudeMeanSeaLevel);
         }
         else
         {
-            length = snprintf(pMarker, lengthRemaining,",,,");
+            length = snprintf(pMarker, lengthRemaining, ",,");
+        }
+        if (length < 0 || length >= lengthRemaining)
+        {
+            LOC_LOGE("NMEA Error in string formatting");
+            return;
+        }
+        pMarker += length;
+        lengthRemaining -= length;
+
+        if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DGNSS_DATA_AGE)
+        {
+            length = snprintf(pMarker, lengthRemaining, "%.1f,",
+                              (float)locationExtended.dgnssDataAgeMsec / 1000);
+        }
+        else
+        {
+            length = snprintf(pMarker, lengthRemaining, ",");
+        }
+        if (length < 0 || length >= lengthRemaining)
+        {
+            LOC_LOGE("NMEA Error in string formatting");
+            return;
+        }
+        pMarker += length;
+        lengthRemaining -= length;
+
+        if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DGNSS_REF_STATION_ID)
+        {
+            length = snprintf(pMarker, lengthRemaining, "%04d",
+                              locationExtended.dgnssRefStationId);
+            if (length < 0 || length >= lengthRemaining)
+            {
+                LOC_LOGE("NMEA Error in string formatting");
+                return;
+            }
+            pMarker += length;
+            lengthRemaining -= length;
         }
 
-        length = loc_nmea_put_checksum(sentence_GGA, sizeof(sentence_GGA));
+        length = loc_nmea_put_checksum(sentence_GGA, sizeof(sentence_GGA), false);
 
         // ------$--DTM-------
         nmeaArraystr.push_back(sentence_DTM);
@@ -1911,32 +2081,32 @@
         }
         // ------$--GGA-------
         nmeaArraystr.push_back(sentence_GGA);
-
+        indexOfGGA = static_cast<int>(nmeaArraystr.size() - 1);
     }
     //Send blank NMEA reports for non-final fixes
     else {
         strlcpy(sentence, "$GPGSA,A,1,,,,,,,,,,,,,,,,", sizeof(sentence));
-        length = loc_nmea_put_checksum(sentence, sizeof(sentence));
+        length = loc_nmea_put_checksum(sentence, sizeof(sentence), false);
         nmeaArraystr.push_back(sentence);
 
         strlcpy(sentence, "$GPVTG,,T,,M,,N,,K,N", sizeof(sentence));
-        length = loc_nmea_put_checksum(sentence, sizeof(sentence));
+        length = loc_nmea_put_checksum(sentence, sizeof(sentence), false);
         nmeaArraystr.push_back(sentence);
 
         strlcpy(sentence, "$GPDTM,,,,,,,,", sizeof(sentence));
-        length = loc_nmea_put_checksum(sentence, sizeof(sentence));
+        length = loc_nmea_put_checksum(sentence, sizeof(sentence), false);
         nmeaArraystr.push_back(sentence);
 
         strlcpy(sentence, "$GPRMC,,V,,,,,,,,,,N,V", sizeof(sentence));
-        length = loc_nmea_put_checksum(sentence, sizeof(sentence));
+        length = loc_nmea_put_checksum(sentence, sizeof(sentence), false);
         nmeaArraystr.push_back(sentence);
 
         strlcpy(sentence, "$GPGNS,,,,,,N,,,,,,,V", sizeof(sentence));
-        length = loc_nmea_put_checksum(sentence, sizeof(sentence));
+        length = loc_nmea_put_checksum(sentence, sizeof(sentence), false);
         nmeaArraystr.push_back(sentence);
 
         strlcpy(sentence, "$GPGGA,,,,,,0,,,,,,,,", sizeof(sentence));
-        length = loc_nmea_put_checksum(sentence, sizeof(sentence));
+        length = loc_nmea_put_checksum(sentence, sizeof(sentence), false);
         nmeaArraystr.push_back(sentence);
     }
 
@@ -1967,41 +2137,26 @@
     ENTRY_LOG();
 
     char sentence[NMEA_SENTENCE_MAX_LENGTH] = {0};
-    int svCount = svNotify.count;
-    int svNumber = 1;
     loc_sv_cache_info sv_cache_info = {};
 
     //Count GPS SVs for saparating GPS from GLONASS and throw others
-    for(svNumber=1; svNumber <= svCount; svNumber++) {
-        if (GNSS_SV_TYPE_GPS == svNotify.gnssSvs[svNumber - 1].type)
+    for (uint32_t svOffset = 0; svOffset < svNotify.count; svOffset++) {
+        if ((GNSS_SV_TYPE_GPS == svNotify.gnssSvs[svOffset].type) ||
+            (GNSS_SV_TYPE_SBAS == svNotify.gnssSvs[svOffset].type))
         {
-            // cache the used in fix mask, as it will be needed to send $GPGSA
-            // during the position report
-            if (GNSS_SV_OPTIONS_USED_IN_FIX_BIT ==
-                    (svNotify.gnssSvs[svNumber - 1].gnssSvOptionsMask &
-                      GNSS_SV_OPTIONS_USED_IN_FIX_BIT))
-            {
-                sv_cache_info.gps_used_mask |= (1ULL << (svNotify.gnssSvs[svNumber - 1].svId - 1));
-            }
-            if (GNSS_SIGNAL_GPS_L5 == svNotify.gnssSvs[svNumber - 1].gnssSignalTypeMask) {
+            if (GNSS_SIGNAL_GPS_L5 == svNotify.gnssSvs[svOffset].gnssSignalTypeMask) {
                 sv_cache_info.gps_l5_count++;
+            } else if (GNSS_SIGNAL_GPS_L2 == svNotify.gnssSvs[svOffset].gnssSignalTypeMask) {
+                sv_cache_info.gps_l2_count++;
             } else {
-                // GNSS_SIGNAL_GPS_L1CA or default
+                // GNSS_SIGNAL_GPS_L1CA, GNSS_SIGNAL_SBAS_L1 or default
                 // If no signal type in report, it means default L1
                 sv_cache_info.gps_l1_count++;
             }
         }
-        else if (GNSS_SV_TYPE_GLONASS == svNotify.gnssSvs[svNumber - 1].type)
+        else if (GNSS_SV_TYPE_GLONASS == svNotify.gnssSvs[svOffset].type)
         {
-            // cache the used in fix mask, as it will be needed to send $GNGSA
-            // during the position report
-            if (GNSS_SV_OPTIONS_USED_IN_FIX_BIT ==
-                    (svNotify.gnssSvs[svNumber - 1].gnssSvOptionsMask &
-                      GNSS_SV_OPTIONS_USED_IN_FIX_BIT))
-            {
-                sv_cache_info.glo_used_mask |= (1ULL << (svNotify.gnssSvs[svNumber - 1].svId - 1));
-            }
-            if (GNSS_SIGNAL_GLONASS_G2 == svNotify.gnssSvs[svNumber - 1].gnssSignalTypeMask){
+            if (GNSS_SIGNAL_GLONASS_G2 == svNotify.gnssSvs[svOffset].gnssSignalTypeMask){
                 sv_cache_info.glo_g2_count++;
             } else {
                 // GNSS_SIGNAL_GLONASS_G1 or default
@@ -2009,74 +2164,53 @@
                 sv_cache_info.glo_g1_count++;
             }
         }
-        else if (GNSS_SV_TYPE_GALILEO == svNotify.gnssSvs[svNumber - 1].type)
+        else if (GNSS_SV_TYPE_GALILEO == svNotify.gnssSvs[svOffset].type)
         {
-            // cache the used in fix mask, as it will be needed to send $GAGSA
-            // during the position report
-            if (GNSS_SV_OPTIONS_USED_IN_FIX_BIT ==
-                    (svNotify.gnssSvs[svNumber - 1].gnssSvOptionsMask &
-                      GNSS_SV_OPTIONS_USED_IN_FIX_BIT))
-            {
-                sv_cache_info.gal_used_mask |= (1ULL << (svNotify.gnssSvs[svNumber - 1].svId - 1));
-            }
-            if(GNSS_SIGNAL_GALILEO_E5A == svNotify.gnssSvs[svNumber - 1].gnssSignalTypeMask){
+            if(GNSS_SIGNAL_GALILEO_E5A == svNotify.gnssSvs[svOffset].gnssSignalTypeMask){
                 sv_cache_info.gal_e5_count++;
+            } else if (GNSS_SIGNAL_GALILEO_E5B == svNotify.gnssSvs[svOffset].gnssSignalTypeMask) {
+                sv_cache_info.gal_e5b_count++;
             } else {
                 // GNSS_SIGNAL_GALILEO_E1 or default
                 // If no signal type in report, it means default E1
                 sv_cache_info.gal_e1_count++;
             }
         }
-        else if (GNSS_SV_TYPE_QZSS == svNotify.gnssSvs[svNumber - 1].type)
+        else if (GNSS_SV_TYPE_QZSS == svNotify.gnssSvs[svOffset].type)
         {
-            // cache the used in fix mask, as it will be needed to send $PQGSA
-            // during the position report
-            if (GNSS_SV_OPTIONS_USED_IN_FIX_BIT ==
-                (svNotify.gnssSvs[svNumber - 1].gnssSvOptionsMask &
-                  GNSS_SV_OPTIONS_USED_IN_FIX_BIT))
-            {
-                // For QZSS we adjusted SV id's in GnssAdapter, we need to re-adjust here
-                sv_cache_info.qzss_used_mask |=
-                        (1ULL << (svNotify.gnssSvs[svNumber - 1].svId - (QZSS_SV_PRN_MIN - 1) - 1));
-            }
-            if (GNSS_SIGNAL_QZSS_L5 == svNotify.gnssSvs[svNumber - 1].gnssSignalTypeMask) {
+            if (GNSS_SIGNAL_QZSS_L5 == svNotify.gnssSvs[svOffset].gnssSignalTypeMask) {
                 sv_cache_info.qzss_l5_count++;
+            } else if (GNSS_SIGNAL_QZSS_L2 == svNotify.gnssSvs[svOffset].gnssSignalTypeMask) {
+                sv_cache_info.qzss_l2_count++;
             } else {
                 // GNSS_SIGNAL_QZSS_L1CA or default
                 // If no signal type in report, it means default L1
                 sv_cache_info.qzss_l1_count++;
             }
         }
-        else if (GNSS_SV_TYPE_BEIDOU == svNotify.gnssSvs[svNumber - 1].type)
+        else if (GNSS_SV_TYPE_BEIDOU == svNotify.gnssSvs[svOffset].type)
         {
             // cache the used in fix mask, as it will be needed to send $PQGSA
             // during the position report
             if (GNSS_SV_OPTIONS_USED_IN_FIX_BIT ==
-                (svNotify.gnssSvs[svNumber - 1].gnssSvOptionsMask &
+                (svNotify.gnssSvs[svOffset].gnssSvOptionsMask &
                   GNSS_SV_OPTIONS_USED_IN_FIX_BIT))
             {
-                sv_cache_info.bds_used_mask |= (1ULL << (svNotify.gnssSvs[svNumber - 1].svId - 1));
+                setSvMask(sv_cache_info.bds_used_mask, svNotify.gnssSvs[svOffset].svId);
             }
-            if ((GNSS_SIGNAL_BEIDOU_B2AI == svNotify.gnssSvs[svNumber - 1].gnssSignalTypeMask) ||
-                   (GNSS_SIGNAL_BEIDOU_B2AQ == svNotify.gnssSvs[svNumber - 1].gnssSignalTypeMask)) {
+            if ((GNSS_SIGNAL_BEIDOU_B2AI == svNotify.gnssSvs[svOffset].gnssSignalTypeMask) ||
+                   (GNSS_SIGNAL_BEIDOU_B2AQ == svNotify.gnssSvs[svOffset].gnssSignalTypeMask)) {
                 sv_cache_info.bds_b2_count++;
+            } else if (GNSS_SIGNAL_BEIDOU_B1C == svNotify.gnssSvs[svOffset].gnssSignalTypeMask) {
+                sv_cache_info.bds_b1c_count++;
             } else {
                 // GNSS_SIGNAL_BEIDOU_B1I or default
                 // If no signal type in report, it means default B1I
-                sv_cache_info.bds_b1_count++;
+                sv_cache_info.bds_b1i_count++;
             }
         }
-        else if (GNSS_SV_TYPE_NAVIC == svNotify.gnssSvs[svNumber - 1].type)
+        else if (GNSS_SV_TYPE_NAVIC == svNotify.gnssSvs[svOffset].type)
         {
-            // cache the used in fix mask, as it will be needed to send $PQGSA
-            // during the position report
-            if (GNSS_SV_OPTIONS_USED_IN_FIX_BIT ==
-                (svNotify.gnssSvs[svNumber - 1].gnssSvOptionsMask &
-                  GNSS_SV_OPTIONS_USED_IN_FIX_BIT))
-            {
-                sv_cache_info.navic_used_mask |=
-                        (1ULL << (svNotify.gnssSvs[svNumber - 1].svId - 1));
-            }
             // GNSS_SIGNAL_NAVIC_L5 is the only signal type for NAVIC
             sv_cache_info.navic_l5_count++;
         }
@@ -2098,6 +2232,14 @@
     loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
             loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GPS,
             GNSS_SIGNAL_GPS_L5, false), nmeaArraystr);
+
+    // ---------------------
+    // ------$GPGSV:L2------
+    // ---------------------
+    loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
+            loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GPS,
+            GNSS_SIGNAL_GPS_L2, false), nmeaArraystr);
+
     // ---------------------
     // ------$GLGSV:G1------
     // ---------------------
@@ -2129,8 +2271,15 @@
             loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GALILEO,
             GNSS_SIGNAL_GALILEO_E5A, false), nmeaArraystr);
 
+    // -------------------------
+    // ------$GAGSV:E5B---------
+    // -------------------------
+    loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
+            loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GALILEO,
+            GNSS_SIGNAL_GALILEO_E5B, false), nmeaArraystr);
+
     // -----------------------------
-    // ------$PQGSV (QZSS):L1CA-----
+    // ------$GQGSV (QZSS):L1CA-----
     // -----------------------------
 
     loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
@@ -2138,27 +2287,45 @@
             GNSS_SIGNAL_QZSS_L1CA, false), nmeaArraystr);
 
     // -----------------------------
-    // ------$PQGSV (QZSS):L5-------
+    // ------$GQGSV (QZSS):L5-------
     // -----------------------------
 
     loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
             loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_QZSS,
             GNSS_SIGNAL_QZSS_L5, false), nmeaArraystr);
+
     // -----------------------------
-    // ------$PQGSV (BEIDOU:B1I)----
+    // ------$GQGSV (QZSS):L2-------
+    // -----------------------------
+
+    loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
+            loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_QZSS,
+            GNSS_SIGNAL_QZSS_L2, false), nmeaArraystr);
+
+
+    // -----------------------------
+    // ------$GBGSV (BEIDOU:B1I)----
     // -----------------------------
 
     loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
             loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_BEIDOU,
-            GNSS_SIGNAL_BEIDOU_B1I,false), nmeaArraystr);
+            GNSS_SIGNAL_BEIDOU_B1I, false), nmeaArraystr);
 
     // -----------------------------
-    // ------$PQGSV (BEIDOU:B2AI)---
+    // ------$GBGSV (BEIDOU:B1C)----
     // -----------------------------
 
     loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
             loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_BEIDOU,
-            GNSS_SIGNAL_BEIDOU_B2AI,false), nmeaArraystr);
+            GNSS_SIGNAL_BEIDOU_B1C, false), nmeaArraystr);
+
+    // -----------------------------
+    // ------$GBGSV (BEIDOU:B2AI)---
+    // -----------------------------
+
+    loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
+            loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_BEIDOU,
+            GNSS_SIGNAL_BEIDOU_B2AI, false), nmeaArraystr);
 
     // -----------------------------
     // ------$GIGSV (NAVIC:L5)------
diff --git a/utils/loc_nmea.h b/utils/loc_nmea.h
index a9cafb7..2d98f42 100644
--- a/utils/loc_nmea.h
+++ b/utils/loc_nmea.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, 2015-2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, 2015-2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -80,7 +80,9 @@
                                const LocationSystemInfo &systemInfo,
                                unsigned char generate_nmea,
                                bool custom_gga_fix_quality,
-                               std::vector<std::string> &nmeaArraystr);
+                               std::vector<std::string> &nmeaArraystr,
+                               int& indexOfGGA,
+                               bool isTagBlockGroupingEnabled);
 
 #define DEBUG_NMEA_MINSIZE 6
 #define DEBUG_NMEA_MAXSIZE 4096
diff --git a/utils/log_util.h b/utils/log_util.h
index 13c08bc..33aa6e2 100644
--- a/utils/log_util.h
+++ b/utils/log_util.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2014 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 2020 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -31,7 +31,7 @@
 #define __LOG_UTIL_H__
 
 #include <stdbool.h>
-
+#include <loc_pla.h>
 #if defined (USE_ANDROID_LOGGING) || defined (ANDROID)
 // Android and LE targets with logcat support
 #include <utils/Log.h>
@@ -52,7 +52,7 @@
 #endif /* LOG_TAG */
 
 // LE targets with no logcat support
-#ifdef FEATURE_EXTERNAL_AP
+#if defined(FEATURE_EXTERNAL_AP) || defined(USE_SYSLOG_LOGGING)
 #include <syslog.h>
 #define ALOGE(...) syslog(LOG_ERR,     "LOC_LOGE: " __VA_ARGS__);
 #define ALOGW(...) syslog(LOG_WARNING, "LOC_LOGW: " __VA_ARGS__);
@@ -119,6 +119,12 @@
 extern const char ENTRY_TAG[];
 extern const char EXIT_ERROR_TAG[];
 
+#define BUILD_TYPE_PROP_NA 0
+#define BUILD_TYPE_PROP_USER 1
+#define BUILD_TYPE_PROP_USERDEBUG 2
+#define BUILD_TYPE_PROP_INVALID 3
+extern int build_type_prop;
+
 /*=============================================================================
  *
  *                        MODULE EXPORTED FUNCTIONS
@@ -126,23 +132,37 @@
  *============================================================================*/
 inline void loc_logger_init(unsigned long debug, unsigned long timestamp)
 {
-   loc_logger.DEBUG_LEVEL = debug;
-#ifdef TARGET_BUILD_VARIANT_USER
-   // force user builds to 2 or less
-   if (loc_logger.DEBUG_LEVEL > 2) {
-       loc_logger.DEBUG_LEVEL = 2;
-   }
-#endif
-   loc_logger.TIMESTAMP   = timestamp;
+    loc_logger.DEBUG_LEVEL = debug;
+
+    if (BUILD_TYPE_PROP_NA == build_type_prop) {
+        char value[PROPERTY_VALUE_MAX] = "NA";
+        property_get("ro.build.type", value, "userdebug");
+        if (0 == strcmp(value, "user")) {
+            build_type_prop = BUILD_TYPE_PROP_USER;
+        } else if (0 == strcmp(value, "userdebug")) {
+            build_type_prop = BUILD_TYPE_PROP_USERDEBUG;
+        } else {
+            build_type_prop = BUILD_TYPE_PROP_INVALID;
+        }
+    }
+
+    if (BUILD_TYPE_PROP_USER == build_type_prop) {
+        // force user builds to 2 or less
+        if (loc_logger.DEBUG_LEVEL > 2) {
+            loc_logger.DEBUG_LEVEL = 2;
+        }
+     }
+
+    loc_logger.TIMESTAMP = timestamp;
 }
 
 inline void log_buffer_init(bool enabled) {
     loc_logger.LOG_BUFFER_ENABLE = enabled;
 }
-
+extern void log_tag_level_map_init();
+extern int get_tag_log_level(const char* tag);
 extern char* get_timestamp(char* str, unsigned long buf_size);
 extern void log_buffer_insert(char *str, unsigned long buf_size, int level);
-
 /*=============================================================================
  *
  *                          LOGGING BUFFER MACROS
@@ -175,11 +195,28 @@
   if that value remains unchanged, it means gps.conf did not
   provide a value and we default to the initial value to use
   Android's logging levels*/
-#define IF_LOC_LOGE if((loc_logger.DEBUG_LEVEL >= 1) && (loc_logger.DEBUG_LEVEL <= 5))
-#define IF_LOC_LOGW if((loc_logger.DEBUG_LEVEL >= 2) && (loc_logger.DEBUG_LEVEL <= 5))
-#define IF_LOC_LOGI if((loc_logger.DEBUG_LEVEL >= 3) && (loc_logger.DEBUG_LEVEL <= 5))
-#define IF_LOC_LOGD if((loc_logger.DEBUG_LEVEL >= 4) && (loc_logger.DEBUG_LEVEL <= 5))
-#define IF_LOC_LOGV if((loc_logger.DEBUG_LEVEL >= 5) && (loc_logger.DEBUG_LEVEL <= 5))
+
+
+/* Tag based logging control MACROS */
+/* The logic is like this:
+ * 1, LOCAL_LOG_LEVEL is defined as a static variable in log_util.h,
+ *    then all source files which includes log_util.h will have its own LOCAL_LOG_LEVEL variable;
+ * 2, For each source file,
+ *    2.1, First time when LOC_LOG* is invoked(its LOCAL_LOG_LEVEL == -1),
+ *         Set the tag based log level according to the <tag, level> map;
+ *         If this tag isn't found in map, set local debug level as global loc_logger.DEBUG_LEVEL;
+ *    2.2, If not the first time, use its LOCAL_LOG_LEVEL as the debug level of this tag.
+*/
+static int LOCAL_LOG_LEVEL = -1;
+#define IF_LOC_LOG(x) \
+    if (((LOCAL_LOG_LEVEL == -1 && (LOCAL_LOG_LEVEL = get_tag_log_level(LOG_TAG)) >= x) ||\
+            LOCAL_LOG_LEVEL >= x) && LOCAL_LOG_LEVEL <= 5)
+
+#define IF_LOC_LOGE IF_LOC_LOG(1)
+#define IF_LOC_LOGW IF_LOC_LOG(2)
+#define IF_LOC_LOGI IF_LOC_LOG(3)
+#define IF_LOC_LOGD IF_LOC_LOG(4)
+#define IF_LOC_LOGV IF_LOC_LOG(5)
 
 #define LOC_LOGE(...) IF_LOC_LOGE { ALOGE(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 0, __VA_ARGS__);}
 #define LOC_LOGW(...) IF_LOC_LOGW { ALOGW(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 1, __VA_ARGS__);}