Merge "Assure event mask is set properly to get positions"
diff --git a/sdm845/android/Gnss.cpp b/sdm845/android/Gnss.cpp
index d31a18b..3e83235 100644
--- a/sdm845/android/Gnss.cpp
+++ b/sdm845/android/Gnss.cpp
@@ -380,10 +380,17 @@
         uint32_t minIntervalMs,
         uint32_t preferredAccuracyMeters,
         uint32_t preferredTimeMs,
-        bool /*lowPowerMode*/) {
+        bool lowPowerMode) {
     ENTRY_LOG_CALLFLOW();
-    return setPositionMode(mode, recurrence, minIntervalMs,
-            preferredAccuracyMeters, preferredTimeMs);
+    bool retVal = false;
+    GnssAPIClient* api = getApi();
+    if (api) {
+        GnssPowerMode powerMode = lowPowerMode?
+                GNSS_POWER_MODE_M3 : GNSS_POWER_MODE_M2;
+        retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs,
+                preferredAccuracyMeters, preferredTimeMs, powerMode);
+    }
+    return retVal;
 }
 
 Return<sp<V1_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_1_1() {
diff --git a/sdm845/android/GnssMeasurement.cpp b/sdm845/android/GnssMeasurement.cpp
index 2578a85..ffe5c52 100644
--- a/sdm845/android/GnssMeasurement.cpp
+++ b/sdm845/android/GnssMeasurement.cpp
@@ -100,7 +100,7 @@
 
 // Methods from ::android::hardware::gnss::V1_1::IGnssMeasurement follow.
 Return<GnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_1_1(
-        const sp<IGnssMeasurementCallback>& callback, bool /*enableFullTracking*/) {
+        const sp<IGnssMeasurementCallback>& callback, bool enableFullTracking) {
 
     Return<IGnssMeasurement::GnssMeasurementStatus> ret =
         IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
@@ -113,7 +113,7 @@
         LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
         return ret;
     }
-    if (mApi == nullptr) {
+    if (nullptr == mApi) {
         LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
         return ret;
     }
@@ -121,7 +121,10 @@
     mGnssMeasurementCbIface_1_1 = callback;
     mGnssMeasurementCbIface_1_1->linkToDeath(mGnssMeasurementDeathRecipient, 0);
 
-    return mApi->measurementSetCallback_1_1(callback);
+    GnssPowerMode powerMode = enableFullTracking?
+            GNSS_POWER_MODE_M1 : GNSS_POWER_MODE_M2;
+
+    return mApi->measurementSetCallback_1_1(callback, powerMode);
 }
 
 }  // namespace implementation
diff --git a/sdm845/android/location_api/GnssAPIClient.cpp b/sdm845/android/location_api/GnssAPIClient.cpp
index 6c0f3fb..5941e2a 100644
--- a/sdm845/android/location_api/GnssAPIClient.cpp
+++ b/sdm845/android/location_api/GnssAPIClient.cpp
@@ -62,11 +62,11 @@
     LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
 
     // set default LocationOptions.
-    memset(&mLocationOptions, 0, sizeof(LocationOptions));
-    mLocationOptions.size = sizeof(LocationOptions);
-    mLocationOptions.minInterval = 1000;
-    mLocationOptions.minDistance = 0;
-    mLocationOptions.mode = GNSS_SUPL_MODE_STANDALONE;
+    memset(&mTrackingOptions, 0, sizeof(TrackingOptions));
+    mTrackingOptions.size = sizeof(TrackingOptions);
+    mTrackingOptions.minInterval = 1000;
+    mTrackingOptions.minDistance = 0;
+    mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE;
 
     gnssUpdateCallbacks(gpsCb, niCb);
 }
@@ -142,7 +142,7 @@
 {
     LOC_LOGD("%s]: ()", __FUNCTION__);
     bool retVal = true;
-    locAPIStartTracking(mLocationOptions);
+    locAPIStartTracking(mTrackingOptions);
     return retVal;
 }
 
@@ -156,26 +156,32 @@
 
 bool GnssAPIClient::gnssSetPositionMode(IGnss::GnssPositionMode mode,
         IGnss::GnssPositionRecurrence recurrence, uint32_t minIntervalMs,
-        uint32_t preferredAccuracyMeters, uint32_t preferredTimeMs)
+        uint32_t preferredAccuracyMeters, uint32_t preferredTimeMs,
+        GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
 {
-    LOC_LOGD("%s]: (%d %d %d %d %d)", __FUNCTION__,
-            (int)mode, recurrence, minIntervalMs, preferredAccuracyMeters, preferredTimeMs);
+    LOC_LOGD("%s]: (%d %d %d %d %d %d %d)", __FUNCTION__,
+            (int)mode, recurrence, minIntervalMs, preferredAccuracyMeters,
+            preferredTimeMs, (int)powerMode, timeBetweenMeasurement);
     bool retVal = true;
-    memset(&mLocationOptions, 0, sizeof(LocationOptions));
-    mLocationOptions.size = sizeof(LocationOptions);
-    mLocationOptions.minInterval = minIntervalMs;
-    mLocationOptions.minDistance = preferredAccuracyMeters;
+    memset(&mTrackingOptions, 0, sizeof(TrackingOptions));
+    mTrackingOptions.size = sizeof(TrackingOptions);
+    mTrackingOptions.minInterval = minIntervalMs;
+    mTrackingOptions.minDistance = preferredAccuracyMeters;
     if (mode == IGnss::GnssPositionMode::STANDALONE)
-        mLocationOptions.mode = GNSS_SUPL_MODE_STANDALONE;
+        mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE;
     else if (mode == IGnss::GnssPositionMode::MS_BASED)
-        mLocationOptions.mode = GNSS_SUPL_MODE_MSB;
+        mTrackingOptions.mode = GNSS_SUPL_MODE_MSB;
     else if (mode ==  IGnss::GnssPositionMode::MS_ASSISTED)
-        mLocationOptions.mode = GNSS_SUPL_MODE_MSA;
+        mTrackingOptions.mode = GNSS_SUPL_MODE_MSA;
     else {
         LOC_LOGD("%s]: invalid GnssPositionMode: %d", __FUNCTION__, (int)mode);
         retVal = false;
     }
-    locAPIUpdateTrackingOptions(mLocationOptions);
+    if (GNSS_POWER_MODE_INVALID != powerMode) {
+        mTrackingOptions.powerMode = powerMode;
+        mTrackingOptions.tbm = timeBetweenMeasurement;
+    }
+    locAPIUpdateTrackingOptions(mTrackingOptions);
     return retVal;
 }
 
diff --git a/sdm845/android/location_api/GnssAPIClient.h b/sdm845/android/location_api/GnssAPIClient.h
index f23ba64..82f8fbf 100644
--- a/sdm845/android/location_api/GnssAPIClient.h
+++ b/sdm845/android/location_api/GnssAPIClient.h
@@ -63,7 +63,9 @@
             V1_0::IGnss::GnssPositionRecurrence recurrence,
             uint32_t minIntervalMs,
             uint32_t preferredAccuracyMeters,
-            uint32_t preferredTimeMs);
+            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);
@@ -96,7 +98,7 @@
     LocationAPIControlClient* mControlClient;
     LocationCapabilitiesMask mLocationCapabilitiesMask;
     bool mLocationCapabilitiesCached;
-    LocationOptions mLocationOptions;
+    TrackingOptions mTrackingOptions;
 };
 
 }  // namespace implementation
diff --git a/sdm845/android/location_api/MeasurementAPIClient.cpp b/sdm845/android/location_api/MeasurementAPIClient.cpp
index 4b7dcb8..7ab5432 100644
--- a/sdm845/android/location_api/MeasurementAPIClient.cpp
+++ b/sdm845/android/location_api/MeasurementAPIClient.cpp
@@ -80,19 +80,23 @@
 }
 
 Return<IGnssMeasurement::GnssMeasurementStatus>
