Allow users to switch between FE source and DVR source when testing
record/descrambling/broadcast

Test: atest VtsHalTvTunerV1_0TargetTest
Test: atest VtsHalTvTunerV1_1TargetTest
Bug: 182519645
CTS-Coverage-Bug: 184077478
Change-Id: I6c57657ac3539d6a6fb3f63d2ecc9af7f6b9e2dc
diff --git a/tv/tuner/1.1/default/Demux.cpp b/tv/tuner/1.1/default/Demux.cpp
index db25c2e..15b8e6c 100644
--- a/tv/tuner/1.1/default/Demux.cpp
+++ b/tv/tuner/1.1/default/Demux.cpp
@@ -392,6 +392,10 @@
     mIsRecording = isRecording;
 }
 
+bool Demux::isRecording() {
+    return mIsRecording;
+}
+
 bool Demux::attachRecordFilter(uint64_t filterId) {
     if (mFilters[filterId] == nullptr || mDvrRecord == nullptr ||
         !mFilters[filterId]->isRecordFilter()) {
diff --git a/tv/tuner/1.1/default/Demux.h b/tv/tuner/1.1/default/Demux.h
index 5212eae..ce46f9c 100644
--- a/tv/tuner/1.1/default/Demux.h
+++ b/tv/tuner/1.1/default/Demux.h
@@ -85,6 +85,7 @@
     void updateMediaFilterOutput(uint64_t filterId, vector<uint8_t> data, uint64_t pts);
     uint16_t getFilterTpid(uint64_t filterId);
     void setIsRecording(bool isRecording);
+    bool isRecording();
     void startFrontendInputLoop();
 
     /**
diff --git a/tv/tuner/1.1/default/Dvr.cpp b/tv/tuner/1.1/default/Dvr.cpp
index 93bb6a8..c487d98 100644
--- a/tv/tuner/1.1/default/Dvr.cpp
+++ b/tv/tuner/1.1/default/Dvr.cpp
@@ -218,19 +218,26 @@
             continue;
         }
 
+        // If the both dvr playback and dvr record are created, the playback will be treated as
+        // the source of the record. isVirtualFrontend set to true would direct the dvr playback
+        // input to the demux record filters or live broadcast filters.
+        bool isRecording = mDemux->isRecording();
+        bool isVirtualFrontend = isRecording;
+
         if (mDvrSettings.playback().dataFormat == DataFormat::ES) {
-            if (!processEsDataOnPlayback(false /*isVirtualFrontend*/, false /*isRecording*/)) {
+            if (!processEsDataOnPlayback(isVirtualFrontend, isRecording)) {
                 ALOGE("[Dvr] playback es data failed to be filtered. Ending thread");
                 break;
             }
             maySendPlaybackStatusCallback();
             continue;
         }
+
         // Our current implementation filter the data and write it into the filter FMQ immediately
         // after the DATA_READY from the VTS/framework
         // This is for the non-ES data source, real playback use case handling.
-        if (!readPlaybackFMQ(false /*isVirtualFrontend*/, false /*isRecording*/) ||
-            !startFilterDispatcher(false /*isVirtualFrontend*/, false /*isRecording*/)) {
+        if (!readPlaybackFMQ(isVirtualFrontend, isRecording) ||
+            !startFilterDispatcher(isVirtualFrontend, isRecording)) {
             ALOGE("[Dvr] playback data failed to be filtered. Ending thread");
             break;
         }
diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
index 1080861..e70c320 100644
--- a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
@@ -22,10 +22,6 @@
     return filterDataOutputTestBase(mFilterTests);
 }
 
