[automerger skipped] Merge pi-platform-release to stage-aosp-master - DO NOT MERGE
am: ae1c7066e9  -s ours

Change-Id: Ic1411e8c56ee9c867d278b212e2c6dfe4a283472
diff --git a/sdm845/android/location_api/GnssAPIClient.cpp b/sdm845/android/location_api/GnssAPIClient.cpp
index 076880e..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);
 }
 
diff --git a/sdm845/core/LocApiBase.cpp b/sdm845/core/LocApiBase.cpp
index 5227d06..c317d59 100644
--- a/sdm845/core/LocApiBase.cpp
+++ b/sdm845/core/LocApiBase.cpp
@@ -167,6 +167,35 @@
     return inSession;
 }
 
+bool LocApiBase::needReport(const UlpLocation& ulpLocation,
+    enum loc_sess_status status,
+    LocPosTechMask techMask)
+{
+    bool reported = false;
+
+    if (LOC_SESS_SUCCESS == status) {
+        // this is a final fix
+        LocPosTechMask mask =
+            LOC_POS_TECH_MASK_SATELLITE | LOC_POS_TECH_MASK_SENSORS | LOC_POS_TECH_MASK_HYBRID;
+        // it is a Satellite fix or a sensor fix
+        reported = (mask & techMask);
+    }
+    else if (LOC_SESS_INTERMEDIATE == status &&
+        LOC_SESS_INTERMEDIATE == ContextBase::mGps_conf.INTERMEDIATE_POS) {
+        // this is a intermediate fix and we accept intermediate
+
+        // it is NOT the case that
+        // there is inaccuracy; and
+        // we care about inaccuracy; and
+        // the inaccuracy exceeds our tolerance
+        reported = !((ulpLocation.gpsLocation.flags & LOC_GPS_LOCATION_HAS_ACCURACY) &&
+            (ContextBase::mGps_conf.ACCURACY_THRES != 0) &&
+            (ulpLocation.gpsLocation.accuracy > ContextBase::mGps_conf.ACCURACY_THRES));
+    }
+
+    return reported;
+}
+
 void LocApiBase::addAdapter(LocAdapterBase* adapter)
 {
     for (int i = 0; i < MAX_ADAPTERS && mLocAdapters[i] != adapter; i++) {
diff --git a/sdm845/core/LocApiBase.h b/sdm845/core/LocApiBase.h
index d230ef2..aec1846 100644
--- a/sdm845/core/LocApiBase.h
+++ b/sdm845/core/LocApiBase.h
@@ -104,6 +104,9 @@
     inline void sendMsg(const LocMsg* msg) const {
         mMsgTask->sendMsg(msg);
     }
+    static bool needReport(const UlpLocation& ulpLocation,
+        enum loc_sess_status status,
+        LocPosTechMask techMask);
     void addAdapter(LocAdapterBase* adapter);
     void removeAdapter(LocAdapterBase* adapter);
 
diff --git a/sdm845/gnss/GnssAdapter.cpp b/sdm845/gnss/GnssAdapter.cpp
index ff9138d..9cc4edf 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)
@@ -1765,6 +1766,9 @@
 {
     LOC_LOGD("%s]: ", __func__);
 
+    // odcpi session is no longer active after restart
+    mOdcpiRequestActive = false;
+
     if (mTrackingSessions.empty()) {
         return;
     }
@@ -2716,25 +2720,8 @@
                         enum loc_sess_status status,
                         LocPosTechMask techMask) {
     bool reported = false;
-    if (LOC_SESS_SUCCESS == status) {
-        // this is a final fix
-        LocPosTechMask mask =
-                LOC_POS_TECH_MASK_SATELLITE | LOC_POS_TECH_MASK_SENSORS | LOC_POS_TECH_MASK_HYBRID;
-        // it is a Satellite fix or a sensor fix
-        reported = (mask & techMask);
-    } else if (LOC_SESS_INTERMEDIATE == status &&
-            LOC_SESS_INTERMEDIATE == ContextBase::mGps_conf.INTERMEDIATE_POS) {
-        // this is a intermediate fix and we accepte intermediate
 
-        // it is NOT the case that
-        // there is inaccuracy; and
-        // we care about inaccuracy; and
-        // the inaccuracy exceeds our tolerance
-        reported = !((ulpLocation.gpsLocation.flags & LOC_GPS_LOCATION_HAS_ACCURACY) &&
-                (ContextBase::mGps_conf.ACCURACY_THRES != 0) &&
-                (ulpLocation.gpsLocation.accuracy > ContextBase::mGps_conf.ACCURACY_THRES));
-    }
-
+    reported = LocApiBase::needReport(ulpLocation, status, techMask);
     return reported;
 }
 
@@ -2745,11 +2732,13 @@
                             LocPosTechMask techMask)
 {
     bool reported = needReport(ulpLocation, status, techMask);
+    mGnssSvIdUsedInPosAvail = false;
     if (reported) {
         if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA) {
             mGnssSvIdUsedInPosAvail = true;
             mGnssSvIdUsedInPosition = locationExtended.gnss_sv_used_ids;
         }
+
         for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
             if (nullptr != it->second.trackingCb) {
                 Location location = {};
@@ -3174,9 +3163,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;
@@ -3196,15 +3182,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");
     }
 }
 
@@ -3254,23 +3270,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();
     }
 }
 
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);