Merge pi-qpr1-release PQ1A.181105.017.A1 to pi-platform-release

Change-Id: Id16641c0709137a916dc8f52316c869a411af238
diff --git a/Android.mk b/Android.mk
index 1ea0bfc..9da21fe 100644
--- a/Android.mk
+++ b/Android.mk
@@ -13,6 +13,9 @@
       else ifneq ($(filter msm8960 msm8084 msm8994 msm8996 msm8998 sdm845,$(TARGET_BOARD_PLATFORM)),)
         #For these, use their platform name as the subdirectory
         include $(call all-named-subdir-makefiles,$(TARGET_BOARD_PLATFORM))
+      else ifneq ($(filter sdm710,$(TARGET_BOARD_PLATFORM)),)
+        #For sdm710 use sdm845
+        include $(call all-named-subdir-makefiles,sdm845)
       else ifeq ($(filter msm8916,$(TARGET_BOARD_PLATFORM)),)
         #For all other targets besides msm8916
         GPS_DIRS=core utils loc_api platform_lib_abstractions etc
diff --git a/sdm845/android/Gnss.cpp b/sdm845/android/Gnss.cpp
index 5cec786..fca72e6 100644
--- a/sdm845/android/Gnss.cpp
+++ b/sdm845/android/Gnss.cpp
@@ -434,10 +434,9 @@
         // For emergency mode, request DBH (Device based hybrid) location
         // Mark Independent from GNSS flag to false.
         if (ODCPI_REQUEST_TYPE_START == request.type) {
-            if (request.isEmergencyMode) {
-                mGnssCbIface_1_1->gnssRequestLocationCb(false);
-            } else {
-                mGnssCbIface_1_1->gnssRequestLocationCb(true);
+            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);
diff --git a/sdm845/android/GnssConfiguration.cpp b/sdm845/android/GnssConfiguration.cpp
index 93f9645..f939c9a 100644
--- a/sdm845/android/GnssConfiguration.cpp
+++ b/sdm845/android/GnssConfiguration.cpp
@@ -233,11 +233,6 @@
         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);
@@ -246,14 +241,14 @@
 
     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);