-AssertionResult TunerRecordHidlTest::filterDataOutputTest() {
-    return filterDataOutputTestBase(mFilterTests);
-}
-
 void TunerFilterHidlTest::configSingleFilterInDemuxTest(FilterConfig1_1 filterConf,
                                                         FrontendConfig1_1 frontendConf) {
     uint32_t feId;
@@ -70,6 +66,9 @@
     ASSERT_TRUE(feId != INVALID_ID);
     ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
     ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+    if (frontendConf.config1_0.isSoftwareFe) {
+        mFrontendTests.setSoftwareFrontendDvrConfig(dvrMap[live.dvrSoftwareFeId]);
+    }
     ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
     ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
     mFrontendTests.setDemux(demux);
@@ -103,6 +102,9 @@
     ASSERT_TRUE(feId != INVALID_ID);
     ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
     ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+    if (frontendConf.config1_0.isSoftwareFe) {
+        mFrontendTests.setSoftwareFrontendDvrConfig(dvrMap[live.dvrSoftwareFeId]);
+    }
     ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
     ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
     mFrontendTests.setDemux(demux);
@@ -129,21 +131,33 @@
 void TunerRecordHidlTest::recordSingleFilterTest(FilterConfig1_1 filterConf,
                                                  FrontendConfig1_1 frontendConf,
                                                  DvrConfig dvrConf) {
-    uint32_t feId;
     uint32_t demuxId;
     sp<IDemux> demux;
+    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+    mDvrTests.setDemux(demux);
+
+    DvrConfig dvrSourceConfig;
+    if (record.hasFrontendConnection) {
+        uint32_t feId;
+        mFrontendTests.getFrontendIdByType(frontendConf.config1_0.type, feId);
+        ASSERT_TRUE(feId != INVALID_ID);
+        ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+        ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+        if (frontendConf.config1_0.isSoftwareFe) {
+            mFrontendTests.setSoftwareFrontendDvrConfig(dvrMap[record.dvrSoftwareFeId]);
+        }
+        ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+        mFrontendTests.setDvrTests(mDvrTests);
+    } else {
+        dvrSourceConfig = dvrMap[record.dvrSourceId];
+        ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrSourceConfig.type, dvrSourceConfig.bufferSize));
+        ASSERT_TRUE(mDvrTests.configDvrPlayback(dvrSourceConfig.settings));
+        ASSERT_TRUE(mDvrTests.getDvrPlaybackMQDescriptor());
+    }
+
     uint64_t filterId;
     sp<IFilter> filter;
-
-    mFrontendTests.getFrontendIdByType(frontendConf.config1_0.type, feId);
-    ASSERT_TRUE(feId != INVALID_ID);
-    ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
-    ASSERT_TRUE(mFrontendTests.setFrontendCallback());
-    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
-    ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
     mFilterTests.setDemux(demux);
-    mDvrTests.setDemux(demux);
-    mFrontendTests.setDvrTests(mDvrTests);
     ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type, dvrConf.bufferSize));
     ASSERT_TRUE(mDvrTests.configDvrRecord(dvrConf.settings));
     ASSERT_TRUE(mDvrTests.getDvrRecordMQDescriptor());
@@ -158,22 +172,46 @@
     ASSERT_TRUE(mDvrTests.attachFilterToDvr(filter));
     ASSERT_TRUE(mDvrTests.startDvrRecord());
     ASSERT_TRUE(mFilterTests.startFilter(filterId));
-    ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
+
+    if (record.hasFrontendConnection) {
+        ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
+    } else {
+        // Start DVR Source
+        mDvrTests.startPlaybackInputThread(dvrSourceConfig.playbackInputFile,
+                                           dvrSourceConfig.settings.playback());
+        ASSERT_TRUE(mDvrTests.startDvrPlayback());
+    }
+
     mDvrTests.testRecordOutput();
-    ASSERT_TRUE(filterDataOutputTest());
     mDvrTests.stopRecordThread();
-    ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
+
+    if (record.hasFrontendConnection) {
+        ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
+    } else {
+        mDvrTests.stopPlaybackThread();
+        ASSERT_TRUE(mDvrTests.stopDvrPlayback());
+    }
+
     ASSERT_TRUE(mFilterTests.stopFilter(filterId));
     ASSERT_TRUE(mDvrTests.stopDvrRecord());
     ASSERT_TRUE(mDvrTests.detachFilterToDvr(filter));
     ASSERT_TRUE(mFilterTests.closeFilter(filterId));
     mDvrTests.closeDvrRecord();
+
+    if (record.hasFrontendConnection) {
+        ASSERT_TRUE(mFrontendTests.closeFrontend());
+    } else {
+        mDvrTests.closeDvrPlayback();
+    }
+
     ASSERT_TRUE(mDemuxTests.closeDemux());
-    ASSERT_TRUE(mFrontendTests.closeFrontend());
 }
 
 TEST_P(TunerFilterHidlTest, StartFilterInDemux) {
     description("Open and start a filter in Demux.");
+    if (!live.hasFrontendConnection) {
+        return;
+    }
     // TODO use parameterized tests
     configSingleFilterInDemuxTest(filterMap[live.videoFilterId], frontendMap[live.frontendId]);
 }