-MeasurementAPIClient::measurementSetCallback_1_1(const sp<IGnssMeasurementCallback>& callback)
+MeasurementAPIClient::measurementSetCallback_1_1(
+        const sp<IGnssMeasurementCallback>& callback,
+        GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
 {
-    LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+    LOC_LOGD("%s]: (%p) (powermode: %d) (tbm: %d)",
+            __FUNCTION__, &callback, (int)powerMode, timeBetweenMeasurement);
 
     mMutex.lock();
     mGnssMeasurementCbIface_1_1 = callback;
     mMutex.unlock();
 
-    return startTracking();
+    return startTracking(powerMode, timeBetweenMeasurement);
 }
 
 Return<IGnssMeasurement::GnssMeasurementStatus>
-MeasurementAPIClient::startTracking()
+MeasurementAPIClient::startTracking(
+        GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
 {
     LocationCallbacks locationCallbacks;
     memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
@@ -116,15 +120,20 @@
     }
 
     locAPISetCallbacks(locationCallbacks);
-    LocationOptions options;
-    memset(&options, 0, sizeof(LocationOptions));
-    options.size = sizeof(LocationOptions);
+
+    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;
 }
 
diff --git a/sdm845/android/location_api/MeasurementAPIClient.h b/sdm845/android/location_api/MeasurementAPIClient.h
index 117ad54..38811c5 100644
--- a/sdm845/android/location_api/MeasurementAPIClient.h
+++ b/sdm845/android/location_api/MeasurementAPIClient.h
@@ -35,6 +35,7 @@
 #include <android/hardware/gnss/1.1/IGnssMeasurementCallback.h>
 #include <LocationAPIClientBase.h>
 #include <hidl/Status.h>
+#include <gps_extended_c.h>
 
 namespace android {
 namespace hardware {
@@ -56,9 +57,13 @@
     Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback(
             const sp<V1_0::IGnssMeasurementCallback>& callback);
     Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback_1_1(
-            const sp<IGnssMeasurementCallback>& callback);
+            const sp<IGnssMeasurementCallback>& callback,
+            GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+            uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS);
     void measurementClose();
-    Return<IGnssMeasurement::GnssMeasurementStatus> startTracking();
+    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;
diff --git a/sdm845/core/ContextBase.cpp b/sdm845/core/ContextBase.cpp
index 35e6585..5ddeeaf 100644
--- a/sdm845/core/ContextBase.cpp
+++ b/sdm845/core/ContextBase.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2014,2016-2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014,2016-2018 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
@@ -96,7 +96,7 @@
    mGps_conf.INTERMEDIATE_POS = 0;
    mGps_conf.ACCURACY_THRES = 0;
    mGps_conf.NMEA_PROVIDER = 0;
-   mGps_conf.GPS_LOCK = 0;
+   mGps_conf.GPS_LOCK = 0x03;
    mGps_conf.SUPL_VER = 0x10000;
    mGps_conf.SUPL_MODE = 0x1;
    mGps_conf.SUPL_ES = 0;
diff --git a/sdm845/core/LocAdapterBase.cpp b/sdm845/core/LocAdapterBase.cpp
index 162b14b..ccbbce9 100644
--- a/sdm845/core/LocAdapterBase.cpp
+++ b/sdm845/core/LocAdapterBase.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2014, 2016-2017The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 2016-2018 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
@@ -42,8 +42,9 @@
 // But if getLocApi(targetEnumType target) is overriden,
 // the right locApi should get created.
 LocAdapterBase::LocAdapterBase(const LOC_API_ADAPTER_EVENT_MASK_T mask,
-                               ContextBase* context, LocAdapterProxyBase *adapterProxyBase) :
-    mEvtMask(mask), mContext(context),
+                               ContextBase* context, bool isMaster,
+                               LocAdapterProxyBase *adapterProxyBase) :
+    mIsMaster(isMaster), mEvtMask(mask), mContext(context),
     mLocApi(context->getLocApi()), mLocAdapterProxyBase(adapterProxyBase),
     mMsgTask(context->getMsgTask())
 {
diff --git a/sdm845/core/LocAdapterBase.h b/sdm845/core/LocAdapterBase.h
index d08864d..2e9f7f9 100644
--- a/sdm845/core/LocAdapterBase.h
+++ b/sdm845/core/LocAdapterBase.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2014, 2016-2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 2016-2018 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
@@ -51,6 +51,7 @@
     return left.id != right.id || left.client != right.client;
 }
 typedef std::map<LocationSessionKey, LocationOptions> LocationSessionMap;
+typedef std::map<LocationSessionKey, TrackingOptions> TrackingOptionsMap;
 
 namespace loc_core {
 
@@ -59,6 +60,7 @@
 class LocAdapterBase {
 private:
     static uint32_t mSessionIdCounter;
+    const bool mIsMaster;
 protected:
     LOC_API_ADAPTER_EVENT_MASK_T mEvtMask;
     ContextBase* mContext;
@@ -66,12 +68,18 @@
     LocAdapterProxyBase* mLocAdapterProxyBase;
     const MsgTask* mMsgTask;
     inline LocAdapterBase(const MsgTask* msgTask) :
-        mEvtMask(0), mContext(NULL), mLocApi(NULL),
+        mIsMaster(false), mEvtMask(0), mContext(NULL), mLocApi(NULL),
         mLocAdapterProxyBase(NULL), mMsgTask(msgTask) {}
+    LocAdapterBase(const LOC_API_ADAPTER_EVENT_MASK_T mask,
+        ContextBase* context, bool isMaster,
+        LocAdapterProxyBase *adapterProxyBase = NULL);
 public:
     inline virtual ~LocAdapterBase() { mLocApi->removeAdapter(this); }
-    LocAdapterBase(const LOC_API_ADAPTER_EVENT_MASK_T mask,
-                   ContextBase* context, LocAdapterProxyBase *adapterProxyBase = NULL);
+    inline LocAdapterBase(const LOC_API_ADAPTER_EVENT_MASK_T mask,
+                          ContextBase* context,
+                          LocAdapterProxyBase *adapterProxyBase = NULL) :
+        LocAdapterBase(mask, context, false, adapterProxyBase) {}
+
     inline LOC_API_ADAPTER_EVENT_MASK_T
         checkMask(LOC_API_ADAPTER_EVENT_MASK_T mask) const {
         return mEvtMask & mask;
@@ -112,6 +120,10 @@
 
     uint32_t generateSessionId();
 
+    inline bool isAdapterMaster() {
+        return mIsMaster;
+    }
+
     // This will be overridden by the individual adapters
     // if necessary.
     inline virtual void setUlpProxyCommand(UlpProxyBase* ulp) {
diff --git a/sdm845/core/LocApiBase.cpp b/sdm845/core/LocApiBase.cpp
index c7dac3b..3d129e3 100644
--- a/sdm845/core/LocApiBase.cpp
+++ b/sdm845/core/LocApiBase.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2014, 2016-2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 2016-2018 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
@@ -142,6 +142,18 @@
     return mask & ~mExcludedMask;
 }
 
+bool LocApiBase::isMaster()
+{
+    bool isMaster = false;
+
+    for (int i = 0;
+            !isMaster && i < MAX_ADAPTERS && NULL != mLocAdapters[i];
+            i++) {
+        isMaster |= mLocAdapters[i]->isAdapterMaster();
+    }
+    return isMaster;
+}
+
 bool LocApiBase::isInSession()
 {
     bool inSession = false;
@@ -603,7 +615,7 @@
 DEFAULT_IMPL()
 
 int LocApiBase::
-    getGpsLock()
+    getGpsLock(uint8_t /*subType*/)
 DEFAULT_IMPL(-1)
 
 LocationError LocApiBase::
diff --git a/sdm845/core/LocApiBase.h b/sdm845/core/LocApiBase.h
index 042ef2c..2ffdd45 100644
--- a/sdm845/core/LocApiBase.h
+++ b/sdm845/core/LocApiBase.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2014, 2016-2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 2016-2018 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
@@ -98,6 +98,7 @@
     inline virtual ~LocApiBase() { close(); }
     bool isInSession();
     const LOC_API_ADAPTER_EVENT_MASK_T mExcludedMask;
+    bool isMaster();
 
 public:
     inline void sendMsg(const LocMsg* msg) const {
@@ -246,7 +247,7 @@
       Current value of GPS Lock on success
       -1 on failure
      */
-    virtual int getGpsLock(void);
+    virtual int getGpsLock(uint8_t subType);
 
     virtual LocationError setXtraVersionCheck(uint32_t check);
     /*
diff --git a/sdm845/core/loc_core_log.cpp b/sdm845/core/loc_core_log.cpp
index 139902c..865f311 100644
--- a/sdm845/core/loc_core_log.cpp
+++ b/sdm845/core/loc_core_log.cpp
@@ -39,14 +39,17 @@
 {
     LOC_LOGV ("Position mode: %s\n  Position recurrence: %s\n  "
               "min interval: %d\n  preferred accuracy: %d\n  "
-              "preferred time: %d\n  credentials: %s  provider: %s",
+              "preferred time: %d\n  credentials: %s  provider: %s \n  "
+              "power mode: %d\n  tbm %d",
               loc_get_position_mode_name(mode),
               loc_get_position_recurrence_name(recurrence),
               min_interval,
               preferred_accuracy,
               preferred_time,
               credentials,
-              provider);
+              provider,
+              powerMode,
+              timeBetweenMeasurements);
 }
 
 /* GPS status names */
diff --git a/sdm845/etc/gps.conf b/sdm845/etc/gps.conf
index d30461e..6cd410a 100644
--- a/sdm845/etc/gps.conf
+++ b/sdm845/etc/gps.conf
@@ -34,8 +34,8 @@
 # should be locked when user turns off GPS on Settings
 # Set bit 0x1 if MO GPS functionalities are to be locked
 # Set bit 0x2 if NI GPS functionalities are to be locked
-# default - non is locked for backward compatibility
-#GPS_LOCK = 0
+# default – both MO and NI locked for maximal privacy
+#GPS_LOCK = 3
 
 # supl version 1.0
 SUPL_VER=0x10000
diff --git a/sdm845/gnss/GnssAdapter.cpp b/sdm845/gnss/GnssAdapter.cpp
index bc1e111..45a5260 100644
--- a/sdm845/gnss/GnssAdapter.cpp
+++ b/sdm845/gnss/GnssAdapter.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -64,7 +64,7 @@
                    LocDualContext::getLocFgContext(NULL,
                                                    NULL,
                                                    LocDualContext::mLocationHalName,
-                                                   false)),
+                                                   false), true, nullptr),
     mUlpProxy(new UlpProxyBase()),
     mUlpPositionMode(),
     mGnssSvIdUsedInPosition(),
@@ -172,10 +172,9 @@
 }
 
 void
-GnssAdapter::convertOptions(LocPosMode& out, const LocationOptions& options)
+GnssAdapter::convertOptions(LocPosMode& out, const TrackingOptions& trackingOptions)
 {
-    LocPosMode locPosMode = {};
-    switch (options.mode) {
+    switch (trackingOptions.mode) {
     case GNSS_SUPL_MODE_MSB:
         out.mode = LOC_POSITION_MODE_MS_BASED;
         break;
@@ -187,7 +186,9 @@
         break;
     }
     out.share_position = true;
-    out.min_interval = options.minInterval;
+    out.min_interval = trackingOptions.minInterval;
+    out.powerMode = trackingOptions.powerMode;
+    out.timeBetweenMeasurements = trackingOptions.tbm;
 }
 
 void
@@ -762,6 +763,10 @@
             if (mConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
                 uint32_t newGpsLock = mAdapter.convertGpsLock(mConfig.gpsLock);
                 ContextBase::mGps_conf.GPS_LOCK = newGpsLock;
+                if (0 == ContextBase::mGps_conf.GPS_LOCK) {
+                    // we should minimally lock MO
+                    ContextBase::mGps_conf.GPS_LOCK = 1;
+                }
                 if (0 == mAdapter.getPowerVoteId()) {
                     err = mApi.setGpsLock(mConfig.gpsLock);
                 }
@@ -1741,16 +1746,26 @@
     }
 
     // get the LocationOptions that has the smallest interval, which should be the active one
-    LocationOptions smallestIntervalOptions = {}; // size is zero until set for the first time
+    TrackingOptions smallestIntervalOptions = {}; // size is zero until set for the first time
+    TrackingOptions highestPowerTrackingOptions = {};
     for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) {
-        if (0 == smallestIntervalOptions.size || //size of zero means we havent set it yet
+        // size of zero means we havent set it yet
+        if (0 == smallestIntervalOptions.size ||
             it->second.minInterval < smallestIntervalOptions.minInterval) {
              smallestIntervalOptions = it->second;
         }
+        GnssPowerMode powerMode = it->second.powerMode;
+        // Size of zero means we havent set it yet
+        if (0 == highestPowerTrackingOptions.size ||
+            (GNSS_POWER_MODE_INVALID != powerMode &&
+                    powerMode < highestPowerTrackingOptions.powerMode)) {
+             highestPowerTrackingOptions = it->second;
+        }
     }
 
     LocPosMode locPosMode = {};
-    convertOptions(locPosMode, smallestIntervalOptions);
+    highestPowerTrackingOptions.setLocationOptions(smallestIntervalOptions);
+    convertOptions(locPosMode, highestPowerTrackingOptions);
     mLocApi->startFix(locPosMode);
 }
 
@@ -1879,21 +1894,20 @@
 
 void
 GnssAdapter::saveTrackingSession(LocationAPI* client, uint32_t sessionId,
-                                 const LocationOptions& options)
+                                 const TrackingOptions& trackingOptions)
 {
     LocationSessionKey key(client, sessionId);
-    mTrackingSessions[key] = options;
+    mTrackingSessions[key] = trackingOptions;
 }
 
 void
 GnssAdapter::eraseTrackingSession(LocationAPI* client, uint32_t sessionId)
 {
     LocationSessionKey key(client, sessionId);
-    auto it = mTrackingSessions.find(key);
-    if (it != mTrackingSessions.end()) {
-        mTrackingSessions.erase(it);
+    auto itr = mTrackingSessions.find(key);
+    if (itr != mTrackingSessions.end()) {
+        mTrackingSessions.erase(itr);
     }
-
 }
 
 bool GnssAdapter::setUlpPositionMode(const LocPosMode& mode) {
@@ -1958,72 +1972,91 @@
 }
 
 uint32_t
-GnssAdapter::startTrackingCommand(LocationAPI* client, LocationOptions& options)
+GnssAdapter::startTrackingCommand(LocationAPI* client, TrackingOptions& options)
 {
     uint32_t sessionId = generateSessionId();
-    LOC_LOGD("%s]: client %p id %u minInterval %u mode %u",
-             __func__, client, sessionId, options.minInterval, options.mode);
+    LOC_LOGD("%s]: client %p id %u minInterval %u minDistance %u mode %u powermode %u tbm %u",
+             __func__, client, sessionId, options.minInterval, options.minDistance, options.mode,
+             options.powerMode, options.tbm);
 
     struct MsgStartTracking : public LocMsg {
         GnssAdapter& mAdapter;
         LocApiBase& mApi;
         LocationAPI* mClient;
         uint32_t mSessionId;
-        LocationOptions mOptions;
+        mutable TrackingOptions mTrackingOptions;
         inline MsgStartTracking(GnssAdapter& adapter,
                                LocApiBase& api,
                                LocationAPI* client,
                                uint32_t sessionId,
-                               LocationOptions options) :
+                               TrackingOptions trackingOptions) :
             LocMsg(),
             mAdapter(adapter),
             mApi(api),
             mClient(client),
             mSessionId(sessionId),
-            mOptions(options) {}
+            mTrackingOptions(trackingOptions) {}
         inline virtual void proc() const {
             LocationError err = LOCATION_ERROR_SUCCESS;
             if (!mAdapter.hasTrackingCallback(mClient) &&
                 !mAdapter.hasMeasurementsCallback(mClient)) {
                 err = LOCATION_ERROR_CALLBACK_MISSING;
-            } else if (0 == mOptions.size) {
+            } else if (0 == mTrackingOptions.size) {
                 err = LOCATION_ERROR_INVALID_PARAMETER;
             } else {
+                if (GNSS_POWER_MODE_INVALID != mTrackingOptions.powerMode &&
+                        !mApi.isFeatureSupported(LOC_SUPPORTED_FEATURE_AGPM_V02)) {
+                    LOC_LOGv("Ignoring power mode, feature not supported.");
+                    mTrackingOptions.powerMode = GNSS_POWER_MODE_INVALID;
+                }
                 // Api doesn't support multiple clients for time based tracking, so mutiplex
-                err = mAdapter.startTrackingMultiplex(mOptions);
+                err = mAdapter.startTrackingMultiplex(mTrackingOptions);
                 if (LOCATION_ERROR_SUCCESS == err) {
-                    mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
+                    mAdapter.saveTrackingSession(
+                            mClient, mSessionId, mTrackingOptions);
                 }
             }
             mAdapter.reportResponse(mClient, err, mSessionId);
         }
     };
 
-    sendMsg(new MsgStartTracking(*this, *mLocApi, client, sessionId, options));
+    sendMsg(new MsgStartTracking(
+            *this, *mLocApi, client, sessionId, options));
     return sessionId;
-
 }
 
 LocationError
-GnssAdapter::startTrackingMultiplex(const LocationOptions& options)
+GnssAdapter::startTrackingMultiplex(const TrackingOptions& options)
 {
     LocationError err = LOCATION_ERROR_SUCCESS;
 
     if (mTrackingSessions.empty()) {
         err = startTracking(options);
     } else {
-        // get the LocationOptions that has the smallest interval, which should be the active one
-        LocationOptions smallestIntervalOptions = {}; // size is zero until set for the first time
+        // Get the LocationOptions that has the smallest interval,
+        // which should be the active one
+        // Also get the highest power tracking options
+        TrackingOptions smallestIntervalOptions = {};
+        TrackingOptions highestPowerTrackingOptions = options;
         for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) {
-            if (0 == smallestIntervalOptions.size || //size of zero means we havent set it yet
+            GnssPowerMode powerMode = it->second.powerMode;
+            // Size of zero means we havent set it yet
+            if (0 == smallestIntervalOptions.size ||
                 it->second.minInterval < smallestIntervalOptions.minInterval) {
                  smallestIntervalOptions = it->second;
             }
+            // Size of zero means we havent set it yet
+            if (0 == highestPowerTrackingOptions.size ||
+                (GNSS_POWER_MODE_INVALID != powerMode &&
+                        powerMode < highestPowerTrackingOptions.powerMode)) {
+                 highestPowerTrackingOptions = it->second;
+            }
         }
         // if new session's minInterval is smaller than any in other sessions
         if (options.minInterval < smallestIntervalOptions.minInterval) {
             // restart time based tracking with new options
-            err = startTracking(options);
+            highestPowerTrackingOptions.setLocationOptions(smallestIntervalOptions);
+            err = startTracking(highestPowerTrackingOptions);
         }
     }
 
@@ -2031,11 +2064,11 @@
 }
 
 LocationError
-GnssAdapter::startTracking(const LocationOptions& options)
+GnssAdapter::startTracking(const TrackingOptions& trackingOptions)
 {
     LocationError err = LOCATION_ERROR_SUCCESS;
     LocPosMode locPosMode = {};
-    convertOptions(locPosMode, options);
+    convertOptions(locPosMode, trackingOptions);
     if (!mUlpProxy->sendFixMode(locPosMode)) {
         // do nothing
     }
@@ -2107,7 +2140,7 @@
 
 void
 GnssAdapter::updateTrackingOptionsCommand(LocationAPI* client, uint32_t id,
-                                          LocationOptions& options)
+                                          TrackingOptions& options)
 {
     LOC_LOGD("%s]: client %p id %u minInterval %u mode %u",
              __func__, client, id, options.minInterval, options.mode);
@@ -2117,28 +2150,35 @@
         LocApiBase& mApi;
         LocationAPI* mClient;
         uint32_t mSessionId;
-        LocationOptions mOptions;
+        mutable TrackingOptions mTrackingOptions;
         inline MsgUpdateTracking(GnssAdapter& adapter,
                                 LocApiBase& api,
                                 LocationAPI* client,
                                 uint32_t sessionId,
-                                LocationOptions options) :
+                                TrackingOptions trackingOptions) :
             LocMsg(),
             mAdapter(adapter),
             mApi(api),
             mClient(client),
             mSessionId(sessionId),
-            mOptions(options) {}
+            mTrackingOptions(trackingOptions) {}
         inline virtual void proc() const {
             if (mAdapter.isTrackingSession(mClient, mSessionId)) {
                 LocationError err = LOCATION_ERROR_SUCCESS;
-                if (0 == mOptions.size) {
+                if (0 == mTrackingOptions.size) {
                     err = LOCATION_ERROR_INVALID_PARAMETER;
                 } else {
+                    if (GNSS_POWER_MODE_INVALID != mTrackingOptions.powerMode &&
+                            !mApi.isFeatureSupported(LOC_SUPPORTED_FEATURE_AGPM_V02)) {
+                        LOC_LOGv("Ignoring power mode, feature not supported.");
+                        mTrackingOptions.powerMode = GNSS_POWER_MODE_INVALID;
+                    }
                     // Api doesn't support multiple clients for time based tracking, so mutiplex
-                    err = mAdapter.updateTrackingMultiplex(mClient, mSessionId, mOptions);
+                    err = mAdapter.updateTrackingMultiplex(
+                            mClient, mSessionId, mTrackingOptions);
                     if (LOCATION_ERROR_SUCCESS == err) {
-                        mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
+                        mAdapter.saveTrackingSession(
+                                mClient, mSessionId, mTrackingOptions);
                     }
                 }
                 mAdapter.reportResponse(mClient, err, mSessionId);
@@ -2154,12 +2194,12 @@
 
 LocationError
 GnssAdapter::updateTrackingMultiplex(LocationAPI* client, uint32_t id,
-                                     const LocationOptions& options)
+                                     const TrackingOptions& trackingOptions)
 {
     LocationError err = LOCATION_ERROR_SUCCESS;
 
     if (1 == mTrackingSessions.size()) {
-        err = startTracking(options);
+        err = startTracking(trackingOptions);
     } else {
         LocationSessionKey key(client, id);
 
@@ -2167,23 +2207,34 @@
         auto it = mTrackingSessions.find(key);
         if (it != mTrackingSessions.end()) {
             // find the smallest interval, other than the session we are updating
-            LocationOptions smallestIntervalOptions = {}; // size is 0 until set for the first time
+            TrackingOptions smallestIntervalOptions = {}; // size is 0 until set for the first time
+            TrackingOptions highestPowerTrackingOptions = trackingOptions;
             for (auto it2 = mTrackingSessions.begin(); it2 != mTrackingSessions.end(); ++it2) {
-                // if session is not the one we are updating and either smallest interval is not set
-                // or there is a new smallest interval, then set the new smallest interval
+                GnssPowerMode powerMode = it2->second.powerMode;
+                // if session is not the one we are updating and either smallest
+                // interval is not set or there is a new smallest interval,
+                // then set the new smallest interval
                 if (it2->first != key && (0 == smallestIntervalOptions.size ||
                     it2->second.minInterval < smallestIntervalOptions.minInterval)) {
                      smallestIntervalOptions = it2->second;
                 }
+                // size of zero means we havent set it yet
+                if (0 == highestPowerTrackingOptions.size ||
+                    (GNSS_POWER_MODE_INVALID != powerMode &&
+                            powerMode < highestPowerTrackingOptions.powerMode)) {
+                     highestPowerTrackingOptions = it2->second;
+                }
             }
             // if session we are updating has smaller interval then next smallest
-            if (options.minInterval < smallestIntervalOptions.minInterval) {
+            if (trackingOptions.minInterval < smallestIntervalOptions.minInterval) {
                 // restart time based tracking with the newly updated interval
-                err = startTracking(options);
+                highestPowerTrackingOptions.setLocationOptions(trackingOptions);
+                err = startTracking(highestPowerTrackingOptions);
             // else if the session we are updating used to be the smallest
             } else if (it->second.minInterval < smallestIntervalOptions.minInterval) {
                 // restart time based tracking with the next smallest
-                err = startTracking(smallestIntervalOptions);
+                highestPowerTrackingOptions.setLocationOptions(smallestIntervalOptions);
+                err = startTracking(highestPowerTrackingOptions);
             }
         }
     }
@@ -2244,7 +2295,8 @@
         auto it = mTrackingSessions.find(key);
         if (it != mTrackingSessions.end()) {
             // find the next smallest interval, other than the session we are stopping
-            LocationOptions smallestIntervalOptions = {}; // size is 0 until set for the first time
+            TrackingOptions smallestIntervalOptions = {}; // size is 0 until set for the first time
+            TrackingOptions highestPowerTrackingOptions = {};
             for (auto it2 = mTrackingSessions.begin(); it2 != mTrackingSessions.end(); ++it2) {
                 // if session is not the one we are stopping and either smallest interval is not set
                 // or there is a new smallest interval, then set the new smallest interval
@@ -2252,11 +2304,19 @@
                     it2->second.minInterval < smallestIntervalOptions.minInterval)) {
                      smallestIntervalOptions = it2->second;
                 }
+                GnssPowerMode powerMode = it2->second.powerMode;
+                // Size of zero means we havent set it yet
+                if (0 == highestPowerTrackingOptions.size ||
+                    (GNSS_POWER_MODE_INVALID != powerMode &&
+                            powerMode < highestPowerTrackingOptions.powerMode)) {
+                     highestPowerTrackingOptions = it2->second;
+                }
             }
             // if session we are stopping has smaller interval then next smallest
             if (it->second.minInterval < smallestIntervalOptions.minInterval) {
                 // restart time based tracking with next smallest interval
-                err = startTracking(smallestIntervalOptions);
+                highestPowerTrackingOptions.setLocationOptions(smallestIntervalOptions);
+                err = startTracking(highestPowerTrackingOptions);
             }
         }
     }
diff --git a/sdm845/gnss/GnssAdapter.h b/sdm845/gnss/GnssAdapter.h
index 580c7cd..2531b89 100644
--- a/sdm845/gnss/GnssAdapter.h
+++ b/sdm845/gnss/GnssAdapter.h
@@ -89,7 +89,7 @@
     ClientDataMap mClientData;
 
     /* ==== TRACKING ======================================================================= */
-    LocationSessionMap mTrackingSessions;
+    TrackingOptionsMap mTrackingSessions;
     LocPosMode mUlpPositionMode;
     GnssSvUsedInPosition mGnssSvIdUsedInPosition;
     bool mGnssSvIdUsedInPosAvail;
@@ -117,7 +117,7 @@
     XtraSystemStatusObserver mXtraObserver;
 
     /*==== CONVERSION ===================================================================*/
-    static void convertOptions(LocPosMode& out, const LocationOptions& options);
+    static void convertOptions(LocPosMode& out, const TrackingOptions& trackingOptions);
     static void convertLocation(Location& out, const LocGpsLocation& locGpsLocation,
                                 const GpsLocationExtended& locationExtended,
                                 const LocPosTechMask techMask);
@@ -159,8 +159,10 @@
 
     /* ==== TRACKING ======================================================================= */
     /* ======== COMMANDS ====(Called from Client Thread)==================================== */
-    uint32_t startTrackingCommand(LocationAPI* client, LocationOptions& options);
-    void updateTrackingOptionsCommand(LocationAPI* client, uint32_t id, LocationOptions& options);
+    uint32_t startTrackingCommand(
+            LocationAPI* client, TrackingOptions& trackingOptions);
+    void updateTrackingOptionsCommand(
+            LocationAPI* client, uint32_t id, TrackingOptions& trackingOptions);
     void stopTrackingCommand(LocationAPI* client, uint32_t id);
     /* ======================(Called from ULP Thread)======================================= */
     virtual void setPositionModeCommand(LocPosMode& locPosMode);
@@ -174,16 +176,16 @@
     bool hasMeasurementsCallback(LocationAPI* client);
     bool isTrackingSession(LocationAPI* client, uint32_t sessionId);
     void saveTrackingSession(LocationAPI* client, uint32_t sessionId,
-                             const LocationOptions& options);
+                             const TrackingOptions& trackingOptions);
     void eraseTrackingSession(LocationAPI* client, uint32_t sessionId);
     bool setUlpPositionMode(const LocPosMode& mode);
     LocPosMode& getUlpPositionMode() { return mUlpPositionMode; }
-    LocationError startTrackingMultiplex(const LocationOptions& options);
-    LocationError startTracking(const LocationOptions& options);
+    LocationError startTrackingMultiplex(const TrackingOptions& trackingOptions);
+    LocationError startTracking(const TrackingOptions& trackingOptions);
     LocationError stopTrackingMultiplex(LocationAPI* client, uint32_t id);
     LocationError stopTracking();
     LocationError updateTrackingMultiplex(LocationAPI* client, uint32_t id,
-                                          const LocationOptions& options);
+                                          const TrackingOptions& trackingOptions);
 
     /* ==== NI ============================================================================= */
     /* ======== COMMANDS ====(Called from Client Thread)==================================== */
