Merge "Refine tuner aidl hal threads."
diff --git a/tv/tuner/aidl/default/Demux.cpp b/tv/tuner/aidl/default/Demux.cpp
index 3937c6a..8e83d06 100644
--- a/tv/tuner/aidl/default/Demux.cpp
+++ b/tv/tuner/aidl/default/Demux.cpp
@@ -37,8 +37,7 @@
 }
 
 Demux::~Demux() {
-    mFrontendInputThreadRunning = false;
-    std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
+    close();
 }
 
 ::ndk::ScopedAStatus Demux::setFrontendDataSource(int32_t in_frontendId) {
@@ -171,6 +170,8 @@
 ::ndk::ScopedAStatus Demux::close() {
     ALOGV("%s", __FUNCTION__);
 
+    stopFrontendInput();
+
     set<int64_t>::iterator it;
     for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
         mDvrPlayback->removePlaybackFilter(*it);
@@ -180,8 +181,6 @@
     mFilters.clear();
     mLastUsedFilterId = -1;
     mTuner->removeDemux(mDemuxId);
-    mFrontendInputThreadRunning = false;
-    std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
 
     return ::ndk::ScopedAStatus::ok();
 }
@@ -345,14 +344,7 @@
 
 void Demux::startFrontendInputLoop() {
     mFrontendInputThreadRunning = true;
-    pthread_create(&mFrontendInputThread, NULL, __threadLoopFrontend, this);
-    pthread_setname_np(mFrontendInputThread, "frontend_input_thread");
-}
-
-void* Demux::__threadLoopFrontend(void* user) {
-    Demux* const self = static_cast<Demux*>(user);
-    self->frontendInputThreadLoop();
-    return 0;
+    mFrontendInputThread = std::thread(&Demux::frontendInputThreadLoop, this);
 }
 
 void Demux::frontendInputThreadLoop() {
@@ -360,7 +352,6 @@
         return;
     }
 
-    std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
     if (!mDvrPlayback) {
         ALOGW("[Demux] No software Frontend input configured. Ending Frontend thread loop.");
         mFrontendInputThreadRunning = false;
@@ -402,7 +393,9 @@
     ALOGD("[Demux] stop frontend on demux");
     mKeepFetchingDataFromFrontend = false;
     mFrontendInputThreadRunning = false;
-    std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
+    if (mFrontendInputThread.joinable()) {
+        mFrontendInputThread.join();
+    }
 }
 
 void Demux::setIsRecording(bool isRecording) {
diff --git a/tv/tuner/aidl/default/Demux.h b/tv/tuner/aidl/default/Demux.h
index 4d9b7fe..1b789bd 100644
--- a/tv/tuner/aidl/default/Demux.h
+++ b/tv/tuner/aidl/default/Demux.h
@@ -20,7 +20,10 @@
 
 #include <fmq/AidlMessageQueue.h>
 #include <math.h>
+#include <atomic>
 #include <set>
+#include <thread>
+
 #include "Dvr.h"
 #include "Filter.h"
 #include "Frontend.h"
@@ -155,12 +158,14 @@
     std::shared_ptr<Dvr> mDvrRecord;
 
     // Thread handlers
-    pthread_t mFrontendInputThread;
+    std::thread mFrontendInputThread;
+
     /**
      * If a specific filter's writing loop is still running
      */
-    bool mFrontendInputThreadRunning;
-    bool mKeepFetchingDataFromFrontend;
+    std::atomic<bool> mFrontendInputThreadRunning;
+    std::atomic<bool> mKeepFetchingDataFromFrontend;
+
     /**
      * If the dvr recording is running.
      */
@@ -169,10 +174,6 @@
      * Lock to protect writes to the FMQs
      */
     std::mutex mWriteLock;
-    /**
-     * Lock to protect writes to the input status
-     */
-    std::mutex mFrontendInputThreadLock;
 
     // temp handle single PES filter
     // TODO handle mulptiple Pes filters
diff --git a/tv/tuner/aidl/default/Dvr.h b/tv/tuner/aidl/default/Dvr.h
index 586f885..ad8728e 100644
--- a/tv/tuner/aidl/default/Dvr.h
+++ b/tv/tuner/aidl/default/Dvr.h
@@ -129,7 +129,7 @@
      * If a specific filter's writing loop is still running
      */
     std::atomic<bool> mDvrThreadRunning;
-    bool mKeepFetchingDataFromFrontend;
+
     /**
      * Lock to protect writes to the FMQs
      */
diff --git a/tv/tuner/aidl/default/Filter.cpp b/tv/tuner/aidl/default/Filter.cpp
index 9755e39..bf89d12 100644
--- a/tv/tuner/aidl/default/Filter.cpp
+++ b/tv/tuner/aidl/default/Filter.cpp
@@ -85,8 +85,7 @@
 }
 
 Filter::~Filter() {
-    mFilterThreadRunning = false;
-    std::lock_guard<std::mutex> lock(mFilterThreadLock);
+    close();
 }
 
 ::ndk::ScopedAStatus Filter::getId64Bit(int64_t* _aidl_return) {
@@ -187,8 +186,12 @@
 
 ::ndk::ScopedAStatus Filter::stop() {
     ALOGV("%s", __FUNCTION__);
+
     mFilterThreadRunning = false;
-    std::lock_guard<std::mutex> lock(mFilterThreadLock);
+    if (mFilterThread.joinable()) {
+        mFilterThread.join();
+    }
+
     return ::ndk::ScopedAStatus::ok();
 }
 
@@ -226,8 +229,8 @@
 ::ndk::ScopedAStatus Filter::close() {
     ALOGV("%s", __FUNCTION__);
 
-    mFilterThreadRunning = false;
-    std::lock_guard<std::mutex> lock(mFilterThreadLock);
+    stop();
+
     return mDemux->removeFilter(mFilterId);
 }
 
@@ -376,22 +379,15 @@
 }
 
 ::ndk::ScopedAStatus Filter::startFilterLoop() {
-    pthread_create(&mFilterThread, NULL, __threadLoopFilter, this);
-    pthread_setname_np(mFilterThread, "filter_waiting_loop");
+    mFilterThread = std::thread(&Filter::filterThreadLoop, this);
     return ::ndk::ScopedAStatus::ok();
 }
 
-void* Filter::__threadLoopFilter(void* user) {
-    Filter* const self = static_cast<Filter*>(user);
-    self->filterThreadLoop();
-    return 0;
-}
-
 void Filter::filterThreadLoop() {
     if (!mFilterThreadRunning) {
         return;
     }
-    std::lock_guard<std::mutex> lock(mFilterThreadLock);
+
     ALOGD("[Filter] filter %" PRIu64 " threadLoop start.", mFilterId);
 
     // For the first time of filter output, implementation needs to send the filter
diff --git a/tv/tuner/aidl/default/Filter.h b/tv/tuner/aidl/default/Filter.h
index 3f40256..2ca25af 100644
--- a/tv/tuner/aidl/default/Filter.h
+++ b/tv/tuner/aidl/default/Filter.h
@@ -24,7 +24,10 @@
 #include <ion/ion.h>
 #include <math.h>
 #include <sys/stat.h>
+#include <atomic>
 #include <set>
+#include <thread>
+
 #include "Demux.h"
 #include "Dvr.h"
 #include "Frontend.h"
@@ -126,15 +129,14 @@
     vector<DemuxFilterEvent> mFilterEvents;
 
     // Thread handlers
-    pthread_t mFilterThread;
+    std::thread mFilterThread;
 
     // FMQ status local records
     DemuxFilterStatus mFilterStatus;
     /**
      * If a specific filter's writing loop is still running
      */
-    bool mFilterThreadRunning;
-    bool mKeepFetchingDataFromFrontend;
+    std::atomic<bool> mFilterThreadRunning;
 
     /**
      * How many times a filter should write
@@ -204,7 +206,6 @@
      * Lock to protect writes to the input status
      */
     std::mutex mFilterStatusLock;
-    std::mutex mFilterThreadLock;
     std::mutex mFilterOutputLock;
     std::mutex mRecordFilterOutputLock;
 
diff --git a/tv/tuner/aidl/vts/functional/DvrTests.cpp b/tv/tuner/aidl/vts/functional/DvrTests.cpp
index e356099..a9c3b51 100644
--- a/tv/tuner/aidl/vts/functional/DvrTests.cpp
+++ b/tv/tuner/aidl/vts/functional/DvrTests.cpp
@@ -24,26 +24,22 @@
     mPlaybackSettings = settings;
     mPlaybackMQ = std::make_unique<FilterMQ>(playbackMQDescriptor, true /* resetPointers */);
     EXPECT_TRUE(mPlaybackMQ);
-    pthread_create(&mPlaybackThread, NULL, __threadLoopPlayback, this);
-    pthread_setname_np(mPlaybackThread, "test_playback_input_loop");
+
+    mPlaybackThread = std::thread(&DvrCallback::playbackThreadLoop, this);
 }
 
 void DvrCallback::stopPlaybackThread() {
     mPlaybackThreadRunning = false;
     mKeepWritingPlaybackFMQ = false;
 
-    android::Mutex::Autolock autoLock(mPlaybackThreadLock);
-}
-
-void* DvrCallback::__threadLoopPlayback(void* user) {
-    DvrCallback* const self = static_cast<DvrCallback*>(user);
-    self->playbackThreadLoop();
-    return 0;
+    if (mPlaybackThread.joinable()) {
+        mPlaybackThread.join();
+    }
 }
 
 void DvrCallback::playbackThreadLoop() {
-    android::Mutex::Autolock autoLock(mPlaybackThreadLock);
     mPlaybackThreadRunning = true;
+    mKeepWritingPlaybackFMQ = true;
 
     // Create the EventFlag that is used to signal the HAL impl that data have been
     // written into the Playback FMQ
@@ -121,43 +117,31 @@
 }
 
 void DvrCallback::testRecordOutput() {
-    android::Mutex::Autolock autoLock(mMsgLock);
-    while (mDataOutputBuffer.empty()) {
-        if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
-            EXPECT_TRUE(false) << "record output matching pid does not output within timeout";
-            stopRecordThread();
-            return;
+    bool passed = true;
+    {
+        android::Mutex::Autolock autoLock(mMsgLock);
+        while (mDataOutputBuffer.empty()) {
+            if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+                EXPECT_TRUE(false) << "record output matching pid does not output within timeout";
+                passed = false;
+                break;
+            }
         }
     }
     stopRecordThread();
-    ALOGW("[vts] record pass and stop");
+    if (passed) ALOGW("[vts] record pass and stop");
 }
 
-void DvrCallback::startRecordOutputThread(RecordSettings recordSettings,
+void DvrCallback::startRecordOutputThread(RecordSettings /* recordSettings */,
                                           MQDesc& recordMQDescriptor) {
     mRecordMQ = std::make_unique<FilterMQ>(recordMQDescriptor, true /* resetPointers */);
     EXPECT_TRUE(mRecordMQ);
-    struct RecordThreadArgs* threadArgs =
-            (struct RecordThreadArgs*)malloc(sizeof(struct RecordThreadArgs));
-    threadArgs->user = this;
-    threadArgs->recordSettings = &recordSettings;
-    threadArgs->keepReadingRecordFMQ = &mKeepReadingRecordFMQ;
 
-    pthread_create(&mRecordThread, NULL, __threadLoopRecord, (void*)threadArgs);
-    pthread_setname_np(mRecordThread, "test_record_input_loop");
+    mRecordThread = std::thread(&DvrCallback::recordThreadLoop, this);
 }
 
-void* DvrCallback::__threadLoopRecord(void* threadArgs) {
-    DvrCallback* const self =
-            static_cast<DvrCallback*>(((struct RecordThreadArgs*)threadArgs)->user);
-    self->recordThreadLoop(((struct RecordThreadArgs*)threadArgs)->recordSettings,
-                           ((struct RecordThreadArgs*)threadArgs)->keepReadingRecordFMQ);
-    return 0;
-}
-
-void DvrCallback::recordThreadLoop(RecordSettings* /*recordSettings*/, bool* keepReadingRecordFMQ) {
+void DvrCallback::recordThreadLoop() {
     ALOGD("[vts] DvrCallback record threadLoop start.");
-    android::Mutex::Autolock autoLock(mRecordThreadLock);
     mRecordThreadRunning = true;
     mKeepReadingRecordFMQ = true;
 
@@ -168,7 +152,7 @@
                 android::OK);
 
     while (mRecordThreadRunning) {
-        while (*keepReadingRecordFMQ) {
+        while (mKeepReadingRecordFMQ) {
             uint32_t efState = 0;
             android::status_t status = recordMQEventFlag->wait(
                     static_cast<int32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
@@ -206,6 +190,10 @@
 void DvrCallback::stopRecordThread() {
     mKeepReadingRecordFMQ = false;
     mRecordThreadRunning = false;
+
+    if (mRecordThread.joinable()) {
+        mRecordThread.join();
+    }
 }
 
 AssertionResult DvrTests::openDvrInDemux(DvrType type, int32_t bufferSize) {
diff --git a/tv/tuner/aidl/vts/functional/DvrTests.h b/tv/tuner/aidl/vts/functional/DvrTests.h
index bda57b3..6662637 100644
--- a/tv/tuner/aidl/vts/functional/DvrTests.h
+++ b/tv/tuner/aidl/vts/functional/DvrTests.h
@@ -22,9 +22,11 @@
 #include <log/log.h>
 #include <utils/Condition.h>
 #include <utils/Mutex.h>
+#include <atomic>
 #include <fstream>
 #include <iostream>
 #include <map>
+#include <thread>
 
 #include <aidl/android/hardware/tv/tuner/BnDvrCallback.h>
 #include <aidl/android/hardware/tv/tuner/IDvr.h>
@@ -94,7 +96,7 @@
     static void* __threadLoopPlayback(void* user);
     static void* __threadLoopRecord(void* threadArgs);
     void playbackThreadLoop();
-    void recordThreadLoop(RecordSettings* recordSetting, bool* keepWritingPlaybackFMQ);
+    void recordThreadLoop();
 
     bool readRecordFMQ();
 
@@ -115,16 +117,14 @@
     std::map<uint32_t, EventFlag*> mFilterMQEventFlag;
 
     android::Mutex mMsgLock;
-    android::Mutex mPlaybackThreadLock;
-    android::Mutex mRecordThreadLock;
     android::Condition mMsgCondition;
 
-    bool mKeepWritingPlaybackFMQ = true;
-    bool mKeepReadingRecordFMQ = true;
-    bool mPlaybackThreadRunning;
-    bool mRecordThreadRunning;
-    pthread_t mPlaybackThread;
-    pthread_t mRecordThread;
+    std::atomic<bool> mKeepWritingPlaybackFMQ = true;
+    std::atomic<bool> mKeepReadingRecordFMQ = true;
+    std::atomic<bool> mPlaybackThreadRunning;
+    std::atomic<bool> mRecordThreadRunning;
+    std::thread mPlaybackThread;
+    std::thread mRecordThread;
     string mInputDataFile;
     PlaybackSettings mPlaybackSettings;