Wait for all the thread loop to exit to finish the filter/dvr/frontend
close/stop API Call

Test: atest android.media.tv.tuner.cts
Bug: 180641600
Change-Id: I0925e8ffe5604d2c6a48871897871f5ac51c572e
diff --git a/tv/tuner/1.1/default/Demux.cpp b/tv/tuner/1.1/default/Demux.cpp
index 66c95dc..f4e4a91 100644
--- a/tv/tuner/1.1/default/Demux.cpp
+++ b/tv/tuner/1.1/default/Demux.cpp
@@ -27,12 +27,16 @@
 namespace implementation {
 
 #define WAIT_TIMEOUT 3000000000
+
 Demux::Demux(uint32_t demuxId, sp<Tuner> tuner) {
     mDemuxId = demuxId;
     mTunerService = tuner;
 }
 
-Demux::~Demux() {}
+Demux::~Demux() {
+    mFrontendInputThreadRunning = false;
+    std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
+}
 
 Return<Result> Demux::setFrontendDataSource(uint32_t frontendId) {
     ALOGV("%s", __FUNCTION__);
@@ -171,6 +175,8 @@
     mFilters.clear();
     mLastUsedFilterId = -1;
     mTunerService->removeDemux(mDemuxId);
+    mFrontendInputThreadRunning = false;
+    std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
 
     return Result::SUCCESS;
 }
@@ -322,6 +328,7 @@
 }
 
 void Demux::startFrontendInputLoop() {
+    mFrontendInputThreadRunning = true;
     pthread_create(&mFrontendInputThread, NULL, __threadLoopFrontend, this);
     pthread_setname_np(mFrontendInputThread, "frontend_input_thread");
 }
@@ -334,8 +341,6 @@
 
 void Demux::frontendInputThreadLoop() {
     std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
-    mFrontendInputThreadRunning = true;
-
     if (!mDvrPlayback) {
         ALOGW("[Demux] No software Frontend input configured. Ending Frontend thread loop.");
         mFrontendInputThreadRunning = false;
diff --git a/tv/tuner/1.1/default/Dvr.cpp b/tv/tuner/1.1/default/Dvr.cpp
index 3a4ef1b..93bb6a8 100644
--- a/tv/tuner/1.1/default/Dvr.cpp
+++ b/tv/tuner/1.1/default/Dvr.cpp
@@ -37,7 +37,10 @@
     mDemux = demux;
 }
 
-Dvr::~Dvr() {}
+Dvr::~Dvr() {
+    mDvrThreadRunning = false;
+    lock_guard<mutex> lock(mDvrThreadLock);
+}
 
 Return<void> Dvr::getQueueDesc(getQueueDesc_cb _hidl_cb) {
     ALOGV("%s", __FUNCTION__);
@@ -118,6 +121,9 @@
 
 Return<Result> Dvr::start() {
     ALOGV("%s", __FUNCTION__);
+    if (mDvrThreadRunning) {
+        return Result::SUCCESS;
+    }
 
     if (!mCallback) {
         return Result::NOT_INITIALIZED;
@@ -128,6 +134,7 @@
     }
 
     if (mType == DvrType::PLAYBACK) {
+        mDvrThreadRunning = true;
         pthread_create(&mDvrThread, NULL, __threadLoopPlayback, this);
         pthread_setname_np(mDvrThread, "playback_waiting_loop");
     } else if (mType == DvrType::RECORD) {
@@ -144,7 +151,6 @@
     ALOGV("%s", __FUNCTION__);
 
     mDvrThreadRunning = false;
-
     lock_guard<mutex> lock(mDvrThreadLock);
 
     mIsRecordStarted = false;
@@ -164,6 +170,8 @@
 Return<Result> Dvr::close() {
     ALOGV("%s", __FUNCTION__);
 
+    mDvrThreadRunning = false;
+    lock_guard<mutex> lock(mDvrThreadLock);
     return Result::SUCCESS;
 }
 
@@ -199,7 +207,6 @@
 void Dvr::playbackThreadLoop() {
     ALOGD("[Dvr] playback threadLoop start.");
     lock_guard<mutex> lock(mDvrThreadLock);
-    mDvrThreadRunning = true;
 
     while (mDvrThreadRunning) {
         uint32_t efState = 0;
diff --git a/tv/tuner/1.1/default/Filter.cpp b/tv/tuner/1.1/default/Filter.cpp
index 6b2413c..2e29aa9 100644
--- a/tv/tuner/1.1/default/Filter.cpp
+++ b/tv/tuner/1.1/default/Filter.cpp
@@ -77,7 +77,10 @@
     }
 }
 
-Filter::~Filter() {}
+Filter::~Filter() {
+    mFilterThreadRunning = false;
+    std::lock_guard<std::mutex> lock(mFilterThreadLock);
+}
 
 Return<void> Filter::getId64Bit(getId64Bit_cb _hidl_cb) {
     ALOGV("%s", __FUNCTION__);
@@ -137,15 +140,14 @@
 
 Return<Result> Filter::start() {
     ALOGV("%s", __FUNCTION__);
-
+    mFilterThreadRunning = true;
     return startFilterLoop();
 }
 
 Return<Result> Filter::stop() {
     ALOGV("%s", __FUNCTION__);
-
     mFilterThreadRunning = false;
-
+    std::lock_guard<std::mutex> lock(mFilterThreadLock);
     return Result::SUCCESS;
 }
 
@@ -185,6 +187,8 @@
 Return<Result> Filter::close() {
     ALOGV("%s", __FUNCTION__);
 
+    mFilterThreadRunning = false;
+    std::lock_guard<std::mutex> lock(mFilterThreadLock);
     return mDemux->removeFilter(mFilterId);
 }
 
@@ -331,9 +335,11 @@
 }
 
 void Filter::filterThreadLoop() {
-    ALOGD("[Filter] filter %" PRIu64 " threadLoop start.", mFilterId);
+    if (!mFilterThreadRunning) {
+        return;
+    }
     std::lock_guard<std::mutex> lock(mFilterThreadLock);
-    mFilterThreadRunning = true;
+    ALOGD("[Filter] filter %" PRIu64 " threadLoop start.", mFilterId);
 
     // For the first time of filter output, implementation needs to send the filter
     // Event Callback without waiting for the DATA_CONSUMED to init the process.
@@ -382,6 +388,9 @@
         // We do not wait for the last round of written data to be read to finish the thread
         // because the VTS can verify the reading itself.
         for (int i = 0; i < SECTION_WRITE_COUNT; i++) {
+            if (!mFilterThreadRunning) {
+                break;
+            }
             while (mFilterThreadRunning && mIsUsingFMQ) {
                 status_t status = mFilterEventFlag->wait(
                         static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED), &efState,
@@ -417,9 +426,8 @@
                 break;
             }
         }
-        mFilterThreadRunning = false;
+        break;
     }
-
     ALOGD("[Filter] filter thread ended.");
 }