Move thread creation to setCallback() from start()

This change only modifies the Cuttlefish emulator behavior.

Creating a new thread is a heavy operation. Doing so in start() slows
down the request handling. In a stress test like
testVariedRatesRepetitive, 100+ requests are received in a short time,
which results in accumulated requests waiting to be handled, and thus
breaks the subsequent tests.

This change moves creating a new thread from start() to setCallback()
to avoid thread creation for each new request.

Bug: 400325468
Test: atest CtsLocationGnssTestCases
Test: atest GtsLocationTestCases
Test: atest VtsHalGnssTargetTest
Change-Id: I6bf89989c572b0e7b1b9ba9339b922363ef26ce4
diff --git a/gnss/aidl/default/Gnss.cpp b/gnss/aidl/default/Gnss.cpp
index 1fd21d8..a0510ce 100644
--- a/gnss/aidl/default/Gnss.cpp
+++ b/gnss/aidl/default/Gnss.cpp
@@ -91,6 +91,52 @@
     if (!status.isOk()) {
         ALOGE("%s: Unable to invoke callback.gnssSetSignalTypeCapabilitiesCb", __func__);
     }
+
+    // In case when the setCallback() and close() calls are not balanced
+    mIsInitialized = false;
+    mIsActive = false;
+    mThreadBlocker.notify();
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+
+    mIsInitialized = true;
+    mThreadBlocker.reset();
+    mThread = std::thread([this]() {
+        while (mIsInitialized) {
+            if (mIsActive) {
+                if (mReportedLocationCount == 0) {
+                    if (!mGnssMeasurementEnabled || mMinIntervalMs <= mGnssMeasurementIntervalMs) {
+                        this->reportSvStatus();
+                    }
+                    if (!mFirstFixReceived) {
+                        // Simulate the code start TTFF
+                        std::this_thread::sleep_for(std::chrono::milliseconds(TTFF_MILLIS));
+                        mFirstFixReceived = true;
+                    }
+                }
+                if (!mGnssMeasurementEnabled || mMinIntervalMs <= mGnssMeasurementIntervalMs) {
+                    this->reportSvStatus();
+                }
+                this->reportNmea();
+
+                auto currentLocation = getLocationFromHW();
+                mGnssPowerIndication->notePowerConsumption();
+                if (currentLocation != nullptr) {
+                    this->reportLocation(*currentLocation);
+                } else {
+                    const auto location = Utils::getMockLocation();
+                    this->reportLocation(location);
+                }
+                mReportedLocationCount += 1;
+                mThreadBlocker.wait_for(std::chrono::milliseconds(mMinIntervalMs));
+            } else {
+                // Wait indefinitely until start() or close() is called
+                mThreadBlocker.wait();
+            }
+        }
+    });
+
     return ScopedAStatus::ok();
 }
 
@@ -104,48 +150,16 @@
 }
 
 ScopedAStatus Gnss::start() {
-    ALOGD("start()");
+    ALOGD("start");
     if (mIsActive) {
         ALOGW("Gnss has started. Restarting...");
         stop();
     }
-
     mIsActive = true;
-    mThreadBlocker.reset();
     // notify measurement engine to update measurement interval
     mGnssMeasurementInterface->setLocationEnabled(true);
     this->reportGnssStatusValue(IGnssCallback::GnssStatusValue::SESSION_BEGIN);
-    mThread = std::thread([this]() {
-        if (!mGnssMeasurementEnabled || mMinIntervalMs <= mGnssMeasurementIntervalMs) {
-            this->reportSvStatus();
-        }
-        if (!mFirstFixReceived) {
-            std::this_thread::sleep_for(std::chrono::milliseconds(TTFF_MILLIS));
-            mFirstFixReceived = true;
-        }
-        int reportGnssCount = 0;
-        do {
-            if (!mIsActive) {
-                ALOGD("Do not report location. mIsActive is false");
-                break;
-            }
-            reportGnssCount += 1;
-            if (!mGnssMeasurementEnabled || mMinIntervalMs <= mGnssMeasurementIntervalMs) {
-                this->reportSvStatus();
-            }
-            this->reportNmea();
-
-            auto currentLocation = getLocationFromHW();
-            mGnssPowerIndication->notePowerConsumption();
-            if (currentLocation != nullptr) {
-                this->reportLocation(*currentLocation);
-            } else {
-                const auto location = Utils::getMockLocation();
-                this->reportLocation(location);
-            }
-        } while (mIsActive && mThreadBlocker.wait_for(std::chrono::milliseconds(mMinIntervalMs)));
-        ALOGD("reportGnssCount: %d", reportGnssCount);
-    });
+    mThreadBlocker.notify();
     return ScopedAStatus::ok();
 }
 
@@ -154,16 +168,22 @@
     mIsActive = false;
     mGnssMeasurementInterface->setLocationEnabled(false);
     this->reportGnssStatusValue(IGnssCallback::GnssStatusValue::SESSION_END);
+
+    int reportedLocationCount = mReportedLocationCount;
+    ALOGD("reportedLocationCount: %d", reportedLocationCount);
+    mReportedLocationCount = 0;
     mThreadBlocker.notify();
-    if (mThread.joinable()) {
-        mThread.join();
-    }
     return ScopedAStatus::ok();
 }
 
 ScopedAStatus Gnss::close() {
     ALOGD("close");
     sGnssCallback = nullptr;
+    mIsInitialized = false;
+    mThreadBlocker.notify();
+    if (mThread.joinable()) {
+        mThread.join();
+    }
     return ScopedAStatus::ok();
 }