Batching API batch retrieval changes

Allows one last batch of fixes, if available, be retrieved by HIDL
client after stop() is called. Also, if flush() is called, service
end will always report something, empty if no more fixes in the
batch.

Bug: 180602917
Test: atest CtsLocationFineTestCases:android.location.cts.fine.LocationManagerFineTest#testRequestFlush_Gnss
CRs-fixed: 2870223
Change-Id: Ib6e47a601f881b79ae459b163da5bbf04bf24f52
diff --git a/sdm845/android/location_api/BatchingAPIClient.cpp b/sdm845/android/location_api/BatchingAPIClient.cpp
index ccb78b9..8ecfa55 100644
--- a/sdm845/android/location_api/BatchingAPIClient.cpp
+++ b/sdm845/android/location_api/BatchingAPIClient.cpp
@@ -32,6 +32,7 @@
 
 #include <log_util.h>
 #include <loc_cfg.h>
+#include <thread>
 
 #include "LocationUtil.h"
 #include "BatchingAPIClient.h"
@@ -90,12 +91,16 @@
 
 int BatchingAPIClient::getBatchSize()
 {
-    LOC_LOGD("%s]: ()", __FUNCTION__);
-    return locAPIGetBatchSize();
+    int batchSize = locAPIGetBatchSize();
+    LOC_LOGd("batchSize: %d", batchSize);
+    return batchSize;
 }
 
 int BatchingAPIClient::startSession(const IGnssBatching::Options& opts)
 {
+    mMutex.lock();
+    mState = STARTED;
+    mMutex.unlock();
     LOC_LOGD("%s]: (%lld %d)", __FUNCTION__,
             static_cast<long long>(opts.periodNanos), static_cast<uint8_t>(opts.flags));
     int retVal = -1;
@@ -131,8 +136,12 @@
 
 int BatchingAPIClient::stopSession()
 {
+    mMutex.lock();
+    mState = STOPPING;
+    mMutex.unlock();
     LOC_LOGD("%s]: ", __FUNCTION__);
     int retVal = -1;
+    locAPIGetBatchedLocations(mDefaultId, SIZE_MAX);
     if (locAPIStopSession(mDefaultId) == LOCATION_ERROR_SUCCESS) {
         retVal = 1;
     }
@@ -148,7 +157,13 @@
 void BatchingAPIClient::flushBatchedLocations()
 {
     LOC_LOGD("%s]: ()", __FUNCTION__);
-    locAPIGetBatchedLocations(mDefaultId, SIZE_MAX);
+    uint32_t retVal = locAPIGetBatchedLocations(mDefaultId, SIZE_MAX);
+    // when flush a stopped session or one doesn't exist, just report an empty batch.
+    if (LOCATION_ERROR_ID_UNKNOWN == retVal) {
+        BatchingOptions opt = {};
+        ::std::thread thd(&BatchingAPIClient::onBatchingCb, this, 0, nullptr, opt);
+        thd.detach();
+    }
 }
 
 void BatchingAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)
@@ -159,19 +174,50 @@
 
 void BatchingAPIClient::onBatchingCb(size_t count, Location* location, BatchingOptions /*batchOptions*/)
 {
-    LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, count);
-    if (mGnssBatchingCbIface != nullptr && count > 0) {
-        hidl_vec<GnssLocation> locationVec;
-        locationVec.resize(count);
-        for (size_t i = 0; i < count; i++) {
-            convertGnssLocation(location[i], locationVec[i]);
-        }
-        auto r = mGnssBatchingCbIface->gnssLocationBatchCb(locationVec);
-        if (!r.isOk()) {
-            LOC_LOGE("%s] Error from gnssLocationBatchCb description=%s",
-                __func__, r.description().c_str());
-        }
+    bool processReport = false;
+    LOC_LOGd("(count: %zu)", count);
+    mMutex.lock();
+    // back to back stop() and flush() could bring twice onBatchingCb(). Each one might come first.
+    // Combine them both (the first goes to cache, the second in location*) before report to FW
+    switch (mState) {
+        case STOPPING:
+            mState = STOPPED;
+            for (size_t i = 0; i < count; i++) {
+                mBatchedLocationInCache.push_back(location[i]);
+            }
+            break;
+        case STARTED:
+        case STOPPED: // flush() always trigger report, even on a stopped session
+            processReport = true;
+            break;
+        default:
+            break;
     }
+    // report location batch when in STARTED state or flush(), combined with cache in last stop()
+    if (processReport) {
+        auto gnssBatchingCbIface(mGnssBatchingCbIface);
+        size_t batchCacheCnt = mBatchedLocationInCache.size();
+        LOC_LOGd("(batchCacheCnt: %zu)", batchCacheCnt);
+        if (gnssBatchingCbIface != nullptr) {
+            hidl_vec<V1_0::GnssLocation> locationVec;
+            if (count+batchCacheCnt > 0) {
+                locationVec.resize(count+batchCacheCnt);
+                for (size_t i = 0; i < batchCacheCnt; ++i) {
+                    convertGnssLocation(mBatchedLocationInCache[i], locationVec[i]);
+                }
+                for (size_t i = 0; i < count; i++) {
+                    convertGnssLocation(location[i], locationVec[i+batchCacheCnt]);
+                }
+            }
+            auto r = gnssBatchingCbIface->gnssLocationBatchCb(locationVec);
+            if (!r.isOk()) {
+                LOC_LOGE("%s] Error from gnssLocationBatchCb 1.0 description=%s",
+                        __func__, r.description().c_str());
+            }
+        }
+        mBatchedLocationInCache.clear();
+    }
+    mMutex.unlock();
 }
 
 static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out,
diff --git a/sdm845/android/location_api/BatchingAPIClient.h b/sdm845/android/location_api/BatchingAPIClient.h
index 64d47a0..93ccd16 100644
--- a/sdm845/android/location_api/BatchingAPIClient.h
+++ b/sdm845/android/location_api/BatchingAPIClient.h
@@ -33,7 +33,7 @@
 #include <android/hardware/gnss/1.0/IGnssBatching.h>
 #include <android/hardware/gnss/1.0/IGnssBatchingCallback.h>
 #include <pthread.h>
-
+#include <mutex>
 #include <LocationAPIClientBase.h>
 
 namespace android {
@@ -42,6 +42,8 @@
 namespace V1_1 {
 namespace implementation {
 
+enum BATCHING_STATE { STARTED, STOPPING, STOPPED };
+
 class BatchingAPIClient : public LocationAPIClientBase
 {
 public:
@@ -62,8 +64,12 @@
 
 private:
     sp<V1_0::IGnssBatchingCallback> mGnssBatchingCbIface;
+    std::mutex mMutex;
     uint32_t mDefaultId;
     LocationCapabilitiesMask mLocationCapabilitiesMask;
+    volatile BATCHING_STATE mState = STOPPED;
+
+    std::vector<Location> mBatchedLocationInCache;
 };
 
 }  // namespace implementation
diff --git a/sdm845/location/LocationAPIClientBase.cpp b/sdm845/location/LocationAPIClientBase.cpp
index 67e559b..f181798 100644
--- a/sdm845/location/LocationAPIClientBase.cpp
+++ b/sdm845/location/LocationAPIClientBase.cpp
@@ -613,7 +613,7 @@
             }
         }  else {
             retVal = LOCATION_ERROR_ID_UNKNOWN;
-            LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, id);
+            LOC_LOGd("unknown session id: %d, might flush() a stopped session",  id);
         }
     }
     pthread_mutex_unlock(&mMutex);