Make log reader thread a class member

pushedEventThread references class members after detaching. Making
pushedEventThread as class member and joining in statsService
destructor. Adding a method to stop readLogs thread.

Ignore-AOSP-First: Bug is in still security triage and fuzzer is
crashing on startup.
Test: atest statsd_test
Test: m statsd_service_fuzzer && adb sync data && adb shell
/data/fuzz/arm64/statsd_service_fuzzer/statsd_service_fuzzer -runs=10000
Bug: 285645039
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:3937ea3cdcf531a14cdba4ef176d8aa89d9d6066)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:8dca7a8e0f241a041ac2e061c0070839aee560ff)
Merged-In: I91dadeaf8a14d2e41d272c0ebfac618bff255998
Change-Id: I91dadeaf8a14d2e41d272c0ebfac618bff255998
diff --git a/statsd/src/StatsService.cpp b/statsd/src/StatsService.cpp
index ef21a04..c0c1076 100644
--- a/statsd/src/StatsService.cpp
+++ b/statsd/src/StatsService.cpp
@@ -170,12 +170,15 @@
     init_system_properties();
 
     if (mEventQueue != nullptr) {
-        std::thread pushedEventThread([this] { readLogs(); });
-        pushedEventThread.detach();
+        mLogsReaderThread = std::make_unique<std::thread>([this] { readLogs(); });
     }
 }
 
 StatsService::~StatsService() {
+    if (mEventQueue != nullptr) {
+        stopReadingLogs();
+        mLogsReaderThread->join();
+    }
 }
 
 /* Runs on a dedicated thread to process pushed events. */
@@ -184,6 +187,13 @@
     while (1) {
         // Block until an event is available.
         auto event = mEventQueue->waitPop();
+
+        // Below flag will be set when statsd is exiting and log event will be pushed to break
+        // out of waitPop.
+        if (mIsStopRequested) {
+            break;
+        }
+
         // Pass it to StatsLogProcess to all configs/metrics
         // At this point, the LogEventQueue is not blocked, so that the socketListener
         // can read events from the socket and write to buffer to avoid data drop.
@@ -1349,6 +1359,15 @@
     mPullerManager->SetStatsCompanionService(nullptr);
 }
 
+void StatsService::stopReadingLogs() {
+    mIsStopRequested = true;
+    // Push this event so that readLogs will process and break out of the loop
+    // after the stop is requested.
+    int64_t timeStamp;
+    std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
+    mEventQueue->push(std::move(logEvent), &timeStamp);
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/statsd/src/StatsService.h b/statsd/src/StatsService.h
index 790397f..39c9a9f 100644
--- a/statsd/src/StatsService.h
+++ b/statsd/src/StatsService.h
@@ -347,6 +347,13 @@
     void statsCompanionServiceDiedImpl();
 
     /**
+     *  This method is used to stop log reader thread.
+     */
+    void stopReadingLogs();
+
+    std::atomic<bool> mIsStopRequested = false;
+
+    /**
      * Tracks the uid <--> package name mapping.
      */
     sp<UidMap> mUidMap;
@@ -389,6 +396,8 @@
     mutable mutex mShellSubscriberMutex;
     std::shared_ptr<LogEventQueue> mEventQueue;
 
+    std::unique_ptr<std::thread> mLogsReaderThread;
+
     MultiConditionTrigger mBootCompleteTrigger;
     static const inline string kBootCompleteTag = "BOOT_COMPLETE";
     static const inline string kUidMapReceivedTag = "UID_MAP";