@@ -181,6 +219,9 @@
 TEST_P(TunerFilterHidlTest, ConfigIpFilterInDemuxWithCid) {
     description("Open and configure an ip filter in Demux.");
     // TODO use parameterized tests
+    if (!live.hasFrontendConnection) {
+        return;
+    }
     if (live.ipFilterId.compare(emptyHardwareId) == 0) {
         return;
     }
@@ -189,6 +230,9 @@
 
 TEST_P(TunerFilterHidlTest, ReconfigFilterToReceiveStartId) {
     description("Recofigure and restart a filter to test start id.");
+    if (!live.hasFrontendConnection) {
+        return;
+    }
     // TODO use parameterized tests
     reconfigSingleFilterInDemuxTest(filterMap[live.videoFilterId], filterMap[live.videoFilterId],
                                     frontendMap[live.frontendId]);
@@ -205,16 +249,25 @@
 
 TEST_P(TunerFrontendHidlTest, TuneFrontendWithFrontendSettingsExt1_1) {
     description("Tune one Frontend with v1_1 extended setting and check Lock event");
+    if (!live.hasFrontendConnection) {
+        return;
+    }
     mFrontendTests.tuneTest(frontendMap[live.frontendId]);
 }
 
 TEST_P(TunerFrontendHidlTest, BlindScanFrontendWithEndFrequency) {
     description("Run an blind frontend scan with v1_1 extended setting and check lock scanMessage");
+    if (!scan.hasFrontendConnection) {
+        return;
+    }
     mFrontendTests.scanTest(frontendMap[scan.frontendId], FrontendScanType::SCAN_BLIND);
 }
 
 TEST_P(TunerBroadcastHidlTest, MediaFilterWithSharedMemoryHandle) {
     description("Test the Media Filter with shared memory handle");
+    if (!live.hasFrontendConnection) {
+        return;
+    }
     mediaFilterUsingSharedMemoryTest(filterMap[live.videoFilterId], frontendMap[live.frontendId]);
 }
 
@@ -225,6 +278,9 @@
 
 TEST_P(TunerFrontendHidlTest, LinkToCiCam) {
     description("Test Frontend link to CiCam");
+    if (!live.hasFrontendConnection) {
+        return;
+    }
     if (!frontendMap[live.frontendId].canConnectToCiCam) {
         return;
     }
diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h
index 863f649..007e3d5 100644
--- a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h
@@ -97,7 +97,6 @@
 
     void recordSingleFilterTest(FilterConfig1_1 filterConf, FrontendConfig1_1 frontendConf,
                                 DvrConfig dvrConf);
-    AssertionResult filterDataOutputTest();
 
     sp<ITuner> mService;
     FrontendTests mFrontendTests;
diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h
index 390bd4c..2b5ad46 100644
--- a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h
@@ -148,6 +148,11 @@
 };
 
 inline bool validateConnections() {
+    if (record.support && !record.hasFrontendConnection &&
+        record.dvrSourceId.compare(emptyHardwareId) == 0) {
+        ALOGW("[vts config] Record must support either a DVR source or a Frontend source.");
+        return false;
+    }
     bool feIsValid = frontendMap.find(live.frontendId) != frontendMap.end() &&
                      frontendMap.find(scan.frontendId) != frontendMap.end();
     feIsValid &= record.support ? frontendMap.find(record.frontendId) != frontendMap.end() : true;
@@ -160,9 +165,14 @@
     bool dvrIsValid = frontendMap[live.frontendId].config1_0.isSoftwareFe
                               ? dvrMap.find(live.dvrSoftwareFeId) != dvrMap.end()
                               : true;
+
     if (record.support) {
-        if (frontendMap[record.frontendId].config1_0.isSoftwareFe) {
-            dvrIsValid &= dvrMap.find(record.dvrSoftwareFeId) != dvrMap.end();
+        if (record.hasFrontendConnection) {
+            if (frontendMap[record.frontendId].config1_0.isSoftwareFe) {
+                dvrIsValid &= dvrMap.find(record.dvrSoftwareFeId) != dvrMap.end();
+            }
+        } else {
+            dvrIsValid &= dvrMap.find(record.dvrSourceId) != dvrMap.end();
         }
         dvrIsValid &= dvrMap.find(record.dvrRecordId) != dvrMap.end();
     }