Put tuner scan handling to a thread.

Bug: 210747502
Fix: 210747502
Test: atest android.media.tv.tuner.cts on AIDL and HILD HALs.
Test: atest VtsHalTvTunerTargetTest
Test: atest VtsHalTvTunerV1_1TargetTest
Test: atest VtsHalTvTunerV1_0TargetTest
Change-Id: Iead93df1dc09ef2a047893037ad2345ad4183b1e
diff --git a/tv/tuner/1.1/default/Frontend.cpp b/tv/tuner/1.1/default/Frontend.cpp
index f5463a9..919c956 100644
--- a/tv/tuner/1.1/default/Frontend.cpp
+++ b/tv/tuner/1.1/default/Frontend.cpp
@@ -88,46 +88,60 @@
 
 Return<Result> Frontend::scan(const FrontendSettings& settings, FrontendScanType type) {
     ALOGV("%s", __FUNCTION__);
+
+    // If it's in middle of scanning, stop it first.
+    if (mScanThread.joinable()) {
+        mScanThread.join();
+    }
+
+    mFrontendSettings = settings;
+    mFrontendScanType = type;
+    mScanThread = std::thread(&Frontend::scanThreadLoop, this);
+
+    return Result::SUCCESS;
+}
+
+void Frontend::scanThreadLoop() {
     FrontendScanMessage msg;
 
     if (mIsLocked) {
         msg.isEnd(true);
         mCallback->onScanMessage(FrontendScanMessageType::END, msg);
-        return Result::SUCCESS;
+        return;
     }
 
     uint32_t frequency;
-    switch (settings.getDiscriminator()) {
+    switch (mFrontendSettings.getDiscriminator()) {
         case FrontendSettings::hidl_discriminator::analog:
-            frequency = settings.analog().frequency;
+            frequency = mFrontendSettings.analog().frequency;
             break;
         case FrontendSettings::hidl_discriminator::atsc:
-            frequency = settings.atsc().frequency;
+            frequency = mFrontendSettings.atsc().frequency;
             break;
         case FrontendSettings::hidl_discriminator::atsc3:
-            frequency = settings.atsc3().frequency;
+            frequency = mFrontendSettings.atsc3().frequency;
             break;
         case FrontendSettings::hidl_discriminator::dvbs:
-            frequency = settings.dvbs().frequency;
+            frequency = mFrontendSettings.dvbs().frequency;
             break;
         case FrontendSettings::hidl_discriminator::dvbc:
-            frequency = settings.dvbc().frequency;
+            frequency = mFrontendSettings.dvbc().frequency;
             break;
         case FrontendSettings::hidl_discriminator::dvbt:
-            frequency = settings.dvbt().frequency;
+            frequency = mFrontendSettings.dvbt().frequency;
             break;
         case FrontendSettings::hidl_discriminator::isdbs:
-            frequency = settings.isdbs().frequency;
+            frequency = mFrontendSettings.isdbs().frequency;
             break;
         case FrontendSettings::hidl_discriminator::isdbs3:
-            frequency = settings.isdbs3().frequency;
+            frequency = mFrontendSettings.isdbs3().frequency;
             break;
         case FrontendSettings::hidl_discriminator::isdbt:
-            frequency = settings.isdbt().frequency;
+            frequency = mFrontendSettings.isdbt().frequency;
             break;
     }
 
-    if (type == FrontendScanType::SCAN_BLIND) {
+    if (mFrontendScanType == FrontendScanType::SCAN_BLIND) {
         frequency += 100 * 1000;
     }
 
@@ -204,8 +218,6 @@
     msg.isLocked(true);
     mCallback->onScanMessage(FrontendScanMessageType::LOCKED, msg);
     mIsLocked = true;
-
-    return Result::SUCCESS;
 }
 
 Return<Result> Frontend::scan_1_1(const FrontendSettings& settings, FrontendScanType type,
@@ -218,6 +230,10 @@
 Return<Result> Frontend::stopScan() {
     ALOGV("%s", __FUNCTION__);
 
+    if (mScanThread.joinable()) {
+        mScanThread.join();
+    }
+
     mIsLocked = false;
     return Result::SUCCESS;
 }
diff --git a/tv/tuner/1.1/default/Frontend.h b/tv/tuner/1.1/default/Frontend.h
index a28fb64..bf739a8 100644
--- a/tv/tuner/1.1/default/Frontend.h
+++ b/tv/tuner/1.1/default/Frontend.h
@@ -20,6 +20,7 @@
 #include <android/hardware/tv/tuner/1.1/IFrontend.h>
 #include <fstream>
 #include <iostream>
+#include <thread>
 #include "Tuner.h"
 
 using namespace std;
@@ -81,13 +82,17 @@
   private:
     virtual ~Frontend();
     bool supportsSatellite();
+    void scanThreadLoop();
+
     sp<IFrontendCallback> mCallback;
     sp<Tuner> mTunerService;
     FrontendType mType = FrontendType::UNDEFINED;
     FrontendId mId = 0;
     bool mIsLocked = false;
     uint32_t mCiCamId;
-
+    std::thread mScanThread;
+    FrontendSettings mFrontendSettings;
+    FrontendScanType mFrontendScanType;
     std::ifstream mFrontendData;
 };
 
diff --git a/tv/tuner/aidl/default/Frontend.cpp b/tv/tuner/aidl/default/Frontend.cpp
index d36841c..714612d 100644
--- a/tv/tuner/aidl/default/Frontend.cpp
+++ b/tv/tuner/aidl/default/Frontend.cpp
@@ -87,47 +87,60 @@
 ::ndk::ScopedAStatus Frontend::scan(const FrontendSettings& in_settings, FrontendScanType in_type) {
     ALOGV("%s", __FUNCTION__);
 
+    // If it's in middle of scanning, stop it first.
+    if (mScanThread.joinable()) {
+        mScanThread.join();
+    }
+
+    mFrontendSettings = in_settings;
+    mFrontendScanType = in_type;
+    mScanThread = std::thread(&Frontend::scanThreadLoop, this);
+
+    return ::ndk::ScopedAStatus::ok();
+}
+
+void Frontend::scanThreadLoop() {
     if (mIsLocked) {
         FrontendScanMessage msg;
         msg.set<FrontendScanMessage::Tag::isEnd>(true);
         mCallback->onScanMessage(FrontendScanMessageType::END, msg);
-        return ::ndk::ScopedAStatus::ok();
+        return;
     }
 
     int64_t frequency = 0;
-    switch (in_settings.getTag()) {
+    switch (mFrontendSettings.getTag()) {
         case FrontendSettings::Tag::analog:
-            frequency = in_settings.get<FrontendSettings::Tag::analog>().frequency;
+            frequency = mFrontendSettings.get<FrontendSettings::Tag::analog>().frequency;
             break;
         case FrontendSettings::Tag::atsc:
-            frequency = in_settings.get<FrontendSettings::Tag::atsc>().frequency;
+            frequency = mFrontendSettings.get<FrontendSettings::Tag::atsc>().frequency;
             break;
         case FrontendSettings::Tag::atsc3:
-            frequency = in_settings.get<FrontendSettings::Tag::atsc3>().frequency;
+            frequency = mFrontendSettings.get<FrontendSettings::Tag::atsc3>().frequency;
             break;
         case FrontendSettings::Tag::dvbs:
-            frequency = in_settings.get<FrontendSettings::Tag::dvbs>().frequency;
+            frequency = mFrontendSettings.get<FrontendSettings::Tag::dvbs>().frequency;
             break;
         case FrontendSettings::Tag::dvbc:
-            frequency = in_settings.get<FrontendSettings::Tag::dvbc>().frequency;
+            frequency = mFrontendSettings.get<FrontendSettings::Tag::dvbc>().frequency;
             break;
         case FrontendSettings::Tag::dvbt:
-            frequency = in_settings.get<FrontendSettings::Tag::dvbt>().frequency;
+            frequency = mFrontendSettings.get<FrontendSettings::Tag::dvbt>().frequency;
             break;
         case FrontendSettings::Tag::isdbs:
-            frequency = in_settings.get<FrontendSettings::Tag::isdbs>().frequency;
+            frequency = mFrontendSettings.get<FrontendSettings::Tag::isdbs>().frequency;
             break;
         case FrontendSettings::Tag::isdbs3:
-            frequency = in_settings.get<FrontendSettings::Tag::isdbs3>().frequency;
+            frequency = mFrontendSettings.get<FrontendSettings::Tag::isdbs3>().frequency;
             break;
         case FrontendSettings::Tag::isdbt:
-            frequency = in_settings.get<FrontendSettings::Tag::isdbt>().frequency;
+            frequency = mFrontendSettings.get<FrontendSettings::Tag::isdbt>().frequency;
             break;
         default:
             break;
     }
 
-    if (in_type == FrontendScanType::SCAN_BLIND) {
+    if (mFrontendScanType == FrontendScanType::SCAN_BLIND) {
         frequency += 100 * 1000;
     }
 
@@ -250,13 +263,15 @@
         mCallback->onScanMessage(FrontendScanMessageType::LOCKED, msg);
         mIsLocked = true;
     }
-
-    return ::ndk::ScopedAStatus::ok();
 }
 
 ::ndk::ScopedAStatus Frontend::stopScan() {
     ALOGV("%s", __FUNCTION__);
 
+    if (mScanThread.joinable()) {
+        mScanThread.join();
+    }
+
     mIsLocked = false;
     return ::ndk::ScopedAStatus::ok();
 }
diff --git a/tv/tuner/aidl/default/Frontend.h b/tv/tuner/aidl/default/Frontend.h
index 66ae901..fdedf1e 100644
--- a/tv/tuner/aidl/default/Frontend.h
+++ b/tv/tuner/aidl/default/Frontend.h
@@ -19,6 +19,7 @@
 #include <aidl/android/hardware/tv/tuner/BnFrontend.h>
 #include <fstream>
 #include <iostream>
+#include <thread>
 #include "Tuner.h"
 
 using namespace std;
@@ -60,13 +61,17 @@
   private:
     virtual ~Frontend();
     bool supportsSatellite();
+    void scanThreadLoop();
+
     std::shared_ptr<IFrontendCallback> mCallback;
     std::shared_ptr<Tuner> mTuner;
     FrontendType mType = FrontendType::UNDEFINED;
     int32_t mId = 0;
     bool mIsLocked = false;
     int32_t mCiCamId;
-
+    std::thread mScanThread;
+    FrontendSettings mFrontendSettings;
+    FrontendScanType mFrontendScanType;
     std::ifstream mFrontendData;
 };