+        // Add source to list if valid
+        if (setBlacklistedSource(source, blacklist[idx])) {
+            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));
+    // Update configuration
+    return mGnss->updateConfiguration(config);
 }
 
 bool GnssConfiguration::setBlacklistedSource(
@@ -264,6 +259,8 @@
     uint16_t svIdOffset = 0;
     copyToSource.size = sizeof(GnssSvIdSource);
     copyToSource.svId = copyFromSource.svid;
+    GnssSvId initialSvId = 0;
+    GnssSvId lastSvId = 0;
 
     switch(copyFromSource.constellation) {
     case GnssConstellationType::GPS:
@@ -279,18 +276,26 @@
     case GnssConstellationType::GLONASS:
         copyToSource.constellation = GNSS_SV_TYPE_GLONASS;
         svIdOffset = GNSS_SV_CONFIG_GLO_INITIAL_SV_ID - 1;
+        initialSvId = GNSS_SV_CONFIG_GLO_INITIAL_SV_ID;
+        lastSvId = GNSS_SV_CONFIG_GLO_LAST_SV_ID;
         break;
     case GnssConstellationType::QZSS:
         copyToSource.constellation = GNSS_SV_TYPE_QZSS;
         svIdOffset = 0;
+        initialSvId = GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID;
+        lastSvId = GNSS_SV_CONFIG_QZSS_LAST_SV_ID;
         break;
     case GnssConstellationType::BEIDOU:
         copyToSource.constellation = GNSS_SV_TYPE_BEIDOU;
         svIdOffset = GNSS_SV_CONFIG_BDS_INITIAL_SV_ID - 1;
+        initialSvId = GNSS_SV_CONFIG_BDS_INITIAL_SV_ID;
+        lastSvId = GNSS_SV_CONFIG_BDS_LAST_SV_ID;
         break;
     case GnssConstellationType::GALILEO:
         copyToSource.constellation = GNSS_SV_TYPE_GALILEO;
         svIdOffset = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID - 1;
+        initialSvId = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID;
+        lastSvId = GNSS_SV_CONFIG_GAL_LAST_SV_ID;
         break;
     default:
         copyToSource.constellation = GNSS_SV_TYPE_UNKNOWN;
@@ -299,8 +304,14 @@
         break;
     }
 
-    if (copyToSource.svId > 0 && svIdOffset > 0) {
+    if (copyToSource.svId > 0) {
         copyToSource.svId += svIdOffset;
+        if (copyToSource.svId < initialSvId || copyToSource.svId > lastSvId) {
+            LOC_LOGe("Invalid sv id %d for sv type %d allowed range [%d, %d]",
+                     copyToSource.svId, copyToSource.constellation,
+                     initialSvId, lastSvId);
+            retVal = false;
+        }
     }
 
     return retVal;
diff --git a/sdm845/android/location_api/GnssAPIClient.cpp b/sdm845/android/location_api/GnssAPIClient.cpp
index 7296093..f0b6f76 100644
--- a/sdm845/android/location_api/GnssAPIClient.cpp
+++ b/sdm845/android/location_api/GnssAPIClient.cpp
@@ -190,17 +190,22 @@
         IGnssNiCallback::GnssUserResponseType userResponse)
 {
     LOC_LOGD("%s]: (%d %d)", __FUNCTION__, notifId, static_cast<int>(userResponse));
-    GnssNiResponse data = GNSS_NI_RESPONSE_IGNORE;
-    if (userResponse == IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT)
+    GnssNiResponse data;
+    switch (userResponse) {
+    case IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT:
         data = GNSS_NI_RESPONSE_ACCEPT;
-    else if (userResponse == IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY)
+        break;
+    case IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY:
         data = GNSS_NI_RESPONSE_DENY;
-    else if (userResponse == IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP)
+        break;
+    case IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP:
         data = GNSS_NI_RESPONSE_NO_RESPONSE;
-    else {
-        LOC_LOGD("%s]: invalid GnssUserResponseType: %d", __FUNCTION__, (int)userResponse);
-        return;
+        break;
+    default:
+        data = GNSS_NI_RESPONSE_IGNORE;
+        break;
     }
+
     locAPIGnssNiResponse(notifId, data);
 }
 
@@ -319,8 +324,11 @@
     }
     if (gnssCbIface != nullptr) {
         IGnssCallback::GnssSystemInfo gnssInfo;
-        if (capabilitiesMask & LOCATION_CAPABILITIES_DEBUG_NMEA_BIT) {
+        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 {
diff --git a/sdm845/gnss/GnssAdapter.cpp b/sdm845/gnss/GnssAdapter.cpp
index 121345a..e981d04 100644
--- a/sdm845/gnss/GnssAdapter.cpp
+++ b/sdm845/gnss/GnssAdapter.cpp
@@ -80,7 +80,8 @@
     mAgpsCbInfo(),
     mOdcpiRequestCb(nullptr),
     mOdcpiRequestActive(false),
-    mOdcpiInjectedPositionCount(0),
+    mOdcpiTimer(this),
+    mOdcpiRequest(),
     mSystemStatus(SystemStatus::getInstance(mMsgTask)),
     mServerUrl(":"),
     mXtraObserver(mSystemStatus->getOsObserver(), mMsgTask)
@@ -1120,7 +1121,7 @@
 GnssAdapter::convertToGnssSvIdConfig(
         const std::vector<GnssSvIdSource>& blacklistedSvIds, GnssSvIdConfig& config)
 {
-    bool retVal = false;
+    bool retVal = true;
     config.size = sizeof(GnssSvIdConfig);
 
     // Empty vector => Clear any previous blacklisted SVs
@@ -1129,28 +1130,32 @@
         config.bdsBlacklistSvMask = 0;
         config.qzssBlacklistSvMask = 0;
         config.galBlacklistSvMask = 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;
+            GnssSvId lastSvId = 0;
             switch(source.constellation) {
             case GNSS_SV_TYPE_GLONASS:
                 svMaskPtr = &config.gloBlacklistSvMask;
                 initialSvId = GNSS_SV_CONFIG_GLO_INITIAL_SV_ID;
+                lastSvId = GNSS_SV_CONFIG_GLO_LAST_SV_ID;
                 break;
             case GNSS_SV_TYPE_BEIDOU:
                 svMaskPtr = &config.bdsBlacklistSvMask;
                 initialSvId = GNSS_SV_CONFIG_BDS_INITIAL_SV_ID;
+                lastSvId = GNSS_SV_CONFIG_BDS_LAST_SV_ID;
                 break;
             case GNSS_SV_TYPE_QZSS:
                 svMaskPtr = &config.qzssBlacklistSvMask;
                 initialSvId = GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID;
+                lastSvId = GNSS_SV_CONFIG_QZSS_LAST_SV_ID;
                 break;
             case GNSS_SV_TYPE_GALILEO:
                 svMaskPtr = &config.galBlacklistSvMask;
                 initialSvId = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID;
+                lastSvId = GNSS_SV_CONFIG_GAL_LAST_SV_ID;
                 break;
             default:
                 break;
@@ -1162,22 +1167,14 @@
                 // SV ID 0 = All SV IDs
                 if (0 == source.svId) {
                     *svMaskPtr = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
-                } else if (source.svId < initialSvId || source.svId >= initialSvId + 64) {
-                    LOC_LOGe("Invalid sv id %d for sv type %d",
-                            source.svId, source.constellation);
+                } else if (source.svId < initialSvId || source.svId > lastSvId) {
+                    LOC_LOGe("Invalid sv id %d for sv type %d allowed range [%d, %d]",
+                            source.svId, source.constellation, initialSvId, lastSvId);
                 } else {
-                    *svMaskPtr |= (1 << (source.svId - initialSvId));
+                    *svMaskPtr |= ((uint64_t)1 << (source.svId - initialSvId));
                 }
             }
         }
-
-        // Return true if any one source is valid
-        if (0 != config.gloBlacklistSvMask ||
-                0 != config.bdsBlacklistSvMask ||
-                0 != config.galBlacklistSvMask ||
-                0 != config.qzssBlacklistSvMask) {
-            retVal = true;
-        }
     }
 
     return retVal;
@@ -1769,6 +1766,9 @@
 {
     LOC_LOGD("%s]: ", __func__);
 
+    // odcpi session is no longer active after restart
+    mOdcpiRequestActive = false;
+
     if (mTrackingSessions.empty()) {
         return;
     }
@@ -1858,6 +1858,12 @@
     if (mLocApi->isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
         mask |= LOCATION_CAPABILITIES_DEBUG_NMEA_BIT;
     }
+    if (mLocApi->isFeatureSupported(LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
+        mask |= LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT;
+    }
+    if (mLocApi->isFeatureSupported(LOC_SUPPORTED_FEATURE_AGPM_V02)) {
+        mask |= LOCATION_CAPABILITIES_AGPM_BIT;
+    }
     return mask;
 }
 
@@ -3118,7 +3124,7 @@
 GnssAdapter::reportGnssMeasurementDataEvent(const GnssMeasurementsNotification& measurements,
                                             int msInWeek)
 {
-    LOC_LOGD("%s]: ", __func__);
+    LOC_LOGD("%s]: msInWeek=%d", __func__, msInWeek);
 
     struct MsgReportGnssMeasurementData : public LocMsg {
         GnssAdapter& mAdapter;
@@ -3172,9 +3178,6 @@
 bool
 GnssAdapter::reportOdcpiRequestEvent(OdcpiRequestInfo& request)
 {
-    LOC_LOGd("ODCPI request: type %d, tbf %d, isEmergency %d", request.type,
-            request.tbfMillis, request.isEmergencyMode);
-
     struct MsgReportOdcpiRequest : public LocMsg {
         GnssAdapter& mAdapter;
         OdcpiRequestInfo mOdcpiRequest;
@@ -3194,15 +3197,45 @@
 void GnssAdapter::reportOdcpiRequest(const OdcpiRequestInfo& request)
 {
     if (nullptr != mOdcpiRequestCb) {
-        mOdcpiInjectedPositionCount = 0;
+        LOC_LOGd("request: type %d, tbf %d, isEmergency %d"
+                 " requestActive: %d timerActive: %d",
+                 request.type, request.tbfMillis, request.isEmergencyMode,
+                 mOdcpiRequestActive, mOdcpiTimer.isActive());
+        // ODCPI START and ODCPI STOP from modem can come in quick succession
+        // so the mOdcpiTimer helps avoid spamming the framework as well as
+        // extending the odcpi session past 30 seconds if needed
         if (ODCPI_REQUEST_TYPE_START == request.type) {
-            mOdcpiRequestCb(request);
-            mOdcpiRequestActive = true;
+            if (false == mOdcpiRequestActive && false == mOdcpiTimer.isActive()) {
+                mOdcpiRequestCb(request);
+                mOdcpiRequestActive = true;
+                mOdcpiTimer.start();
+            // if the current active odcpi session is non-emergency, and the new
+            // odcpi request is emergency, replace the odcpi request with new request
+            // and restart the timer
+            } else if (false == mOdcpiRequest.isEmergencyMode &&
+                       true == request.isEmergencyMode) {
+                mOdcpiRequestCb(request);
+                mOdcpiRequestActive = true;
+                if (true == mOdcpiTimer.isActive()) {
+                    mOdcpiTimer.restart();
+                } else {
+                    mOdcpiTimer.start();
+                }
+            // if ODCPI request is not active but the timer is active, then
+            // just update the active state and wait for timer to expire
+            // before requesting new ODCPI to avoid spamming ODCPI requests
+            } else if (false == mOdcpiRequestActive && true == mOdcpiTimer.isActive()) {
+                mOdcpiRequestActive = true;
+            }
+            mOdcpiRequest = request;
+        // 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 {
             mOdcpiRequestActive = false;
         }
     } else {
-        LOC_LOGe("ODCPI request not supported");
+        LOC_LOGw("ODCPI request not supported");
     }
 }
 
@@ -3252,23 +3285,51 @@
 
 void GnssAdapter::injectOdcpi(const Location& location)
 {
-    LOC_LOGd("ODCPI Injection: requestActive: %d, lat %.7f long %.7f",
-            mOdcpiRequestActive, location.latitude, location.longitude);
+    LOC_LOGd("ODCPI Injection: requestActive: %d timerActive: %d"
+             "lat %.7f long %.7f",
+            mOdcpiRequestActive, mOdcpiTimer.isActive(),
+            location.latitude, location.longitude);
 
-    if (mOdcpiRequestActive) {
-        loc_api_adapter_err err = mLocApi->injectPosition(location);
-        if (LOC_API_ADAPTER_ERR_SUCCESS == err) {
-            mOdcpiInjectedPositionCount++;
-            if (mOdcpiInjectedPositionCount >=
-                    ODCPI_INJECTED_POSITION_COUNT_PER_REQUEST) {
-                mOdcpiRequestActive = false;
-                mOdcpiInjectedPositionCount = 0;
-            }
-        } else {
-            LOC_LOGe("Inject Position API error %d", err);
+    loc_api_adapter_err err = mLocApi->injectPosition(location);
+    if (LOC_API_ADAPTER_ERR_SUCCESS != err) {
+        LOC_LOGe("Inject Position API error %d", err);
+    }
+}
+
+// Called in the context of LocTimer thread
+void OdcpiTimer::timeOutCallback()
+{
+    if (nullptr != mAdapter) {
+        mAdapter->odcpiTimerExpireEvent();
+    }
+}
+
+// Called in the context of LocTimer thread
+void GnssAdapter::odcpiTimerExpireEvent()
+{
+    struct MsgOdcpiTimerExpire : public LocMsg {
+        GnssAdapter& mAdapter;
+        inline MsgOdcpiTimerExpire(GnssAdapter& adapter) :
+                LocMsg(),
+                mAdapter(adapter) {}
+        inline virtual void proc() const {
+            mAdapter.odcpiTimerExpire();
         }
+    };
+    sendMsg(new MsgOdcpiTimerExpire(*this));
+}
+void GnssAdapter::odcpiTimerExpire()
+{
+    LOC_LOGd("requestActive: %d timerActive: %d",
+            mOdcpiRequestActive, mOdcpiTimer.isActive());
+
+    // if ODCPI request is still active after timer
+    // expires, request again and restart timer
+    if (mOdcpiRequestActive) {
+        mOdcpiRequestCb(mOdcpiRequest);
+        mOdcpiTimer.restart();
     } else {
-        LOC_LOGv("ODCPI request inactive, injection dropped");
+        mOdcpiTimer.stop();
     }
 }
 
@@ -3833,12 +3894,12 @@
         systemstatus->getReport(reports, true);
 
         if ((!reports.mRfAndParams.empty()) && (!reports.mTimeAndClock.empty()) &&
-            reports.mTimeAndClock.back().mTimeValid &&
             (abs(msInWeek - (int)reports.mTimeAndClock.back().mGpsTowMs) < 2000)) {
 
             for (size_t i = 0; i < measurements.count; i++) {
                 switch (measurements.measurements[i].svType) {
                 case GNSS_SV_TYPE_GPS:
+                case GNSS_SV_TYPE_QZSS:
                     measurements.measurements[i].agcLevelDb =
                             reports.mRfAndParams.back().mAgcGps;
                     measurements.measurements[i].flags |=
@@ -3866,7 +3927,6 @@
                             GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
                     break;
 
-                case GNSS_SV_TYPE_QZSS:
                 case GNSS_SV_TYPE_SBAS:
                 case GNSS_SV_TYPE_UNKNOWN:
                 default:
diff --git a/sdm845/gnss/GnssAdapter.h b/sdm845/gnss/GnssAdapter.h
index cfea974..9d54e6a 100644
--- a/sdm845/gnss/GnssAdapter.h
+++ b/sdm845/gnss/GnssAdapter.h
@@ -43,10 +43,39 @@
 #define MAX_SATELLITES_IN_USE 12
 #define LOC_NI_NO_RESPONSE_TIME 20
 #define LOC_GPS_NI_RESPONSE_IGNORE 4
-#define ODCPI_INJECTED_POSITION_COUNT_PER_REQUEST 30
+#define ODCPI_EXPECTED_INJECTION_TIME_MS 10000
 
 class GnssAdapter;
 
+class OdcpiTimer : public LocTimer {
+public:
+    OdcpiTimer(GnssAdapter* adapter) :
+            LocTimer(), mAdapter(adapter), mActive(false) {}
+
+    inline void start() {
+        mActive = true;
+        LocTimer::start(ODCPI_EXPECTED_INJECTION_TIME_MS, false);
+    }
+    inline void stop() {
+        mActive = false;
+        LocTimer::stop();
+    }
+    inline void restart() {
+        stop();
+        start();
+    }
+    inline bool isActive() {
+        return mActive;
+    }
+
+private:
+    // Override
+    virtual void timeOutCallback() override;
+
+    GnssAdapter* mAdapter;
+    bool mActive;
+};
+
 typedef struct {
     pthread_t               thread;        /* NI thread */
     uint32_t                respTimeLeft;  /* examine time for NI response */
@@ -82,6 +111,7 @@
 }
 
 class GnssAdapter : public LocAdapterBase {
+
     /* ==== ULP ============================================================================ */
     UlpProxyBase* mUlpProxy;
 
@@ -115,7 +145,9 @@
     /* ==== ODCPI ========================================================================== */
     OdcpiRequestCallback mOdcpiRequestCb;
     bool mOdcpiRequestActive;
-    uint32_t mOdcpiInjectedPositionCount;
+    OdcpiTimer mOdcpiTimer;
+    OdcpiRequestInfo mOdcpiRequest;
+    void odcpiTimerExpire();
 
     /* === SystemStatus ===================================================================== */
     SystemStatus* mSystemStatus;
@@ -249,6 +281,7 @@
     /* ======== UTILITIES ================================================================== */
     void initOdcpi(const OdcpiRequestCallback& callback);
     void injectOdcpi(const Location& location);
+    void odcpiTimerExpireEvent();
 
     /* ======== RESPONSES ================================================================== */
     void reportResponse(LocationError err, uint32_t sessionId);
diff --git a/sdm845/location/LocationAPI.h b/sdm845/location/LocationAPI.h
index 31f8412..682a376 100644
--- a/sdm845/location/LocationAPI.h
+++ b/sdm845/location/LocationAPI.h
@@ -142,7 +142,11 @@
     // supports debug nmea sentences in the debugNmeaCallback
     LOCATION_CAPABILITIES_DEBUG_NMEA_BIT                    = (1<<8),
     // support outdoor trip batching
-    LOCATION_CAPABILITIES_OUTDOOR_TRIP_BATCHING_BIT         = (1<<9)
+    LOCATION_CAPABILITIES_OUTDOOR_TRIP_BATCHING_BIT         = (1<<9),
+    // support constellation enablement
+    LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT      = (1<<10),
+    // support agpm
+    LOCATION_CAPABILITIES_AGPM_BIT                          = (1<<11),
 } LocationCapabilitiesBits;
 
 typedef enum {
@@ -675,18 +679,22 @@
 
     // GLONASS - SV 65 maps to bit 0
 #define GNSS_SV_CONFIG_GLO_INITIAL_SV_ID 65
+#define GNSS_SV_CONFIG_GLO_LAST_SV_ID 88
     uint64_t gloBlacklistSvMask;
 
     // BEIDOU - SV 201 maps to bit 0
 #define GNSS_SV_CONFIG_BDS_INITIAL_SV_ID 201
+#define GNSS_SV_CONFIG_BDS_LAST_SV_ID 237
     uint64_t bdsBlacklistSvMask;
 
     // QZSS - SV 193 maps to bit 0
 #define GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID 193
+#define GNSS_SV_CONFIG_QZSS_LAST_SV_ID 200
     uint64_t qzssBlacklistSvMask;
 
     // GAL - SV 301 maps to bit 0
 #define GNSS_SV_CONFIG_GAL_INITIAL_SV_ID 301
+#define GNSS_SV_CONFIG_GAL_LAST_SV_ID 336
     uint64_t galBlacklistSvMask;
 } GnssSvIdConfig;
 
diff --git a/sdm845/utils/loc_nmea.cpp b/sdm845/utils/loc_nmea.cpp
index dd6b128..bf87599 100644
--- a/sdm845/utils/loc_nmea.cpp
+++ b/sdm845/utils/loc_nmea.cpp
@@ -73,8 +73,6 @@
     float vdop;
 } loc_sv_cache_info;
 
-static loc_sv_cache_info sv_cache_info;
-
 /*===========================================================================
 FUNCTION    loc_nmea_sv_meta_init
 
@@ -92,6 +90,7 @@
 
 ===========================================================================*/
 static loc_nmea_sv_meta* loc_nmea_sv_meta_init(loc_nmea_sv_meta& sv_meta,
+                                               loc_sv_cache_info& sv_cache_info,
                                                GnssSvType svType,
                                                bool needCombine)
 {
@@ -498,7 +497,20 @@
     int utcMinutes = pTm->tm_min;
     int utcSeconds = pTm->tm_sec;
     int utcMSeconds = (location.gpsLocation.timestamp)%1000;
+    loc_sv_cache_info sv_cache_info = {};
 
+    if (GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA & locationExtended.flags) {
+        sv_cache_info.gps_used_mask =
+                (uint32_t)locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask;
+        sv_cache_info.glo_used_mask =
+                (uint32_t)locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask;
+        sv_cache_info.gal_used_mask =
+                (uint32_t)locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask;
+        sv_cache_info.qzss_used_mask =
+                (uint32_t)locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask;
+        sv_cache_info.bds_used_mask =
+                (uint32_t)locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask;
+    }
     if (generate_nmea) {
         char talker[3] = {'G', 'P', '\0'};
         uint32_t svUsedCount = 0;
@@ -509,7 +521,8 @@
         // -------------------
 
         count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence),
-                loc_nmea_sv_meta_init(sv_meta, GNSS_SV_TYPE_GPS, true), nmeaArraystr);
+                        loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GPS, true),
+                        nmeaArraystr);
         if (count > 0)
         {
             svUsedCount += count;
@@ -522,7 +535,8 @@
         // -------------------
 
         count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence),
-                loc_nmea_sv_meta_init(sv_meta, GNSS_SV_TYPE_GLONASS, true), nmeaArraystr);
+                        loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GLONASS, true),
+                        nmeaArraystr);
         if (count > 0)
         {
             svUsedCount += count;
@@ -535,7 +549,8 @@
         // -------------------
 
         count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence),
-                loc_nmea_sv_meta_init(sv_meta, GNSS_SV_TYPE_GALILEO, true), nmeaArraystr);
+                        loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GALILEO, true),
+                        nmeaArraystr);
         if (count > 0)
         {
             svUsedCount += count;
@@ -548,7 +563,8 @@
         // --------------------------
 
         count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence),
-                loc_nmea_sv_meta_init(sv_meta, GNSS_SV_TYPE_QZSS, false), nmeaArraystr);
+                        loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_QZSS, false),
+                        nmeaArraystr);
         if (count > 0)
         {
             svUsedCount += count;
@@ -559,7 +575,8 @@
         // ---$PQGSA/$GNGSA (BEIDOU)---
         // ----------------------------
         count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence),
-                loc_nmea_sv_meta_init(sv_meta, GNSS_SV_TYPE_BEIDOU, false), nmeaArraystr);
+                        loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_BEIDOU, false),
+                        nmeaArraystr);
         if (count > 0)
         {
             svUsedCount += count;
@@ -931,13 +948,6 @@
 
         length = loc_nmea_put_checksum(sentence, sizeof(sentence));
         nmeaArraystr.push_back(sentence);
-
-        // clear the cache so they can't be used again
-        sv_cache_info.gps_used_mask = 0;
-        sv_cache_info.glo_used_mask = 0;
-        sv_cache_info.gal_used_mask = 0;
-        sv_cache_info.qzss_used_mask = 0;
-        sv_cache_info.bds_used_mask = 0;
     }
     //Send blank NMEA reports for non-final fixes
     else {
@@ -995,20 +1005,9 @@
     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
-
-    sv_cache_info.gps_used_mask = 0;
-    sv_cache_info.glo_used_mask = 0;
-    sv_cache_info.gal_used_mask = 0;
-    sv_cache_info.qzss_used_mask = 0;
-    sv_cache_info.bds_used_mask = 0;
-
-    sv_cache_info.gps_count = 0;
-    sv_cache_info.glo_count = 0;
-    sv_cache_info.gal_count = 0;
-    sv_cache_info.qzss_count = 0;
-    sv_cache_info.bds_count = 0;
     for(svNumber=1; svNumber <= svCount; svNumber++) {
         if (GNSS_SV_TYPE_GPS == svNotify.gnssSvs[svNumber - 1].type)
         {
@@ -1078,35 +1077,38 @@
     // ------------------
 
     loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
-            loc_nmea_sv_meta_init(sv_meta, GNSS_SV_TYPE_GPS, false), nmeaArraystr);
+            loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GPS, false), nmeaArraystr);
 
     // ------------------
     // ------$GLGSV------
     // ------------------
 
     loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
-            loc_nmea_sv_meta_init(sv_meta, GNSS_SV_TYPE_GLONASS, false), nmeaArraystr);
+            loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GLONASS, false),
+            nmeaArraystr);
 
     // ------------------
     // ------$GAGSV------
     // ------------------
 
     loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
-            loc_nmea_sv_meta_init(sv_meta, GNSS_SV_TYPE_GALILEO, false), nmeaArraystr);
+            loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GALILEO, false),
+            nmeaArraystr);
 
     // -------------------------
     // ------$PQGSV (QZSS)------
     // -------------------------
 
     loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
-            loc_nmea_sv_meta_init(sv_meta, GNSS_SV_TYPE_QZSS, false), nmeaArraystr);
+            loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_QZSS, false), nmeaArraystr);
 
     // ---------------------------
     // ------$PQGSV (BEIDOU)------
     // ---------------------------
 
     loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
-            loc_nmea_sv_meta_init(sv_meta, GNSS_SV_TYPE_BEIDOU, false), nmeaArraystr);
+            loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_BEIDOU, false),
+            nmeaArraystr);
 
     EXIT_LOG(%d, 0);
 }