From 48b4774ece81ed5d61af7de46961483cf2da2278 Mon Sep 17 00:00:00 2001 From: Dante Russo Date: Thu, 19 Jul 2018 10:43:21 -0700 Subject: [PATCH] Add a timer for better handling of ODCPI/DBH Prevent more than one ODCPI request into frameworks each 30 seconds. Request ODCPI every 30 seconds while modem is actively requesting it Allow location injections for ODCPI even outside ODCPI session. Emergency ODCPI requests override normal ODCPI requests Change-Id: Ie2de6a5d42e749fce2e45cd672fc1d667b3f3347 CRs-fixed: 2246658 --- gnss/GnssAdapter.cpp | 105 ++++++++++++++++++++++++++++++++----------- gnss/GnssAdapter.h | 37 +++++++++++++-- 2 files changed, 113 insertions(+), 29 deletions(-) diff --git a/gnss/GnssAdapter.cpp b/gnss/GnssAdapter.cpp index 43b7e598..87565d73 100644 --- a/gnss/GnssAdapter.cpp +++ b/gnss/GnssAdapter.cpp @@ -81,7 +81,8 @@ GnssAdapter::GnssAdapter() : mAgpsCbInfo(), mOdcpiRequestCb(nullptr), mOdcpiRequestActive(false), - mOdcpiInjectedPositionCount(0), + mOdcpiTimer(this), + mOdcpiRequest(), mSystemStatus(SystemStatus::getInstance(mMsgTask)), mServerUrl(":"), mXtraObserver(mSystemStatus->getOsObserver(), mMsgTask), @@ -1943,6 +1944,9 @@ GnssAdapter::restartSessions() { LOC_LOGD("%s]: ", __func__); + // odcpi session is no longer active after restart + mOdcpiRequestActive = false; + if (mTrackingSessions.empty()) { return; } @@ -3297,9 +3301,6 @@ GnssAdapter::reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial) bool GnssAdapter::requestOdcpiEvent(OdcpiRequestInfo& request) { - LOC_LOGd("ODCPI request: type %d, tbf %d, isEmergency %d", request.type, - request.tbfMillis, request.isEmergencyMode); - struct MsgRequestOdcpi : public LocMsg { GnssAdapter& mAdapter; OdcpiRequestInfo mOdcpiRequest; @@ -3319,15 +3320,45 @@ GnssAdapter::requestOdcpiEvent(OdcpiRequestInfo& request) void GnssAdapter::requestOdcpi(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"); } } @@ -3377,26 +3408,48 @@ void GnssAdapter::injectOdcpiCommand(const Location& location) void GnssAdapter::injectOdcpi(const Location& location) { - if (LOCATION_HAS_LAT_LONG_BIT & location.flags) { - if ((uptimeMillis() <= mBlockCPIInfo.blockedTillTsMs) && - (fabs(location.latitude-mBlockCPIInfo.latitude) <= - mBlockCPIInfo.latLonDiffThreshold) && - (fabs(location.longitude-mBlockCPIInfo.longitude) <= - mBlockCPIInfo.latLonDiffThreshold)) { + LOC_LOGd("ODCPI Injection: requestActive: %d timerActive: %d" + "lat %.7f long %.7f", + mOdcpiRequestActive, mOdcpiTimer.isActive(), + location.latitude, location.longitude); - LOC_LOGD("%s]: positon injeciton blocked: lat: %f, lon: %f, accuracy: %f", - __func__, location.latitude, location.longitude, location.accuracy); - } else { - mLocApi->injectPosition(location, true); - if (mOdcpiRequestActive) { - mOdcpiInjectedPositionCount++; - if (mOdcpiInjectedPositionCount >= - ODCPI_INJECTED_POSITION_COUNT_PER_REQUEST) { - mOdcpiRequestActive = false; - mOdcpiInjectedPositionCount = 0; - } - } + mLocApi->injectPosition(location, true); +} + +// 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 { + mOdcpiTimer.stop(); } } diff --git a/gnss/GnssAdapter.h b/gnss/GnssAdapter.h index 6ed96552..7ca605af 100644 --- a/gnss/GnssAdapter.h +++ b/gnss/GnssAdapter.h @@ -44,10 +44,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 30000 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 */ @@ -130,7 +159,9 @@ class GnssAdapter : public LocAdapterBase { /* ==== ODCPI ========================================================================== */ OdcpiRequestCallback mOdcpiRequestCb; bool mOdcpiRequestActive; - uint32_t mOdcpiInjectedPositionCount; + OdcpiTimer mOdcpiTimer; + OdcpiRequestInfo mOdcpiRequest; + void odcpiTimerExpire(); /* === SystemStatus ===================================================================== */ SystemStatus* mSystemStatus; @@ -268,7 +299,6 @@ public: /* ======== COMMANDS ====(Called from Client Thread)==================================== */ void initOdcpiCommand(const OdcpiRequestCallback& callback); void injectOdcpiCommand(const Location& location); - /* ======== RESPONSES ================================================================== */ void reportResponse(LocationError err, uint32_t sessionId); void reportResponse(size_t count, LocationError* errs, uint32_t* ids); @@ -281,6 +311,7 @@ public: virtual bool isInSession() { return !mTrackingSessions.empty(); } void initDefaultAgps(); bool initEngHubProxy(); + void odcpiTimerExpireEvent(); /* ==== REPORTS ======================================================================== */ /* ======== EVENTS ====(Called from QMI/EngineHub Thread)===================================== */