Add VTS tests for measurementInterval, stopSvStatus, and stopNmea

Bug: 206670536
Test: atest VtsHalGnssTargetTest

Change-Id: Id597c772fbe63789cb394b2aa14faeb755196f64
diff --git a/gnss/aidl/default/GnssMeasurementInterface.cpp b/gnss/aidl/default/GnssMeasurementInterface.cpp
index 2c7241b..606de07 100644
--- a/gnss/aidl/default/GnssMeasurementInterface.cpp
+++ b/gnss/aidl/default/GnssMeasurementInterface.cpp
@@ -33,10 +33,11 @@
 
 std::shared_ptr<IGnssMeasurementCallback> GnssMeasurementInterface::sCallback = nullptr;
 
-GnssMeasurementInterface::GnssMeasurementInterface() : mMinIntervalMillis(1000) {}
+GnssMeasurementInterface::GnssMeasurementInterface()
+    : mIntervalMs(1000), mLocationIntervalMs(1000), mFutures(std::vector<std::future<void>>()) {}
 
 GnssMeasurementInterface::~GnssMeasurementInterface() {
-    stop();
+    waitForStoppingThreads();
 }
 
 ndk::ScopedAStatus GnssMeasurementInterface::setCallback(
@@ -44,8 +45,10 @@
         const bool enableCorrVecOutputs) {
     ALOGD("setCallback: enableFullTracking: %d enableCorrVecOutputs: %d", (int)enableFullTracking,
           (int)enableCorrVecOutputs);
-    std::unique_lock<std::mutex> lock(mMutex);
-    sCallback = callback;
+    {
+        std::unique_lock<std::mutex> lock(mMutex);
+        sCallback = callback;
+    }
 
     if (mIsActive) {
         ALOGW("GnssMeasurement callback already set. Resetting the callback...");
@@ -60,14 +63,16 @@
         const std::shared_ptr<IGnssMeasurementCallback>& callback, const Options& options) {
     ALOGD("setCallbackWithOptions: fullTracking:%d, corrVec:%d, intervalMs:%d",
           (int)options.enableFullTracking, (int)options.enableCorrVecOutputs, options.intervalMs);
-    std::unique_lock<std::mutex> lock(mMutex);
-    sCallback = callback;
+    {
+        std::unique_lock<std::mutex> lock(mMutex);
+        sCallback = callback;
+    }
 
     if (mIsActive) {
         ALOGW("GnssMeasurement callback already set. Resetting the callback...");
         stop();
     }
-    mMinIntervalMillis = options.intervalMs;
+    mIntervalMs = std::max(options.intervalMs, 1000);
     start(options.enableCorrVecOutputs);
 
     return ndk::ScopedAStatus::ok();
@@ -75,18 +80,35 @@
 
 ndk::ScopedAStatus GnssMeasurementInterface::close() {
     ALOGD("close");
-    stop();
-    std::unique_lock<std::mutex> lock(mMutex);
-    sCallback = nullptr;
-    mMinIntervalMillis = 1000;
+    if (mIsActive) {
+        stop();
+    }
+    {
+        std::unique_lock<std::mutex> lock(mMutex);
+        sCallback = nullptr;
+    }
+    mIntervalMs = 1000;
     return ndk::ScopedAStatus::ok();
 }
 
 void GnssMeasurementInterface::start(const bool enableCorrVecOutputs) {
     ALOGD("start");
+
+    if (mIsActive) {
+        ALOGD("restarting since measurement has started");
+        stop();
+    }
+    // Wait for stopping previous thread.
+    waitForStoppingThreads();
+
     mIsActive = true;
+    mThreadBlocker.reset();
     mThread = std::thread([this, enableCorrVecOutputs]() {
-        while (mIsActive == true) {
+        int intervalMs;
+        do {
+            if (!mIsActive) {
+                break;
+            }
             std::string rawMeasurementStr = "";
             if (ReplayUtils::hasGnssDeviceFile() &&
                 ReplayUtils::isGnssRawMeasurement(
@@ -103,15 +125,19 @@
                 auto measurement = Utils::getMockMeasurement(enableCorrVecOutputs);
                 this->reportMeasurement(measurement);
             }
-            std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMillis));
-        }
+            intervalMs =
+                    (mLocationEnabled) ? std::min(mLocationIntervalMs, mIntervalMs) : mIntervalMs;
+        } while (mIsActive && mThreadBlocker.wait_for(std::chrono::milliseconds(intervalMs)));
     });
-    mThread.detach();
 }
 
 void GnssMeasurementInterface::stop() {
     ALOGD("stop");
     mIsActive = false;
+    mThreadBlocker.notify();
+    if (mThread.joinable()) {
+        mFutures.push_back(std::async(std::launch::async, [this] { mThread.join(); }));
+    }
 }
 
 void GnssMeasurementInterface::reportMeasurement(const GnssData& data) {
@@ -128,4 +154,21 @@
     callbackCopy->gnssMeasurementCb(data);
 }
 
+void GnssMeasurementInterface::setLocationInterval(const int intervalMs) {
+    mLocationIntervalMs = intervalMs;
+}
+
+void GnssMeasurementInterface::setLocationEnabled(const bool enabled) {
+    mLocationEnabled = enabled;
+}
+
+void GnssMeasurementInterface::waitForStoppingThreads() {
+    for (auto& future : mFutures) {
+        ALOGD("Stopping previous thread.");
+        future.wait();
+        ALOGD("Done stopping thread.");
+    }
+    mFutures.clear();
+}
+
 }  // namespace aidl::android::hardware::gnss