diff --git a/sdm845/gnss/location_gnss.cpp b/sdm845/gnss/location_gnss.cpp
index 0dac13d..3490395 100644
--- a/sdm845/gnss/location_gnss.cpp
+++ b/sdm845/gnss/location_gnss.cpp
@@ -39,8 +39,8 @@
 static void removeClient(LocationAPI* client);
 static void requestCapabilities(LocationAPI* client);
 
-static uint32_t startTracking(LocationAPI* client, LocationOptions& options);
-static void updateTrackingOptions(LocationAPI* client, uint32_t id, LocationOptions& options);
+static uint32_t startTracking(LocationAPI* client, TrackingOptions&);
+static void updateTrackingOptions(LocationAPI* client, uint32_t id, TrackingOptions&);
 static void stopTracking(LocationAPI* client, uint32_t id);
 
 static void gnssNiResponse(LocationAPI* client, uint32_t id, GnssNiResponse response);
@@ -143,19 +143,22 @@
     }
 }
 
-static uint32_t startTracking(LocationAPI* client, LocationOptions& options)
+static uint32_t startTracking(
+        LocationAPI* client, TrackingOptions& trackingOptions)
 {
     if (NULL != gGnssAdapter) {
-        return gGnssAdapter->startTrackingCommand(client, options);
+        return gGnssAdapter->startTrackingCommand(client, trackingOptions);
     } else {
         return 0;
     }
 }
 
-static void updateTrackingOptions(LocationAPI* client, uint32_t id, LocationOptions& options)
+static void updateTrackingOptions(
+        LocationAPI* client, uint32_t id, TrackingOptions& trackingOptions)
 {
     if (NULL != gGnssAdapter) {
-        gGnssAdapter->updateTrackingOptionsCommand(client, id, options);
+        gGnssAdapter->updateTrackingOptionsCommand(
+                client, id, trackingOptions);
     }
 }
 
diff --git a/sdm845/location/LocationAPI.cpp b/sdm845/location/LocationAPI.cpp
index 6bd5b15..5547f1a 100644
--- a/sdm845/location/LocationAPI.cpp
+++ b/sdm845/location/LocationAPI.cpp
@@ -25,6 +25,7 @@
  * 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_LocationAPI"
 
 #include <location_interface.h>
@@ -288,21 +289,21 @@
 }
 
 uint32_t
-LocationAPI::startTracking(LocationOptions& locationOptions)
+LocationAPI::startTracking(TrackingOptions& trackingOptions)
 {
     uint32_t id = 0;
     pthread_mutex_lock(&gDataMutex);
 
     auto it = gData.clientData.find(this);
     if (it != gData.clientData.end()) {
-        if (gData.flpInterface != NULL && locationOptions.minDistance > 0) {
-            id = gData.flpInterface->startTracking(this, locationOptions);
-        } else if (gData.gnssInterface != NULL && needsGnssTrackingInfo(it->second)) {
-            id = gData.gnssInterface->startTracking(this, locationOptions);
-        } else if (gData.flpInterface != NULL) {
-            id = gData.flpInterface->startTracking(this, locationOptions);
-        } else if (gData.gnssInterface != NULL) {
-            id = gData.gnssInterface->startTracking(this, locationOptions);
+        if (NULL != gData.flpInterface && trackingOptions.minDistance > 0) {
+            id = gData.flpInterface->startTracking(this, trackingOptions);
+        } else if (NULL != gData.gnssInterface && needsGnssTrackingInfo(it->second)) {
+            id = gData.gnssInterface->startTracking(this, trackingOptions);
+        } else if (NULL != gData.flpInterface) {
+            id = gData.flpInterface->startTracking(this, trackingOptions);
+        } else if (NULL != gData.gnssInterface) {
+            id = gData.gnssInterface->startTracking(this, trackingOptions);
         } else {
             LOC_LOGE("%s:%d]: No gnss/flp interface available for Location API client %p ",
                      __func__, __LINE__, this);
@@ -344,7 +345,8 @@
 }
 
 void
-LocationAPI::updateTrackingOptions(uint32_t id, LocationOptions& locationOptions)
+LocationAPI::updateTrackingOptions(
+        uint32_t id, TrackingOptions& trackingOptions)
 {
     pthread_mutex_lock(&gDataMutex);
 
@@ -353,10 +355,10 @@
         // we don't know if tracking was started on flp or gnss, so we call update on both, where
         // updateTracking call to the incorrect interface will fail without response back to client
         if (gData.gnssInterface != NULL) {
-            gData.gnssInterface->updateTrackingOptions(this, id, locationOptions);
+            gData.gnssInterface->updateTrackingOptions(this, id, trackingOptions);
         }
         if (gData.flpInterface != NULL) {
-            gData.flpInterface->updateTrackingOptions(this, id, locationOptions);
+            gData.flpInterface->updateTrackingOptions(this, id, trackingOptions);
         }
         if (gData.flpInterface == NULL && gData.gnssInterface == NULL) {
             LOC_LOGE("%s:%d]: No gnss/flp interface available for Location API client %p ",
@@ -371,13 +373,13 @@
 }
 
 uint32_t
-LocationAPI::startBatching(LocationOptions& locationOptions, BatchingOptions &batchingOptions)
+LocationAPI::startBatching(BatchingOptions &batchingOptions)
 {
     uint32_t id = 0;
     pthread_mutex_lock(&gDataMutex);
 
-    if (gData.flpInterface != NULL) {
-        id = gData.flpInterface->startBatching(this, locationOptions, batchingOptions);
+    if (NULL != gData.flpInterface) {
+        id = gData.flpInterface->startBatching(this, batchingOptions);
     } else {
         LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ",
                  __func__, __LINE__, this);
@@ -392,7 +394,7 @@
 {
     pthread_mutex_lock(&gDataMutex);
 
-    if (gData.flpInterface != NULL) {
+    if (NULL != gData.flpInterface) {
         gData.flpInterface->stopBatching(this, id);
     } else {
         LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ",
@@ -403,16 +405,12 @@
 }
 
 void
-LocationAPI::updateBatchingOptions(uint32_t id,
-        LocationOptions& locationOptions, BatchingOptions& batchOptions)
+LocationAPI::updateBatchingOptions(uint32_t id, BatchingOptions& batchOptions)
 {
     pthread_mutex_lock(&gDataMutex);
 
-    if (gData.flpInterface != NULL) {
-        gData.flpInterface->updateBatchingOptions(this,
-                                                  id,
-                                                  locationOptions,
-                                                  batchOptions);
+    if (NULL != gData.flpInterface) {
+        gData.flpInterface->updateBatchingOptions(this, id, batchOptions);
     } else {
         LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ",
                  __func__, __LINE__, this);
diff --git a/sdm845/location/LocationAPI.h b/sdm845/location/LocationAPI.h
index de18031..25e8914 100644
--- a/sdm845/location/LocationAPI.h
+++ b/sdm845/location/LocationAPI.h
@@ -453,18 +453,60 @@
     LocationTechnologyMask techMask;
 } Location;
 
-typedef struct  {
+struct LocationOptions {
     size_t size;          // set to sizeof(LocationOptions)
     uint32_t minInterval; // in milliseconds
     uint32_t minDistance; // in meters. if minDistance > 0, gnssSvCallback/gnssNmeaCallback/
                           // gnssMeasurementsCallback may not be called
     GnssSuplMode mode;    // Standalone/MS-Based/MS-Assisted
-} LocationOptions;
 
-typedef struct {
-    size_t size;
+    inline LocationOptions() :
+            size(0), minInterval(0), minDistance(0), mode(GNSS_SUPL_MODE_STANDALONE) {}
+};
+
+typedef enum {
+    GNSS_POWER_MODE_INVALID = 0,
+    GNSS_POWER_MODE_M1,  /* Improved Accuracy Mode */
+    GNSS_POWER_MODE_M2,  /* Normal Mode */
+    GNSS_POWER_MODE_M3,  /* Background Mode */
+    GNSS_POWER_MODE_M4,  /* Background Mode */
+    GNSS_POWER_MODE_M5   /* Background Mode */
+} GnssPowerMode;
+
+struct TrackingOptions : LocationOptions {
+    GnssPowerMode powerMode; /* Power Mode to be used for time based tracking
+                                sessions */
+    uint32_t tbm;  /* Time interval between measurements.
+                      Applicable to background power modes */
+
+    inline TrackingOptions() :
+            LocationOptions(), powerMode(GNSS_POWER_MODE_INVALID), tbm(0) {}
+    inline TrackingOptions(size_t s, GnssPowerMode m, uint32_t t) :
+            LocationOptions(), powerMode(m), tbm(t) { LocationOptions::size = s; }
+    inline TrackingOptions(const LocationOptions& options) :
+            LocationOptions(options), powerMode(GNSS_POWER_MODE_INVALID), tbm(0) {}
+    inline void setLocationOptions(const LocationOptions& options) {
+        minInterval = options.minInterval;
+        minDistance = options.minDistance;
+        mode = options.mode;
+    }
+};
+
+struct BatchingOptions : LocationOptions {
     BatchingMode batchingMode;
-} BatchingOptions;
+
+    inline BatchingOptions() :
+            LocationOptions(), batchingMode(BATCHING_MODE_ROUTINE) {}
+    inline BatchingOptions(size_t s, BatchingMode m) :
+            LocationOptions(), batchingMode(m) { LocationOptions::size = s; }
+    inline BatchingOptions(const LocationOptions& options) :
+            LocationOptions(options), batchingMode(BATCHING_MODE_ROUTINE) {}
+    inline void setLocationOptions(const LocationOptions& options) {
+        minInterval = options.minInterval;
+        minDistance = options.minDistance;
+        mode = options.mode;
+    }
+};
 
 typedef struct {
     size_t size;
@@ -861,8 +903,8 @@
                 LOCATION_ERROR_SUCCESS if session was successfully started
                 LOCATION_ERROR_ALREADY_STARTED if a startTracking session is already in progress
                 LOCATION_ERROR_CALLBACK_MISSING if no trackingCallback was passed in createInstance
-                LOCATION_ERROR_INVALID_PARAMETER if LocationOptions parameter is invalid */
-    uint32_t startTracking(LocationOptions&); // returns session id
+                LOCATION_ERROR_INVALID_PARAMETER if TrackingOptions parameter is invalid */
+    uint32_t startTracking(TrackingOptions&); // returns session id
 
     /* stopTracking stops a tracking session associated with id parameter.
         responseCallback returns:
@@ -870,12 +912,12 @@
                 LOCATION_ERROR_ID_UNKNOWN if id is not associated with a tracking session */
     void stopTracking(uint32_t id);
 
-    /* updateTrackingOptions changes the LocationOptions of a tracking session associated with id
+    /* updateTrackingOptions changes the TrackingOptions of a tracking session associated with id
         responseCallback returns:
                 LOCATION_ERROR_SUCCESS if successful
-                LOCATION_ERROR_INVALID_PARAMETER if LocationOptions parameters are invalid
+                LOCATION_ERROR_INVALID_PARAMETER if TrackingOptions parameters are invalid
                 LOCATION_ERROR_ID_UNKNOWN if id is not associated with a tracking session */
-    void updateTrackingOptions(uint32_t id, LocationOptions&);
+    void updateTrackingOptions(uint32_t id, TrackingOptions&);
 
     /* ================================== BATCHING ================================== */
 
@@ -894,7 +936,7 @@
                 LOCATION_ERROR_CALLBACK_MISSING if no batchingCallback was passed in createInstance
                 LOCATION_ERROR_INVALID_PARAMETER if a parameter is invalid
                 LOCATION_ERROR_NOT_SUPPORTED if batching is not supported */
-    uint32_t startBatching(LocationOptions&, BatchingOptions&); // returns session id
+    uint32_t startBatching(BatchingOptions&); // returns session id
 
     /* stopBatching stops a batching session associated with id parameter.
         responseCallback returns:
@@ -902,12 +944,12 @@
                 LOCATION_ERROR_ID_UNKNOWN if id is not associated with batching session */
     void stopBatching(uint32_t id);
 
-    /* updateBatchingOptions changes the LocationOptions of a batching session associated with id
+    /* updateBatchingOptions changes the BatchingOptions of a batching session associated with id
         responseCallback returns:
                 LOCATION_ERROR_SUCCESS if successful
-                LOCATION_ERROR_INVALID_PARAMETER if LocationOptions parameters are invalid
+                LOCATION_ERROR_INVALID_PARAMETER if BatchingOptions parameters are invalid
                 LOCATION_ERROR_ID_UNKNOWN if id is not associated with a batching session */
-    void updateBatchingOptions(uint32_t id, LocationOptions&, BatchingOptions&);
+    void updateBatchingOptions(uint32_t id, BatchingOptions&);
 
     /* getBatchedLocations gets a number of locations that are currently stored/batched
        on the low power processor, delivered by the batchingCallback passed in createInstance.
diff --git a/sdm845/location/LocationAPIClientBase.cpp b/sdm845/location/LocationAPIClientBase.cpp
index 65a0984..67e559b 100644
--- a/sdm845/location/LocationAPIClientBase.cpp
+++ b/sdm845/location/LocationAPIClientBase.cpp
@@ -330,7 +330,7 @@
     pthread_mutex_destroy(&mMutex);
 }
 
-uint32_t LocationAPIClientBase::locAPIStartTracking(LocationOptions& options)
+uint32_t LocationAPIClientBase::locAPIStartTracking(TrackingOptions& options)
 {
     uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
     pthread_mutex_lock(&mMutex);
@@ -372,7 +372,7 @@
     pthread_mutex_unlock(&mMutex);
 }
 
-void LocationAPIClientBase::locAPIUpdateTrackingOptions(LocationOptions& options)
+void LocationAPIClientBase::locAPIUpdateTrackingOptions(TrackingOptions& options)
 {
     pthread_mutex_lock(&mMutex);
     if (mLocationAPI) {
@@ -404,9 +404,8 @@
     return mBatchSize;
 }
 
-
-uint32_t LocationAPIClientBase::locAPIStartSession(uint32_t id, uint32_t sessionMode,
-        LocationOptions& locationOptions)
+uint32_t LocationAPIClientBase::locAPIStartSession(
+        uint32_t id, uint32_t sessionMode, TrackingOptions&& options)
 {
     uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
     pthread_mutex_lock(&mMutex);
@@ -420,7 +419,7 @@
             uint32_t batchingSession = 0;
 
             if (sessionMode == SESSION_MODE_ON_FIX) {
-                trackingSession = mLocationAPI->startTracking(locationOptions);
+                trackingSession = mLocationAPI->startTracking(options);
                 LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, trackingSession);
                 mRequestQueues[REQUEST_SESSION].push(new StartTrackingRequest(*this));
             } else {
@@ -439,7 +438,12 @@
                     break;
                 }
 
-                batchingSession = mLocationAPI->startBatching(locationOptions, batchOptions);
+                // Populate location option values
+                batchOptions.minDistance = options.minDistance;
+                batchOptions.minInterval = options.minInterval;
+                batchOptions.mode = options.mode;
+
+                batchingSession = mLocationAPI->startBatching(batchOptions);
                 LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, batchingSession);
                 mRequestQueues[REQUEST_SESSION].setSession(batchingSession);
                 mRequestQueues[REQUEST_SESSION].push(new StartBatchingRequest(*this));
@@ -496,8 +500,8 @@
     return retVal;
 }
 
-uint32_t LocationAPIClientBase::locAPIUpdateSessionOptions(uint32_t id, uint32_t sessionMode,
-        LocationOptions& options)
+uint32_t LocationAPIClientBase::locAPIUpdateSessionOptions(
+        uint32_t id, uint32_t sessionMode, TrackingOptions&& options)
 {
     uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
     pthread_mutex_lock(&mMutex);
@@ -554,13 +558,18 @@
                     mLocationAPI->stopTracking(trackingSession);
                     trackingSession = 0;
 
+                    // Populate location option values
+                    batchOptions.minDistance = options.minDistance;
+                    batchOptions.minInterval = options.minInterval;
+                    batchOptions.mode = options.mode;
+
                     // start batching
-                    batchingSession = mLocationAPI->startBatching(options, batchOptions);
+                    batchingSession = mLocationAPI->startBatching(batchOptions);
                     LOC_LOGI("%s:%d] start new session: %d",
                             __FUNCTION__, __LINE__, batchingSession);
                     mRequestQueues[REQUEST_SESSION].setSession(batchingSession);
                 } else {
-                    mLocationAPI->updateBatchingOptions(batchingSession, options, batchOptions);
+                    mLocationAPI->updateBatchingOptions(batchingSession, batchOptions);
                 }
 
             }
diff --git a/sdm845/location/LocationAPIClientBase.h b/sdm845/location/LocationAPIClientBase.h
index 4d48932..bcc39f3 100644
--- a/sdm845/location/LocationAPIClientBase.h
+++ b/sdm845/location/LocationAPIClientBase.h
@@ -209,16 +209,16 @@
     LocationAPIRequest* getRequestBySession(uint32_t session);
 
     // LocationAPI
-    uint32_t locAPIStartTracking(LocationOptions& options);
+    uint32_t locAPIStartTracking(TrackingOptions& trackingOptions);
     void locAPIStopTracking();
-    void locAPIUpdateTrackingOptions(LocationOptions& options);
+    void locAPIUpdateTrackingOptions(TrackingOptions& trackingOptions);
 
     int32_t locAPIGetBatchSize();
-    uint32_t locAPIStartSession(uint32_t id, uint32_t sessionMode,
-            LocationOptions& options);
+    uint32_t locAPIStartSession(
+            uint32_t id, uint32_t sessionMode, TrackingOptions&& trackingOptions);
     uint32_t locAPIStopSession(uint32_t id);
-    uint32_t locAPIUpdateSessionOptions(uint32_t id, uint32_t sessionMode,
-            LocationOptions& options);
+    uint32_t locAPIUpdateSessionOptions(
+            uint32_t id, uint32_t sessionMode, TrackingOptions&& trackingOptions);
     uint32_t locAPIGetBatchedLocations(uint32_t id, size_t count);
 
     uint32_t locAPIAddGeofences(size_t count, uint32_t* ids,
diff --git a/sdm845/location/location_interface.h b/sdm845/location/location_interface.h
index f4f904d..a460bb6 100644
--- a/sdm845/location/location_interface.h
+++ b/sdm845/location/location_interface.h
@@ -39,8 +39,8 @@
     void (*addClient)(LocationAPI* client, const LocationCallbacks& callbacks);
     void (*removeClient)(LocationAPI* client);
     void (*requestCapabilities)(LocationAPI* client);
-    uint32_t (*startTracking)(LocationAPI* client, LocationOptions& options);
-    void (*updateTrackingOptions)(LocationAPI* client, uint32_t id, LocationOptions& options);
+    uint32_t (*startTracking)(LocationAPI* client, TrackingOptions&);
+    void (*updateTrackingOptions)(LocationAPI* client, uint32_t id, TrackingOptions&);
     void (*stopTracking)(LocationAPI* client, uint32_t id);
     void (*gnssNiResponse)(LocationAPI* client, uint32_t id, GnssNiResponse response);
     void (*setControlCallbacks)(LocationControlCallbacks& controlCallbacks);
@@ -70,13 +70,12 @@
     void (*addClient)(LocationAPI* client, const LocationCallbacks& callbacks);
     void (*removeClient)(LocationAPI* client);
     void (*requestCapabilities)(LocationAPI* client);
-    uint32_t (*startTracking)(LocationAPI* client, LocationOptions& options);
-    void (*updateTrackingOptions)(LocationAPI* client, uint32_t id, LocationOptions& options);
+    uint32_t (*startTracking)(LocationAPI* client, TrackingOptions&);
+    void (*updateTrackingOptions)(LocationAPI* client, uint32_t id, TrackingOptions&);
     void (*stopTracking)(LocationAPI* client, uint32_t id);
-    uint32_t (*startBatching)(LocationAPI* client, LocationOptions&, BatchingOptions&);
+    uint32_t (*startBatching)(LocationAPI* client, BatchingOptions&);
     void (*stopBatching)(LocationAPI* client, uint32_t id);
-    void (*updateBatchingOptions)(LocationAPI* client, uint32_t id, LocationOptions&,
-            BatchingOptions&);
+    void (*updateBatchingOptions)(LocationAPI* client, uint32_t id, BatchingOptions&);
     void (*getBatchedLocations)(LocationAPI* client, uint32_t id, size_t count);
     void (*getPowerStateChanges)(void* powerStateCb);
 };
diff --git a/sdm845/utils/gps_extended.h b/sdm845/utils/gps_extended.h
index dc6ad1e..db046d6 100644
--- a/sdm845/utils/gps_extended.h
+++ b/sdm845/utils/gps_extended.h
@@ -55,14 +55,18 @@
     bool share_position;
     char credentials[14];
     char provider[8];
+    GnssPowerMode powerMode;
+    uint32_t timeBetweenMeasurements;
     LocPosMode(LocPositionMode m, LocGpsPositionRecurrence recr,
                uint32_t gap, uint32_t accu, uint32_t time,
-               bool sp, const char* cred, const char* prov) :
+               bool sp, const char* cred, const char* prov,
+               GnssPowerMode pMode, uint32_t tbm) :
         mode(m), recurrence(recr),
         min_interval(gap < GPS_MIN_POSSIBLE_FIX_INTERVAL_MS ?
                      GPS_MIN_POSSIBLE_FIX_INTERVAL_MS : gap),
         preferred_accuracy(accu), preferred_time(time),
-        share_position(sp) {
+        share_position(sp), powerMode(pMode),
+        timeBetweenMeasurements(tbm) {
         memset(credentials, 0, sizeof(credentials));
         memset(provider, 0, sizeof(provider));
         if (NULL != cred) {
@@ -78,7 +82,8 @@
         recurrence(LOC_GPS_POSITION_RECURRENCE_PERIODIC),
         min_interval(GPS_DEFAULT_FIX_INTERVAL_MS),
         preferred_accuracy(50), preferred_time(120000),
-        share_position(true) {
+        share_position(true), powerMode(GNSS_POWER_MODE_INVALID),
+        timeBetweenMeasurements(GPS_DEFAULT_FIX_INTERVAL_MS) {
         memset(credentials, 0, sizeof(credentials));
         memset(provider, 0, sizeof(provider));
     }
@@ -90,6 +95,8 @@
             anotherMode.min_interval == min_interval &&
             anotherMode.preferred_accuracy == preferred_accuracy &&
             anotherMode.preferred_time == preferred_time &&
+            anotherMode.powerMode == powerMode &&
+            anotherMode.timeBetweenMeasurements == timeBetweenMeasurements &&
             !strncmp(anotherMode.credentials, credentials, sizeof(credentials)-1) &&
             !strncmp(anotherMode.provider, provider, sizeof(provider)-1);
     }
diff --git a/sdm845/utils/gps_extended_c.h b/sdm845/utils/gps_extended_c.h
index 892bb09..ae4964e 100644
--- a/sdm845/utils/gps_extended_c.h
+++ b/sdm845/utils/gps_extended_c.h
@@ -114,11 +114,13 @@
 
 typedef enum {
     LOC_SUPPORTED_FEATURE_ODCPI_2_V02 = 0, /**<  Support ODCPI version 2 feature  */
-    LOC_SUPPORTED_FEATURE_WIFI_AP_DATA_INJECT_2_V02, /**<  Support Wifi AP data inject version 2 feature  */
-    LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02, /**< Support debug NMEA feature */
-    LOC_SUPPORTED_FEATURE_GNSS_ONLY_POSITION_REPORT_V02, /**<  Support the GNSS only position report feature  */
-    LOC_SUPPORTED_FEATURE_FDCL_V02, /**<  Support the FDCL feature  */
-    LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02, /**<  Support the GNSS constellation enablement feature  */
+    LOC_SUPPORTED_FEATURE_WIFI_AP_DATA_INJECT_2_V02 = 1, /**<  Support Wifi AP data inject version 2 feature  */
+    LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02 = 2, /**< Support debug NMEA feature */
+    LOC_SUPPORTED_FEATURE_GNSS_ONLY_POSITION_REPORT_V02 = 3, /**< Support the GNSS only position report feature */
+    LOC_SUPPORTED_FEATURE_FDCL_V02 = 4, /**< Support the FDCL feature */
+    LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02 = 5, /**<  Support the GNSS constellation enablement feature  */
+    LOC_SUPPORTED_FEATURE_AGPM_V02 = 6, /**<  Support the advanced GNSS power management feature  */
+    LOC_SUPPORTED_FEATURE_PASSIVE_LISTENER_V02 = 7, /**<  Support the passive listener feature  */
 } loc_supported_feature_enum;
 
 typedef struct {