Extend 1.0 dynamic config reader to read 1.1 Tuner HAL types

Test: atest VtsHalTvTunerV1_1TargetTest
Test: atest VtsHalTvTunerV1_0TargetTest
Bug: 182519645
CTS-Coverage-Bug: 184077478
Change-Id: I0438fff48a6a763b88ed20e34d8ace66a6211302
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
index e240604..8358291 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
@@ -32,7 +32,8 @@
 namespace {
 
 bool initConfiguration() {
-    if (!TunerTestingConfigReader::checkConfigFileExists()) {
+    TunerTestingConfigReader1_0::setConfigFilePath(configFilePath);
+    if (!TunerTestingConfigReader1_0::checkConfigFileExists()) {
         return false;
     }
     initFrontendConfig();
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
index 65f8615..a1597c7 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
@@ -21,7 +21,7 @@
 #include <hidl/Status.h>
 #include <hidlmemory/FrameworkUtils.h>
 
-#include "../../../config/TunerTestingConfigReader.h"
+#include "../../../config/TunerTestingConfigReaderV1_0.h"
 
 using android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
 using android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
@@ -39,6 +39,8 @@
 const uint32_t FMQ_SIZE_4M = 0x400000;
 const uint32_t FMQ_SIZE_16M = 0x1000000;
 
+const string configFilePath = "/vendor/etc/tuner_vts_config_1_0.xml";
+
 #define FILTER_MAIN_TYPE_BIT_COUNT 5
 
 // Hardware configs
@@ -85,7 +87,7 @@
     frontendMap[defaultFeId].isSoftwareFe = true;
 
     // Read customized config
-    TunerTestingConfigReader::readFrontendConfig1_0(frontendMap);
+    TunerTestingConfigReader1_0::readFrontendConfig1_0(frontendMap);
 };
 
 inline void initFilterConfig() {
@@ -107,44 +109,44 @@
     filterMap[defaultAudioFilterId].settings.ts().filterSettings.av({.isPassthrough = false});
 
     // Read customized config
-    TunerTestingConfigReader::readFilterConfig1_0(filterMap);
+    TunerTestingConfigReader1_0::readFilterConfig1_0(filterMap);
 };
 
 /** Config all the dvrs that would be used in the tests */
 inline void initDvrConfig() {
     // Read customized config
-    TunerTestingConfigReader::readDvrConfig1_0(dvrMap);
+    TunerTestingConfigReader1_0::readDvrConfig1_0(dvrMap);
 };
 
 /** Config all the lnbs that would be used in the tests */
 inline void initLnbConfig() {
     // Read customized config
-    TunerTestingConfigReader::readLnbConfig1_0(lnbMap);
-    TunerTestingConfigReader::readDiseqcMessages(diseqcMsgMap);
+    TunerTestingConfigReader1_0::readLnbConfig1_0(lnbMap);
+    TunerTestingConfigReader1_0::readDiseqcMessages(diseqcMsgMap);
 };
 
 /** Config all the time filters that would be used in the tests */
 inline void initTimeFilterConfig() {
     // Read customized config
-    TunerTestingConfigReader::readTimeFilterConfig1_0(timeFilterMap);
+    TunerTestingConfigReader1_0::readTimeFilterConfig1_0(timeFilterMap);
 };
 
 /** Config all the descramblers that would be used in the tests */
 inline void initDescramblerConfig() {
     // Read customized config
-    TunerTestingConfigReader::readDescramblerConfig1_0(descramblerMap);
+    TunerTestingConfigReader1_0::readDescramblerConfig1_0(descramblerMap);
 };
 
 /** Read the vendor configurations of which hardware to use for each test cases/data flows */
 inline void connectHardwaresToTestCases() {
-    TunerTestingConfigReader::connectLiveBroadcast(live);
-    TunerTestingConfigReader::connectScan(scan);
-    TunerTestingConfigReader::connectDvrPlayback(playback);
-    TunerTestingConfigReader::connectDvrRecord(record);
-    TunerTestingConfigReader::connectDescrambling(descrambling);
-    TunerTestingConfigReader::connectLnbLive(lnbLive);
-    TunerTestingConfigReader::connectLnbRecord(lnbRecord);
-    TunerTestingConfigReader::connectTimeFilter(timeFilter);
+    TunerTestingConfigReader1_0::connectLiveBroadcast(live);
+    TunerTestingConfigReader1_0::connectScan(scan);
+    TunerTestingConfigReader1_0::connectDvrPlayback(playback);
+    TunerTestingConfigReader1_0::connectDvrRecord(record);
+    TunerTestingConfigReader1_0::connectDescrambling(descrambling);
+    TunerTestingConfigReader1_0::connectLnbLive(lnbLive);
+    TunerTestingConfigReader1_0::connectLnbRecord(lnbRecord);
+    TunerTestingConfigReader1_0::connectTimeFilter(timeFilter);
 };
 
 inline bool validateConnections() {
diff --git a/tv/tuner/1.1/vts/functional/Android.bp b/tv/tuner/1.1/vts/functional/Android.bp
index 92e587b..ac835a4 100644
--- a/tv/tuner/1.1/vts/functional/Android.bp
+++ b/tv/tuner/1.1/vts/functional/Android.bp
@@ -33,6 +33,15 @@
         "FrontendTests.cpp",
         "VtsHalTvTunerV1_1TargetTest.cpp",
     ],
+    generated_headers: [
+        "tuner_testing_dynamic_configuration_V1_0_enums",
+        "tuner_testing_dynamic_configuration_V1_0_parser",
+    ],
+    generated_sources: [
+        "tuner_testing_dynamic_configuration_V1_0_enums",
+        "tuner_testing_dynamic_configuration_V1_0_parser",
+    ],
+    header_libs: ["libxsdc-utils"],
     static_libs: [
         "android.hardware.cas@1.0",
         "android.hardware.cas@1.1",
@@ -48,9 +57,12 @@
     ],
     shared_libs: [
         "libbinder",
+        "libxml2",
     ],
     data: [
+        ":tuner_frontend_input_ts",
         ":tuner_frontend_input_es",
+        ":tuner_testing_dynamic_configuration_V1_0",
     ],
     test_suites: [
         "general-tests",
diff --git a/tv/tuner/1.1/vts/functional/FrontendTests.cpp b/tv/tuner/1.1/vts/functional/FrontendTests.cpp
index 0fd5be0..9c575ff 100644
--- a/tv/tuner/1.1/vts/functional/FrontendTests.cpp
+++ b/tv/tuner/1.1/vts/functional/FrontendTests.cpp
@@ -121,7 +121,7 @@
     mLockMsgReceived = false;
 }
 
-void FrontendCallback::scanTest(sp<IFrontend>& frontend, FrontendConfig config,
+void FrontendCallback::scanTest(sp<IFrontend>& frontend, FrontendConfig1_1 config,
                                 FrontendScanType type) {
     sp<android::hardware::tv::tuner::V1_1::IFrontend> frontend_1_1;
     frontend_1_1 = android::hardware::tv::tuner::V1_1::IFrontend::castFrom(frontend);
@@ -130,7 +130,7 @@
         return;
     }
 
-    uint32_t targetFrequency = getTargetFrequency(config.settings);
+    uint32_t targetFrequency = getTargetFrequency(config.config1_0.settings);
     if (type == FrontendScanType::SCAN_BLIND) {
         // reset the frequency in the scan configuration to test blind scan. The settings param of
         // passed in means the real input config on the transponder connected to the DUT.
@@ -139,7 +139,7 @@
         resetBlindScanStartingFrequency(config, targetFrequency - 100);
     }
 
-    Result result = frontend_1_1->scan_1_1(config.settings, type, config.settingsExt1_1);
+    Result result = frontend_1_1->scan_1_1(config.config1_0.settings, type, config.settingsExt1_1);
     EXPECT_TRUE(result == Result::SUCCESS);
 
     bool scanMsgLockedReceived = false;
@@ -159,7 +159,8 @@
     if (mScanMessageType != FrontendScanMessageType::END) {
         if (mScanMessageType == FrontendScanMessageType::LOCKED) {
             scanMsgLockedReceived = true;
-            Result result = frontend_1_1->scan_1_1(config.settings, type, config.settingsExt1_1);
+            Result result =
+                    frontend_1_1->scan_1_1(config.config1_0.settings, type, config.settingsExt1_1);
             EXPECT_TRUE(result == Result::SUCCESS);
         }
 
@@ -207,35 +208,35 @@
     }
 }
 
-void FrontendCallback::resetBlindScanStartingFrequency(FrontendConfig& config,
+void FrontendCallback::resetBlindScanStartingFrequency(FrontendConfig1_1& config,
                                                        uint32_t resetingFreq) {
-    switch (config.settings.getDiscriminator()) {
+    switch (config.config1_0.settings.getDiscriminator()) {
         case FrontendSettings::hidl_discriminator::analog:
-            config.settings.analog().frequency = resetingFreq;
+            config.config1_0.settings.analog().frequency = resetingFreq;
             break;
         case FrontendSettings::hidl_discriminator::atsc:
-            config.settings.atsc().frequency = resetingFreq;
+            config.config1_0.settings.atsc().frequency = resetingFreq;
             break;
         case FrontendSettings::hidl_discriminator::atsc3:
-            config.settings.atsc3().frequency = resetingFreq;
+            config.config1_0.settings.atsc3().frequency = resetingFreq;
             break;
         case FrontendSettings::hidl_discriminator::dvbc:
-            config.settings.dvbc().frequency = resetingFreq;
+            config.config1_0.settings.dvbc().frequency = resetingFreq;
             break;
         case FrontendSettings::hidl_discriminator::dvbs:
-            config.settings.dvbs().frequency = resetingFreq;
+            config.config1_0.settings.dvbs().frequency = resetingFreq;
             break;
         case FrontendSettings::hidl_discriminator::dvbt:
-            config.settings.dvbt().frequency = resetingFreq;
+            config.config1_0.settings.dvbt().frequency = resetingFreq;
             break;
         case FrontendSettings::hidl_discriminator::isdbs:
-            config.settings.isdbs().frequency = resetingFreq;
+            config.config1_0.settings.isdbs().frequency = resetingFreq;
             break;
         case FrontendSettings::hidl_discriminator::isdbs3:
-            config.settings.isdbs3().frequency = resetingFreq;
+            config.config1_0.settings.isdbs3().frequency = resetingFreq;
             break;
         case FrontendSettings::hidl_discriminator::isdbt:
-            config.settings.isdbt().frequency = resetingFreq;
+            config.config1_0.settings.isdbt().frequency = resetingFreq;
             break;
     }
 }
@@ -274,11 +275,11 @@
     return AssertionResult(callbackStatus.isOk());
 }
 
-AssertionResult FrontendTests::scanFrontend(FrontendConfig config, FrontendScanType type) {
+AssertionResult FrontendTests::scanFrontend(FrontendConfig1_1 config, FrontendScanType type) {
     EXPECT_TRUE(mFrontendCallback)
             << "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
 
-    EXPECT_TRUE(mFrontendInfo.type == config.type)
+    EXPECT_TRUE(mFrontendInfo.type == config.config1_0.type)
             << "FrontendConfig does not match the frontend info of the given id.";
 
     mFrontendCallback->scanTest(mFrontend, config, type);
@@ -426,14 +427,14 @@
     ASSERT_TRUE(status == Result::SUCCESS);
 }
 
-AssertionResult FrontendTests::tuneFrontend(FrontendConfig config, bool testWithDemux) {
+AssertionResult FrontendTests::tuneFrontend(FrontendConfig1_1 config, bool testWithDemux) {
     EXPECT_TRUE(mFrontendCallback)
             << "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
 
-    EXPECT_TRUE(mFrontendInfo.type == config.type)
+    EXPECT_TRUE(mFrontendInfo.type == config.config1_0.type)
             << "FrontendConfig does not match the frontend info of the given id.";
 
-    mIsSoftwareFe = config.isSoftwareFe;
+    mIsSoftwareFe = config.config1_0.isSoftwareFe;
     bool result = true;
     if (mIsSoftwareFe && testWithDemux) {
         result &= mDvrTests.openDvrInDemux(mDvrConfig.type, mDvrConfig.bufferSize) == success();
@@ -446,7 +447,7 @@
             return failure();
         }
     }
-    mFrontendCallback->tuneTestOnLock(mFrontend, config.settings, config.settingsExt1_1);
+    mFrontendCallback->tuneTestOnLock(mFrontend, config.config1_0.settings, config.settingsExt1_1);
     return AssertionResult(true);
 }
 
@@ -484,12 +485,9 @@
     feId = INVALID_ID;
 }
 
-void FrontendTests::tuneTest(FrontendConfig frontendConf) {
-    if (!frontendConf.enable) {
-        return;
-    }
+void FrontendTests::tuneTest(FrontendConfig1_1 frontendConf) {
     uint32_t feId;
-    getFrontendIdByType(frontendConf.type, feId);
+    getFrontendIdByType(frontendConf.config1_0.type, feId);
     ASSERT_TRUE(feId != INVALID_ID);
     ASSERT_TRUE(openFrontendById(feId));
     ASSERT_TRUE(setFrontendCallback());
@@ -503,12 +501,9 @@
     ASSERT_TRUE(closeFrontend());
 }
 
-void FrontendTests::scanTest(FrontendConfig frontendConf, FrontendScanType scanType) {
-    if (!frontendConf.enable) {
-        return;
-    }
+void FrontendTests::scanTest(FrontendConfig1_1 frontendConf, FrontendScanType scanType) {
     uint32_t feId;
-    getFrontendIdByType(frontendConf.type, feId);
+    getFrontendIdByType(frontendConf.config1_0.type, feId);
     ASSERT_TRUE(feId != INVALID_ID);
     ASSERT_TRUE(openFrontendById(feId));
     ASSERT_TRUE(setFrontendCallback());
diff --git a/tv/tuner/1.1/vts/functional/FrontendTests.h b/tv/tuner/1.1/vts/functional/FrontendTests.h
index 01d2007..3687389 100644
--- a/tv/tuner/1.1/vts/functional/FrontendTests.h
+++ b/tv/tuner/1.1/vts/functional/FrontendTests.h
@@ -79,11 +79,11 @@
 
     void tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings,
                         FrontendSettingsExt1_1 settingsExt1_1);
-    void scanTest(sp<IFrontend>& frontend, FrontendConfig config, FrontendScanType type);
+    void scanTest(sp<IFrontend>& frontend, FrontendConfig1_1 config, FrontendScanType type);
 
     // Helper methods
     uint32_t getTargetFrequency(FrontendSettings settings);
-    void resetBlindScanStartingFrequency(FrontendConfig& config, uint32_t resetingFreq);
+    void resetBlindScanStartingFrequency(FrontendConfig1_1& config, uint32_t resetingFreq);
 
   private:
     void readFrontendScanMessageExt1_1Modulation(FrontendModulation modulation);
@@ -114,9 +114,9 @@
     AssertionResult getFrontendInfo(uint32_t frontendId);
     AssertionResult openFrontendById(uint32_t frontendId);
     AssertionResult setFrontendCallback();
-    AssertionResult scanFrontend(FrontendConfig config, FrontendScanType type);
+    AssertionResult scanFrontend(FrontendConfig1_1 config, FrontendScanType type);
     AssertionResult stopScanFrontend();
-    AssertionResult tuneFrontend(FrontendConfig config, bool testWithDemux);
+    AssertionResult tuneFrontend(FrontendConfig1_1 config, bool testWithDemux);
     void verifyFrontendStatusExt1_1(vector<FrontendStatusTypeExt1_1> statusTypes,
                                     vector<FrontendStatusExt1_1> expectStatuses);
     AssertionResult stopTuneFrontend(bool testWithDemux);
@@ -127,8 +127,8 @@
     AssertionResult unlinkCiCam(uint32_t ciCamId);
 
     void getFrontendIdByType(FrontendType feType, uint32_t& feId);
-    void tuneTest(FrontendConfig frontendConf);
-    void scanTest(FrontendConfig frontend, FrontendScanType type);
+    void tuneTest(FrontendConfig1_1 frontendConf);
+    void scanTest(FrontendConfig1_1 frontend, FrontendScanType type);
     void getFrontendDtmbCapsTest();
 
     void setDvrTests(DvrTests dvrTests) { mDvrTests = dvrTests; }
diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
index 97fb90d..1080861 100644
--- a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
@@ -26,34 +26,31 @@
     return filterDataOutputTestBase(mFilterTests);
 }
 
-void TunerFilterHidlTest::configSingleFilterInDemuxTest(FilterConfig filterConf,
-                                                        FrontendConfig frontendConf) {
-    if (!frontendConf.enable) {
-        return;
-    }
-
+void TunerFilterHidlTest::configSingleFilterInDemuxTest(FilterConfig1_1 filterConf,
+                                                        FrontendConfig1_1 frontendConf) {
     uint32_t feId;
     uint32_t demuxId;
     sp<IDemux> demux;
     uint64_t filterId;
 
-    mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
+    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);
-    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
+    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.config1_0.type,
+                                               filterConf.config1_0.bufferSize));
     ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId));
-    ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
-    if (filterConf.type.mainType == DemuxFilterMainType::IP) {
+    ASSERT_TRUE(mFilterTests.configFilter(filterConf.config1_0.settings, filterId));
+    if (filterConf.config1_0.type.mainType == DemuxFilterMainType::IP) {
         ASSERT_TRUE(mFilterTests.configIpFilterCid(filterConf.ipCid, filterId));
     }
     if (filterConf.monitorEventTypes > 0) {
         ASSERT_TRUE(mFilterTests.configureMonitorEvent(filterId, filterConf.monitorEventTypes));
     }
-    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.getMqDesc));
+    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.config1_0.getMqDesc));
     ASSERT_TRUE(mFilterTests.startFilter(filterId));
     ASSERT_TRUE(mFilterTests.stopFilter(filterId));
     ASSERT_TRUE(mFilterTests.closeFilter(filterId));
@@ -61,19 +58,15 @@
     ASSERT_TRUE(mFrontendTests.closeFrontend());
 }
 
-void TunerFilterHidlTest::reconfigSingleFilterInDemuxTest(FilterConfig filterConf,
-                                                          FilterConfig filterReconf,
-                                                          FrontendConfig frontendConf) {
-    if (!frontendConf.enable) {
-        return;
-    }
-
+void TunerFilterHidlTest::reconfigSingleFilterInDemuxTest(FilterConfig1_1 filterConf,
+                                                          FilterConfig1_1 filterReconf,
+                                                          FrontendConfig1_1 frontendConf) {
     uint32_t feId;
     uint32_t demuxId;
     sp<IDemux> demux;
     uint64_t filterId;
 
-    mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
+    mFrontendTests.getFrontendIdByType(frontendConf.config1_0.type, feId);
     ASSERT_TRUE(feId != INVALID_ID);
     ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
     ASSERT_TRUE(mFrontendTests.setFrontendCallback());
@@ -81,13 +74,14 @@
     ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
     mFrontendTests.setDemux(demux);
     mFilterTests.setDemux(demux);
-    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
+    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.config1_0.type,
+                                               filterConf.config1_0.bufferSize));
     ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId));
-    ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
-    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.getMqDesc));
+    ASSERT_TRUE(mFilterTests.configFilter(filterConf.config1_0.settings, filterId));
+    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.config1_0.getMqDesc));
     ASSERT_TRUE(mFilterTests.startFilter(filterId));
     ASSERT_TRUE(mFilterTests.stopFilter(filterId));
-    ASSERT_TRUE(mFilterTests.configFilter(filterReconf.settings, filterId));
+    ASSERT_TRUE(mFilterTests.configFilter(filterReconf.config1_0.settings, filterId));
     ASSERT_TRUE(mFilterTests.startFilter(filterId));
     ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
     ASSERT_TRUE(mFilterTests.startIdTest(filterId));
@@ -98,18 +92,14 @@
     ASSERT_TRUE(mFrontendTests.closeFrontend());
 }
 
-void TunerBroadcastHidlTest::mediaFilterUsingSharedMemoryTest(FilterConfig filterConf,
-                                                              FrontendConfig frontendConf) {
-    if (!frontendConf.enable) {
-        return;
-    }
-
+void TunerBroadcastHidlTest::mediaFilterUsingSharedMemoryTest(FilterConfig1_1 filterConf,
+                                                              FrontendConfig1_1 frontendConf) {
     uint32_t feId;
     uint32_t demuxId;
     sp<IDemux> demux;
     uint64_t filterId;
 
-    mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
+    mFrontendTests.getFrontendIdByType(frontendConf.config1_0.type, feId);
     ASSERT_TRUE(feId != INVALID_ID);
     ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
     ASSERT_TRUE(mFrontendTests.setFrontendCallback());
@@ -117,12 +107,13 @@
     ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
     mFrontendTests.setDemux(demux);
     mFilterTests.setDemux(demux);
-    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
+    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.config1_0.type,
+                                               filterConf.config1_0.bufferSize));
     ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId));
     ASSERT_TRUE(mFilterTests.getSharedAvMemoryHandle(filterId));
-    ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
+    ASSERT_TRUE(mFilterTests.configFilter(filterConf.config1_0.settings, filterId));
     ASSERT_TRUE(mFilterTests.configAvFilterStreamType(filterConf.streamType, filterId));
-    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.getMqDesc));
+    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.config1_0.getMqDesc));
     ASSERT_TRUE(mFilterTests.startFilter(filterId));
     // tune test
     ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
@@ -135,19 +126,16 @@
     ASSERT_TRUE(mFrontendTests.closeFrontend());
 }
 
-void TunerRecordHidlTest::recordSingleFilterTest(FilterConfig filterConf,
-                                                 FrontendConfig frontendConf, DvrConfig dvrConf) {
-    if (!frontendConf.enable) {
-        return;
-    }
-
+void TunerRecordHidlTest::recordSingleFilterTest(FilterConfig1_1 filterConf,
+                                                 FrontendConfig1_1 frontendConf,
+                                                 DvrConfig dvrConf) {
     uint32_t feId;
     uint32_t demuxId;
     sp<IDemux> demux;
     uint64_t filterId;
     sp<IFilter> filter;
 
-    mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
+    mFrontendTests.getFrontendIdByType(frontendConf.config1_0.type, feId);
     ASSERT_TRUE(feId != INVALID_ID);
     ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
     ASSERT_TRUE(mFrontendTests.setFrontendCallback());
@@ -159,10 +147,11 @@
     ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type, dvrConf.bufferSize));
     ASSERT_TRUE(mDvrTests.configDvrRecord(dvrConf.settings));
     ASSERT_TRUE(mDvrTests.getDvrRecordMQDescriptor());
-    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
+    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.config1_0.type,
+                                               filterConf.config1_0.bufferSize));
     ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId));
-    ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
-    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.getMqDesc));
+    ASSERT_TRUE(mFilterTests.configFilter(filterConf.config1_0.settings, filterId));
+    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.config1_0.getMqDesc));
     filter = mFilterTests.getFilterById(filterId);
     ASSERT_TRUE(filter != nullptr);
     mDvrTests.startRecordOutputThread(dvrConf.settings.record());
@@ -186,41 +175,47 @@
 TEST_P(TunerFilterHidlTest, StartFilterInDemux) {
     description("Open and start a filter in Demux.");
     // TODO use parameterized tests
-    configSingleFilterInDemuxTest(filterArray[TS_VIDEO0], frontendArray[defaultFrontend]);
+    configSingleFilterInDemuxTest(filterMap[live.videoFilterId], frontendMap[live.frontendId]);
 }
 
 TEST_P(TunerFilterHidlTest, ConfigIpFilterInDemuxWithCid) {
     description("Open and configure an ip filter in Demux.");
     // TODO use parameterized tests
-    configSingleFilterInDemuxTest(filterArray[IP_IP0], frontendArray[defaultFrontend]);
+    if (live.ipFilterId.compare(emptyHardwareId) == 0) {
+        return;
+    }
+    configSingleFilterInDemuxTest(filterMap[live.ipFilterId], frontendMap[live.frontendId]);
 }
 
 TEST_P(TunerFilterHidlTest, ReconfigFilterToReceiveStartId) {
     description("Recofigure and restart a filter to test start id.");
     // TODO use parameterized tests
-    reconfigSingleFilterInDemuxTest(filterArray[TS_VIDEO0], filterArray[TS_VIDEO1],
-                                    frontendArray[defaultFrontend]);
+    reconfigSingleFilterInDemuxTest(filterMap[live.videoFilterId], filterMap[live.videoFilterId],
+                                    frontendMap[live.frontendId]);
 }
 
 TEST_P(TunerRecordHidlTest, RecordDataFlowWithTsRecordFilterTest) {
     description("Feed ts data from frontend to recording and test with ts record filter");
-    recordSingleFilterTest(filterArray[TS_RECORD0], frontendArray[defaultFrontend],
-                           dvrArray[DVR_RECORD0]);
+    if (!record.support) {
+        return;
+    }
+    recordSingleFilterTest(filterMap[record.recordFilterId], frontendMap[record.frontendId],
+                           dvrMap[record.dvrRecordId]);
 }
 
 TEST_P(TunerFrontendHidlTest, TuneFrontendWithFrontendSettingsExt1_1) {
     description("Tune one Frontend with v1_1 extended setting and check Lock event");
-    mFrontendTests.tuneTest(frontendArray[defaultFrontend]);
+    mFrontendTests.tuneTest(frontendMap[live.frontendId]);
 }
 
 TEST_P(TunerFrontendHidlTest, BlindScanFrontendWithEndFrequency) {
     description("Run an blind frontend scan with v1_1 extended setting and check lock scanMessage");
-    mFrontendTests.scanTest(frontendScanArray[defaultScanFrontend], FrontendScanType::SCAN_BLIND);
+    mFrontendTests.scanTest(frontendMap[scan.frontendId], FrontendScanType::SCAN_BLIND);
 }
 
 TEST_P(TunerBroadcastHidlTest, MediaFilterWithSharedMemoryHandle) {
     description("Test the Media Filter with shared memory handle");
-    mediaFilterUsingSharedMemoryTest(filterArray[TS_VIDEO0], frontendArray[defaultFrontend]);
+    mediaFilterUsingSharedMemoryTest(filterMap[live.videoFilterId], frontendMap[live.frontendId]);
 }
 
 TEST_P(TunerFrontendHidlTest, GetFrontendDtmbCaps) {
@@ -230,7 +225,10 @@
 
 TEST_P(TunerFrontendHidlTest, LinkToCiCam) {
     description("Test Frontend link to CiCam");
-    mFrontendTests.tuneTest(frontendArray[defaultFrontend]);
+    if (!frontendMap[live.frontendId].canConnectToCiCam) {
+        return;
+    }
+    mFrontendTests.tuneTest(frontendMap[live.frontendId]);
 }
 
 INSTANTIATE_TEST_SUITE_P(
diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h
index d14a2e8..863f649 100644
--- a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h
@@ -19,11 +19,20 @@
 
 namespace {
 
-void initConfiguration() {
+bool initConfiguration() {
+    TunerTestingConfigReader1_0::setConfigFilePath(configFilePath);
+    if (!TunerTestingConfigReader1_0::checkConfigFileExists()) {
+        return false;
+    }
     initFrontendConfig();
-    initFrontendScanConfig();
     initFilterConfig();
     initDvrConfig();
+    connectHardwaresToTestCases();
+    if (!validateConnections()) {
+        ALOGW("[vts] failed to validate connections.");
+        return false;
+    }
+    return true;
 }
 
 static AssertionResult success() {
@@ -57,9 +66,9 @@
         RecordProperty("description", description);
     }
 
-    void configSingleFilterInDemuxTest(FilterConfig filterConf, FrontendConfig frontendConf);
-    void reconfigSingleFilterInDemuxTest(FilterConfig filterConf, FilterConfig filterReconf,
-                                         FrontendConfig frontendConf);
+    void configSingleFilterInDemuxTest(FilterConfig1_1 filterConf, FrontendConfig1_1 frontendConf);
+    void reconfigSingleFilterInDemuxTest(FilterConfig1_1 filterConf, FilterConfig1_1 filterReconf,
+                                         FrontendConfig1_1 frontendConf);
     sp<ITuner> mService;
     FrontendTests mFrontendTests;
     DemuxTests mDemuxTests;
@@ -86,7 +95,7 @@
         RecordProperty("description", description);
     }
 
-    void recordSingleFilterTest(FilterConfig filterConf, FrontendConfig frontendConf,
+    void recordSingleFilterTest(FilterConfig1_1 filterConf, FrontendConfig1_1 frontendConf,
                                 DvrConfig dvrConf);
     AssertionResult filterDataOutputTest();
 
@@ -144,7 +153,8 @@
 
     AssertionResult filterDataOutputTest();
 
-    void mediaFilterUsingSharedMemoryTest(FilterConfig filterConf, FrontendConfig frontendConf);
+    void mediaFilterUsingSharedMemoryTest(FilterConfig1_1 filterConf,
+                                          FrontendConfig1_1 frontendConf);
 };
 
 // TODO remove from the allow list once the cf tv target is enabled for testing
diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h
index ad57849..390bd4c 100644
--- a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h
@@ -21,6 +21,8 @@
 #include <hidl/Status.h>
 #include <hidlmemory/FrameworkUtils.h>
 
+#include "../../../config/TunerTestingConfigReaderV1_1.h"
+
 using android::hardware::tv::tuner::V1_0::DataFormat;
 using android::hardware::tv::tuner::V1_0::DemuxAlpFilterType;
 using android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
@@ -46,104 +48,39 @@
 using android::hardware::tv::tuner::V1_0::FrontendType;
 using android::hardware::tv::tuner::V1_0::PlaybackSettings;
 using android::hardware::tv::tuner::V1_0::RecordSettings;
-using android::hardware::tv::tuner::V1_1::AudioStreamType;
-using android::hardware::tv::tuner::V1_1::AvStreamType;
-using android::hardware::tv::tuner::V1_1::FrontendSettingsExt1_1;
-using android::hardware::tv::tuner::V1_1::FrontendStatusExt1_1;
-using android::hardware::tv::tuner::V1_1::FrontendStatusTypeExt1_1;
-using android::hardware::tv::tuner::V1_1::VideoStreamType;
 
 using namespace std;
+using namespace android::media::tuner::testing::configuration::V1_0;
 
-const uint32_t FMQ_SIZE_512K = 0x80000;
-const uint32_t FMQ_SIZE_1M = 0x100000;
 const uint32_t FMQ_SIZE_4M = 0x400000;
 const uint32_t FMQ_SIZE_16M = 0x1000000;
 
-typedef enum {
-    TS_VIDEO0,
-    TS_VIDEO1,
-    TS_AUDIO0,
-    TS_AUDIO1,
-    TS_PES0,
-    TS_PCR0,
-    TS_SECTION0,
-    TS_TS0,
-    TS_RECORD0,
-    IP_IP0,
-    FILTER_MAX,
-} Filter;
+const string configFilePath = "/vendor/etc/tuner_vts_config_1_1.xml";
 
-typedef enum {
-    DVBT,
-    DVBS,
-    FRONTEND_MAX,
-} Frontend;
+// Hardware configs
+static map<string, FrontendConfig1_1> frontendMap;
+static map<string, FilterConfig1_1> filterMap;
+static map<string, DvrConfig> dvrMap;
 
-typedef enum {
-    SCAN_DVBT,
-    SCAN_MAX,
-} FrontendScan;
+// Hardware and test cases connections
+static LiveBroadcastHardwareConnections live;
+static ScanHardwareConnections scan;
+static DvrRecordHardwareConnections record;
 
-typedef enum {
-    DVR_RECORD0,
-    DVR_PLAYBACK0,
-    DVR_MAX,
-} Dvr;
-
-struct FilterConfig {
-    uint32_t bufferSize;
-    DemuxFilterType type;
-    DemuxFilterSettings settings;
-    bool getMqDesc;
-    AvStreamType streamType;
-    uint32_t ipCid;
-    uint32_t monitorEventTypes;
-
-    bool operator<(const FilterConfig& /*c*/) const { return false; }
-};
-
-struct FrontendConfig {
-    bool enable;
-    bool isSoftwareFe;
-    bool canConnectToCiCam;
-    uint32_t ciCamId;
-    FrontendType type;
-    FrontendSettings settings;
-    FrontendSettingsExt1_1 settingsExt1_1;
-    vector<FrontendStatusTypeExt1_1> tuneStatusTypes;
-    vector<FrontendStatusExt1_1> expectTuneStatuses;
-};
-
-struct DvrConfig {
-    DvrType type;
-    uint32_t bufferSize;
-    DvrSettings settings;
-    string playbackInputFile;
-};
-
-static FrontendConfig frontendArray[FILTER_MAX];
-static FrontendConfig frontendScanArray[SCAN_MAX];
-static FilterConfig filterArray[FILTER_MAX];
-static DvrConfig dvrArray[DVR_MAX];
-static int defaultFrontend = DVBT;
-static int defaultScanFrontend = SCAN_DVBT;
-
-/** Configuration array for the frontend tune test */
+/** Config all the frontends that would be used in the tests */
 inline void initFrontendConfig() {
+    // The test will use the internal default fe when default fe is connected to any data flow
+    // without overriding in the xml config.
+    string defaultFeId = "FE_DEFAULT";
     FrontendDvbtSettings dvbtSettings{
             .frequency = 578000,
             .transmissionMode = FrontendDvbtTransmissionMode::AUTO,
             .bandwidth = FrontendDvbtBandwidth::BANDWIDTH_8MHZ,
-            .constellation = FrontendDvbtConstellation::AUTO,
-            .hierarchy = FrontendDvbtHierarchy::AUTO,
-            .hpCoderate = FrontendDvbtCoderate::AUTO,
-            .lpCoderate = FrontendDvbtCoderate::AUTO,
-            .guardInterval = FrontendDvbtGuardInterval::AUTO,
             .isHighPriority = true,
-            .standard = FrontendDvbtStandard::T,
     };
-    frontendArray[DVBT].type = FrontendType::DVBT, frontendArray[DVBT].settings.dvbt(dvbtSettings);
+    frontendMap[defaultFeId].config1_0.type = FrontendType::DVBT;
+    frontendMap[defaultFeId].config1_0.settings.dvbt(dvbtSettings);
+
     vector<FrontendStatusTypeExt1_1> types;
     types.push_back(FrontendStatusTypeExt1_1::UEC);
     types.push_back(FrontendStatusTypeExt1_1::IS_MISO);
@@ -153,147 +90,97 @@
     statuses.push_back(status);
     status.isMiso(true);
     statuses.push_back(status);
-
-    frontendArray[DVBT].tuneStatusTypes = types;
-    frontendArray[DVBT].expectTuneStatuses = statuses;
-    frontendArray[DVBT].isSoftwareFe = true;
-    frontendArray[DVBT].canConnectToCiCam = true;
-    frontendArray[DVBT].ciCamId = 0;
-    frontendArray[DVBT].settingsExt1_1.settingExt.dvbt({
+    frontendMap[defaultFeId].tuneStatusTypes = types;
+    frontendMap[defaultFeId].expectTuneStatuses = statuses;
+    frontendMap[defaultFeId].config1_0.isSoftwareFe = true;
+    frontendMap[defaultFeId].canConnectToCiCam = true;
+    frontendMap[defaultFeId].ciCamId = 0;
+    frontendMap[defaultFeId].settingsExt1_1.settingExt.dvbt({
             .transmissionMode =
                     android::hardware::tv::tuner::V1_1::FrontendDvbtTransmissionMode::MODE_8K_E,
     });
-    frontendArray[DVBT].enable = true;
-    frontendArray[DVBS].type = FrontendType::DVBS;
-    frontendArray[DVBS].isSoftwareFe = true;
-    frontendArray[DVBS].enable = true;
+    // Read customized config
+    TunerTestingConfigReader1_1::readFrontendConfig1_1(frontendMap);
 };
 
-/** Configuration array for the frontend scan test */
-inline void initFrontendScanConfig() {
-    frontendScanArray[SCAN_DVBT].type = FrontendType::DVBT;
-    frontendScanArray[SCAN_DVBT].settings.dvbt({
-            .frequency = 578000,
-            .transmissionMode = FrontendDvbtTransmissionMode::MODE_8K,
-            .bandwidth = FrontendDvbtBandwidth::BANDWIDTH_8MHZ,
-            .constellation = FrontendDvbtConstellation::AUTO,
-            .hierarchy = FrontendDvbtHierarchy::AUTO,
-            .hpCoderate = FrontendDvbtCoderate::AUTO,
-            .lpCoderate = FrontendDvbtCoderate::AUTO,
-            .guardInterval = FrontendDvbtGuardInterval::AUTO,
-            .isHighPriority = true,
-            .standard = FrontendDvbtStandard::T,
-    });
-    frontendScanArray[SCAN_DVBT].settingsExt1_1.endFrequency = 800000;
-    frontendScanArray[SCAN_DVBT].settingsExt1_1.settingExt.dvbt({
-            .transmissionMode =
-                    android::hardware::tv::tuner::V1_1::FrontendDvbtTransmissionMode::MODE_8K_E,
-    });
-};
-
-/** Configuration array for the filter test */
 inline void initFilterConfig() {
-    // TS VIDEO filter setting for default implementation testing
-    filterArray[TS_VIDEO0].type.mainType = DemuxFilterMainType::TS;
-    filterArray[TS_VIDEO0].type.subType.tsFilterType(DemuxTsFilterType::VIDEO);
-    filterArray[TS_VIDEO0].bufferSize = FMQ_SIZE_16M;
-    filterArray[TS_VIDEO0].settings.ts().tpid = 256;
-    filterArray[TS_VIDEO0].settings.ts().filterSettings.av({.isPassthrough = false});
-    filterArray[TS_VIDEO0].monitorEventTypes =
+    // The test will use the internal default filter when default filter is connected to any
+    // data flow without overriding in the xml config.
+    string defaultAudioFilterId = "FILTER_AUDIO_DEFAULT";
+    string defaultVideoFilterId = "FILTER_VIDEO_DEFAULT";
+
+    filterMap[defaultVideoFilterId].config1_0.type.mainType = DemuxFilterMainType::TS;
+    filterMap[defaultVideoFilterId].config1_0.type.subType.tsFilterType(DemuxTsFilterType::VIDEO);
+    filterMap[defaultVideoFilterId].config1_0.bufferSize = FMQ_SIZE_16M;
+    filterMap[defaultVideoFilterId].config1_0.settings.ts().tpid = 256;
+    filterMap[defaultVideoFilterId].config1_0.settings.ts().filterSettings.av(
+            {.isPassthrough = false});
+    filterMap[defaultVideoFilterId].monitorEventTypes =
             android::hardware::tv::tuner::V1_1::DemuxFilterMonitorEventType::SCRAMBLING_STATUS |
             android::hardware::tv::tuner::V1_1::DemuxFilterMonitorEventType::IP_CID_CHANGE;
-    filterArray[TS_VIDEO1].type.mainType = DemuxFilterMainType::TS;
-    filterArray[TS_VIDEO1].type.subType.tsFilterType(DemuxTsFilterType::VIDEO);
-    filterArray[TS_VIDEO1].bufferSize = FMQ_SIZE_16M;
-    filterArray[TS_VIDEO1].settings.ts().tpid = 256;
-    filterArray[TS_VIDEO1].settings.ts().filterSettings.av({.isPassthrough = false});
-    filterArray[TS_VIDEO1].streamType.video(VideoStreamType::MPEG1);
-    // TS AUDIO filter setting
-    filterArray[TS_AUDIO0].type.mainType = DemuxFilterMainType::TS;
-    filterArray[TS_AUDIO0].type.subType.tsFilterType(DemuxTsFilterType::AUDIO);
-    filterArray[TS_AUDIO0].bufferSize = FMQ_SIZE_16M;
-    filterArray[TS_AUDIO0].settings.ts().tpid = 256;
-    filterArray[TS_AUDIO0].settings.ts().filterSettings.av({.isPassthrough = false});
-    filterArray[TS_AUDIO1].type.mainType = DemuxFilterMainType::TS;
-    filterArray[TS_AUDIO1].type.subType.tsFilterType(DemuxTsFilterType::AUDIO);
-    filterArray[TS_AUDIO1].bufferSize = FMQ_SIZE_16M;
-    filterArray[TS_AUDIO1].settings.ts().tpid = 257;
-    filterArray[TS_AUDIO1].settings.ts().filterSettings.av({.isPassthrough = false});
-    filterArray[TS_VIDEO1].streamType.audio(AudioStreamType::MP3);
-    // TS PES filter setting
-    filterArray[TS_PES0].type.mainType = DemuxFilterMainType::TS;
-    filterArray[TS_PES0].type.subType.tsFilterType(DemuxTsFilterType::PES);
-    filterArray[TS_PES0].bufferSize = FMQ_SIZE_16M;
-    filterArray[TS_PES0].settings.ts().tpid = 256;
-    filterArray[TS_PES0].settings.ts().filterSettings.pesData({
-            .isRaw = false,
-            .streamId = 0xbd,
-    });
-    filterArray[TS_PES0].getMqDesc = true;
-    // TS PCR filter setting
-    filterArray[TS_PCR0].type.mainType = DemuxFilterMainType::TS;
-    filterArray[TS_PCR0].type.subType.tsFilterType(DemuxTsFilterType::PCR);
-    filterArray[TS_PCR0].bufferSize = FMQ_SIZE_16M;
-    filterArray[TS_PCR0].settings.ts().tpid = 256;
-    filterArray[TS_PCR0].settings.ts().filterSettings.noinit();
-    // TS filter setting
-    filterArray[TS_TS0].type.mainType = DemuxFilterMainType::TS;
-    filterArray[TS_TS0].type.subType.tsFilterType(DemuxTsFilterType::TS);
-    filterArray[TS_TS0].bufferSize = FMQ_SIZE_16M;
-    filterArray[TS_TS0].settings.ts().tpid = 256;
-    filterArray[TS_TS0].settings.ts().filterSettings.noinit();
-    // TS SECTION filter setting
-    filterArray[TS_SECTION0].type.mainType = DemuxFilterMainType::TS;
-    filterArray[TS_SECTION0].type.subType.tsFilterType(DemuxTsFilterType::SECTION);
-    filterArray[TS_SECTION0].bufferSize = FMQ_SIZE_16M;
-    filterArray[TS_SECTION0].settings.ts().tpid = 256;
-    filterArray[TS_SECTION0].settings.ts().filterSettings.section({
-            .isRaw = false,
-    });
-    filterArray[TS_SECTION0].getMqDesc = true;
-    // TS RECORD filter setting
-    filterArray[TS_RECORD0].type.mainType = DemuxFilterMainType::TS;
-    filterArray[TS_RECORD0].type.subType.tsFilterType(DemuxTsFilterType::RECORD);
-    filterArray[TS_RECORD0].settings.ts().tpid = 256;
-    filterArray[TS_RECORD0].settings.ts().filterSettings.record({
-            .scIndexType = DemuxRecordScIndexType::NONE,
-    });
-    // IP filter setting
-    filterArray[IP_IP0].type.mainType = DemuxFilterMainType::IP;
-    filterArray[IP_IP0].type.subType.ipFilterType(DemuxIpFilterType::IP);
-    uint8_t src[4] = {192, 168, 1, 1};
-    uint8_t dest[4] = {192, 168, 1, 2};
-    DemuxIpAddress ipAddress;
-    ipAddress.srcIpAddress.v4(src);
-    ipAddress.dstIpAddress.v4(dest);
-    DemuxIpFilterSettings ipSettings{
-            .ipAddr = ipAddress,
-    };
-    filterArray[IP_IP0].settings.ip(ipSettings);
-    filterArray[IP_IP0].ipCid = 1;
+    filterMap[defaultVideoFilterId].streamType.video(VideoStreamType::MPEG1);
+
+    filterMap[defaultAudioFilterId].config1_0.type.mainType = DemuxFilterMainType::TS;
+    filterMap[defaultAudioFilterId].config1_0.type.subType.tsFilterType(DemuxTsFilterType::AUDIO);
+    filterMap[defaultAudioFilterId].config1_0.bufferSize = FMQ_SIZE_16M;
+    filterMap[defaultAudioFilterId].config1_0.settings.ts().tpid = 256;
+    filterMap[defaultAudioFilterId].config1_0.settings.ts().filterSettings.av(
+            {.isPassthrough = false});
+    filterMap[defaultAudioFilterId].monitorEventTypes =
+            android::hardware::tv::tuner::V1_1::DemuxFilterMonitorEventType::SCRAMBLING_STATUS |
+            android::hardware::tv::tuner::V1_1::DemuxFilterMonitorEventType::IP_CID_CHANGE;
+    filterMap[defaultAudioFilterId].streamType.audio(AudioStreamType::MP3);
+    // Read customized config
+    TunerTestingConfigReader1_1::readFilterConfig1_1(filterMap);
 };
 
-/** Configuration array for the dvr test */
+/** Config all the dvrs that would be used in the tests */
 inline void initDvrConfig() {
-    RecordSettings recordSettings{
-            .statusMask = 0xf,
-            .lowThreshold = 0x1000,
-            .highThreshold = 0x07fff,
-            .dataFormat = DataFormat::TS,
-            .packetSize = 188,
-    };
-    dvrArray[DVR_RECORD0].type = DvrType::RECORD;
-    dvrArray[DVR_RECORD0].bufferSize = FMQ_SIZE_4M;
-    dvrArray[DVR_RECORD0].settings.record(recordSettings);
-    PlaybackSettings playbackSettings{
-            .statusMask = 0xf,
-            .lowThreshold = 0x1000,
-            .highThreshold = 0x07fff,
-            .dataFormat = DataFormat::TS,
-            .packetSize = 188,
-    };
-    dvrArray[DVR_PLAYBACK0].type = DvrType::PLAYBACK;
-    dvrArray[DVR_PLAYBACK0].playbackInputFile = "/data/local/tmp/segment000000.ts";
-    dvrArray[DVR_PLAYBACK0].bufferSize = FMQ_SIZE_4M;
-    dvrArray[DVR_PLAYBACK0].settings.playback(playbackSettings);
+    // Read customized config
+    TunerTestingConfigReader1_0::readDvrConfig1_0(dvrMap);
 };
+
+/** Read the vendor configurations of which hardware to use for each test cases/data flows */
+inline void connectHardwaresToTestCases() {
+    TunerTestingConfigReader1_0::connectLiveBroadcast(live);
+    TunerTestingConfigReader1_0::connectScan(scan);
+    TunerTestingConfigReader1_0::connectDvrRecord(record);
+};
+
+inline bool validateConnections() {
+    bool feIsValid = frontendMap.find(live.frontendId) != frontendMap.end() &&
+                     frontendMap.find(scan.frontendId) != frontendMap.end();
+    feIsValid &= record.support ? frontendMap.find(record.frontendId) != frontendMap.end() : true;
+
+    if (!feIsValid) {
+        ALOGW("[vts config] dynamic config fe connection is invalid.");
+        return false;
+    }
+
+    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();
+        }
+        dvrIsValid &= dvrMap.find(record.dvrRecordId) != dvrMap.end();
+    }
+
+    if (!dvrIsValid) {
+        ALOGW("[vts config] dynamic config dvr connection is invalid.");
+        return false;
+    }
+
+    bool filterIsValid = filterMap.find(live.audioFilterId) != filterMap.end() &&
+                         filterMap.find(live.videoFilterId) != filterMap.end();
+    filterIsValid &=
+            record.support ? filterMap.find(record.recordFilterId) != filterMap.end() : true;
+
+    if (!filterIsValid) {
+        ALOGW("[vts config] dynamic config filter connection is invalid.");
+        return false;
+    }
+
+    return true;
+}
diff --git a/tv/tuner/config/TunerTestingConfigReader.h b/tv/tuner/config/TunerTestingConfigReaderV1_0.h
similarity index 84%
rename from tv/tuner/config/TunerTestingConfigReader.h
rename to tv/tuner/config/TunerTestingConfigReaderV1_0.h
index 90499c4..cff4af1 100644
--- a/tv/tuner/config/TunerTestingConfigReader.h
+++ b/tv/tuner/config/TunerTestingConfigReaderV1_0.h
@@ -36,6 +36,8 @@
 using android::hardware::tv::tuner::V1_0::DemuxFilterSectionSettings;
 using android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
 using android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxIpAddress;
+using android::hardware::tv::tuner::V1_0::DemuxIpFilterSettings;
 using android::hardware::tv::tuner::V1_0::DemuxIpFilterType;
 using android::hardware::tv::tuner::V1_0::DemuxMmtpFilterType;
 using android::hardware::tv::tuner::V1_0::DemuxRecordScIndexType;
@@ -63,9 +65,10 @@
 using android::hardware::tv::tuner::V1_0::PlaybackSettings;
 using android::hardware::tv::tuner::V1_0::RecordSettings;
 
-const string configFilePath = "/vendor/etc/tuner_vts_config.xml";
 const string emptyHardwareId = "";
 
+static string mConfigFilePath;
+
 #define PROVISION_STR                                      \
     "{                                                   " \
     "  \"id\": 21140844,                                 " \
@@ -125,6 +128,7 @@
     string audioFilterId;
     string videoFilterId;
     string sectionFilterId;
+    string ipFilterId;
     string pcrFilterId;
     /* list string of extra filters; */
 };
@@ -186,14 +190,17 @@
     string timeFilterId;
 };
 
-struct TunerTestingConfigReader {
+struct TunerTestingConfigReader1_0 {
   public:
+    static void setConfigFilePath(string path) { mConfigFilePath = path; }
+
     static bool checkConfigFileExists() {
-        auto res = read(configFilePath.c_str());
+        auto res = read(mConfigFilePath.c_str());
         if (res == nullopt) {
-            ALOGW("[ConfigReader] Couldn't read /vendor/etc/tuner_vts_config.xml."
+            ALOGW("[ConfigReader] Couldn't read %s."
                   "Please check tuner_testing_dynamic_configuration.xsd"
-                  "and sample_tuner_vts_config.xml for more details on how to config Tune VTS.");
+                  "and sample_tuner_vts_config.xml for more details on how to config Tune VTS.",
+                  mConfigFilePath.c_str());
         }
         return (res != nullopt);
     }
@@ -413,6 +420,11 @@
         if (liveConfig.hasDvrSoftwareFeConnection()) {
             live.dvrSoftwareFeId = liveConfig.getDvrSoftwareFeConnection();
         }
+        if (liveConfig.hasIpFilterConnection()) {
+            live.ipFilterId = liveConfig.getIpFilterConnection();
+        } else {
+            live.ipFilterId = emptyHardwareId;
+        }
     }
 
     static void connectScan(ScanHardwareConnections& scan) {
@@ -520,6 +532,10 @@
         timeFilter.timeFilterId = timeFilterConfig.getTimeFilterConnection();
     }
 
+    static HardwareConfiguration getHardwareConfig() {
+        return *getTunerConfig().getFirstHardwareConfiguration();
+    }
+
   private:
     static FrontendDvbtSettings readDvbtFrontendSettings(Frontend feConfig) {
         ALOGW("[ConfigReader] fe type is dvbt");
@@ -530,12 +546,17 @@
             ALOGW("[ConfigReader] no more dvbt settings");
             return dvbtSettings;
         }
-        dvbtSettings.transmissionMode = static_cast<FrontendDvbtTransmissionMode>(
-                feConfig.getFirstDvbtFrontendSettings_optional()->getTransmissionMode());
-        dvbtSettings.bandwidth = static_cast<FrontendDvbtBandwidth>(
-                feConfig.getFirstDvbtFrontendSettings_optional()->getBandwidth());
-        dvbtSettings.isHighPriority =
-                feConfig.getFirstDvbtFrontendSettings_optional()->getIsHighPriority();
+        auto dvbt = feConfig.getFirstDvbtFrontendSettings_optional();
+        uint32_t trans = static_cast<uint32_t>(dvbt->getTransmissionMode());
+        if (trans <= (uint32_t)FrontendDvbtTransmissionMode::MODE_32K) {
+            dvbtSettings.transmissionMode = static_cast<FrontendDvbtTransmissionMode>(trans);
+        }
+        dvbtSettings.bandwidth = static_cast<FrontendDvbtBandwidth>(dvbt->getBandwidth());
+        dvbtSettings.isHighPriority = dvbt->getIsHighPriority();
+        if (dvbt->hasConstellation()) {
+            dvbtSettings.constellation =
+                    static_cast<FrontendDvbtConstellation>(dvbt->getConstellation());
+        }
         return dvbtSettings;
     }
 
@@ -559,13 +580,13 @@
                                           DemuxFilterSettings& settings) {
         auto mainType = filterConfig.getMainType();
         auto subType = filterConfig.getSubType();
-        uint32_t pid = static_cast<uint32_t>(filterConfig.getPid());
         switch (mainType) {
             case FilterMainTypeEnum::TS: {
                 ALOGW("[ConfigReader] filter main type is ts");
                 type.mainType = DemuxFilterMainType::TS;
                 switch (subType) {
                     case FilterSubTypeEnum::UNDEFINED:
+                        type.subType.tsFilterType(DemuxTsFilterType::UNDEFINED);
                         break;
                     case FilterSubTypeEnum::SECTION:
                         type.subType.tsFilterType(DemuxTsFilterType::SECTION);
@@ -606,7 +627,9 @@
                         ALOGW("[ConfigReader] ts subtype is not supported");
                         return false;
                 }
-                settings.ts().tpid = pid;
+                if (filterConfig.hasPid()) {
+                    settings.ts().tpid = static_cast<uint32_t>(filterConfig.getPid());
+                }
                 break;
             }
             case FilterMainTypeEnum::MMTP: {
@@ -614,6 +637,7 @@
                 type.mainType = DemuxFilterMainType::MMTP;
                 switch (subType) {
                     case FilterSubTypeEnum::UNDEFINED:
+                        type.subType.mmtpFilterType(DemuxMmtpFilterType::UNDEFINED);
                         break;
                     case FilterSubTypeEnum::SECTION:
                         type.subType.mmtpFilterType(DemuxMmtpFilterType::SECTION);
@@ -652,7 +676,47 @@
                         ALOGW("[ConfigReader] mmtp subtype is not supported");
                         return false;
                 }
-                settings.mmtp().mmtpPid = pid;
+                if (filterConfig.hasPid()) {
+                    settings.mmtp().mmtpPid = static_cast<uint32_t>(filterConfig.getPid());
+                }
+                break;
+            }
+            case FilterMainTypeEnum::IP: {
+                ALOGW("[ConfigReader] filter main type is ip");
+                type.mainType = DemuxFilterMainType::IP;
+                switch (subType) {
+                    case FilterSubTypeEnum::UNDEFINED:
+                        type.subType.ipFilterType(DemuxIpFilterType::UNDEFINED);
+                        break;
+                    case FilterSubTypeEnum::SECTION:
+                        type.subType.ipFilterType(DemuxIpFilterType::SECTION);
+                        settings.ip().filterSettings.section(
+                                readSectionFilterSettings(filterConfig));
+                        break;
+                    case FilterSubTypeEnum::NTP:
+                        type.subType.ipFilterType(DemuxIpFilterType::NTP);
+                        settings.ip().filterSettings.noinit();
+                        break;
+                    case FilterSubTypeEnum::IP: {
+                        DemuxIpFilterSettings ip{
+                                .ipAddr = readIpAddress(filterConfig),
+                        };
+                        ip.filterSettings.bPassthrough(readPassthroughSettings(filterConfig));
+                        settings.ip(ip);
+                        break;
+                    }
+                    case FilterSubTypeEnum::IP_PAYLOAD:
+                        type.subType.ipFilterType(DemuxIpFilterType::IP_PAYLOAD);
+                        settings.ip().filterSettings.noinit();
+                        break;
+                    case FilterSubTypeEnum::PAYLOAD_THROUGH:
+                        type.subType.ipFilterType(DemuxIpFilterType::PAYLOAD_THROUGH);
+                        settings.ip().filterSettings.noinit();
+                        break;
+                    default:
+                        ALOGW("[ConfigReader] mmtp subtype is not supported");
+                        return false;
+                }
                 break;
             }
             default:
@@ -663,6 +727,46 @@
         return true;
     }
 
+    static DemuxIpAddress readIpAddress(Filter filterConfig) {
+        DemuxIpAddress ipAddress;
+        if (!filterConfig.hasIpFilterConfig_optional()) {
+            return ipAddress;
+        }
+        auto ipFilterConfig = filterConfig.getFirstIpFilterConfig_optional();
+        if (ipFilterConfig->hasSrcPort()) {
+            ipAddress.srcPort = ipFilterConfig->getSrcPort();
+        }
+        if (ipFilterConfig->hasDestPort()) {
+            ipAddress.dstPort = ipFilterConfig->getDestPort();
+        }
+        if (ipFilterConfig->getFirstSrcIpAddress()->getIsIpV4()) {
+            memcpy(ipAddress.srcIpAddress.v4().data(),
+                   ipFilterConfig->getFirstSrcIpAddress()->getIp().data(), 4);
+        } else {
+            memcpy(ipAddress.srcIpAddress.v6().data(),
+                   ipFilterConfig->getFirstSrcIpAddress()->getIp().data(), 6);
+        }
+        if (ipFilterConfig->getFirstDestIpAddress()->getIsIpV4()) {
+            memcpy(ipAddress.dstIpAddress.v4().data(),
+                   ipFilterConfig->getFirstDestIpAddress()->getIp().data(), 4);
+        } else {
+            memcpy(ipAddress.dstIpAddress.v6().data(),
+                   ipFilterConfig->getFirstDestIpAddress()->getIp().data(), 6);
+        }
+        return ipAddress;
+    }
+
+    static bool readPassthroughSettings(Filter filterConfig) {
+        if (!filterConfig.hasIpFilterConfig_optional()) {
+            return false;
+        }
+        auto ipFilterConfig = filterConfig.getFirstIpFilterConfig_optional();
+        if (ipFilterConfig->hasDataPassthrough()) {
+            return ipFilterConfig->getDataPassthrough();
+        }
+        return false;
+    }
+
     static DemuxFilterSectionSettings readSectionFilterSettings(Filter filterConfig) {
         DemuxFilterSectionSettings settings;
         if (!filterConfig.hasSectionFilterSettings_optional()) {
@@ -720,11 +824,7 @@
         return recordSettings;
     }
 
-    static TunerConfiguration getTunerConfig() { return *read(configFilePath.c_str()); }
-
-    static HardwareConfiguration getHardwareConfig() {
-        return *getTunerConfig().getFirstHardwareConfiguration();
-    }
+    static TunerConfiguration getTunerConfig() { return *read(mConfigFilePath.c_str()); }
 
     static DataFlowConfiguration getDataFlowConfiguration() {
         return *getTunerConfig().getFirstDataFlowConfiguration();
diff --git a/tv/tuner/config/TunerTestingConfigReaderV1_1.h b/tv/tuner/config/TunerTestingConfigReaderV1_1.h
new file mode 100644
index 0000000..13d5303
--- /dev/null
+++ b/tv/tuner/config/TunerTestingConfigReaderV1_1.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include "TunerTestingConfigReaderV1_0.h"
+
+using android::hardware::tv::tuner::V1_1::AudioStreamType;
+using android::hardware::tv::tuner::V1_1::AvStreamType;
+using android::hardware::tv::tuner::V1_1::FrontendDvbsScanType;
+using android::hardware::tv::tuner::V1_1::FrontendDvbsSettingsExt1_1;
+using android::hardware::tv::tuner::V1_1::FrontendDvbtSettingsExt1_1;
+using android::hardware::tv::tuner::V1_1::FrontendSettingsExt1_1;
+using android::hardware::tv::tuner::V1_1::FrontendStatusExt1_1;
+using android::hardware::tv::tuner::V1_1::FrontendStatusTypeExt1_1;
+using android::hardware::tv::tuner::V1_1::VideoStreamType;
+
+struct FrontendConfig1_1 {
+    FrontendConfig config1_0;
+    bool canConnectToCiCam;
+    uint32_t ciCamId;
+    FrontendSettingsExt1_1 settingsExt1_1;
+    vector<FrontendStatusTypeExt1_1> tuneStatusTypes;
+    vector<FrontendStatusExt1_1> expectTuneStatuses;
+};
+
+struct FilterConfig1_1 {
+    FilterConfig config1_0;
+    AvStreamType streamType;
+    uint32_t ipCid;
+    uint32_t monitorEventTypes;
+
+    bool operator<(const FilterConfig& /*c*/) const { return false; }
+};
+
+struct TunerTestingConfigReader1_1 {
+  public:
+    static void readFrontendConfig1_1(map<string, FrontendConfig1_1>& frontendMap) {
+        map<string, FrontendConfig> frontendMap1_0;
+        TunerTestingConfigReader1_0::readFrontendConfig1_0(frontendMap1_0);
+        for (auto it = frontendMap1_0.begin(); it != frontendMap1_0.end(); it++) {
+            frontendMap[it->first].config1_0 = it->second;
+        }
+
+        auto hardwareConfig = TunerTestingConfigReader1_0::getHardwareConfig();
+        if (hardwareConfig.hasFrontends()) {
+            // TODO: b/182519645 complete the tune status config
+            vector<FrontendStatusTypeExt1_1> types;
+            types.push_back(FrontendStatusTypeExt1_1::UEC);
+            types.push_back(FrontendStatusTypeExt1_1::IS_MISO);
+            vector<FrontendStatusExt1_1> statuses;
+            FrontendStatusExt1_1 status;
+            status.uec(4);
+            statuses.push_back(status);
+            status.isMiso(true);
+            statuses.push_back(status);
+
+            auto frontends = *hardwareConfig.getFirstFrontends();
+
+            for (auto feConfig : frontends.getFrontend()) {
+                string id = feConfig.getId();
+                switch (feConfig.getType()) {
+                    case FrontendTypeEnum::DVBS:
+                        frontendMap[id].settingsExt1_1.settingExt.dvbs(
+                                readDvbsFrontendSettings1_1(feConfig));
+                        break;
+                    case FrontendTypeEnum::DVBT: {
+                        frontendMap[id].settingsExt1_1.settingExt.dvbt(
+                                readDvbtFrontendSettings1_1(feConfig));
+                        break;
+                    }
+                    case FrontendTypeEnum::DTMB:
+                        frontendMap[id].config1_0.type = static_cast<FrontendType>(
+                                android::hardware::tv::tuner::V1_1::FrontendType::DTMB);
+                        break;
+                    case FrontendTypeEnum::UNKNOWN:
+                        ALOGW("[ConfigReader] invalid frontend type");
+                        return;
+                    default:
+                        ALOGW("[ConfigReader] fe already handled in 1_0 reader.");
+                        break;
+                }
+                if (feConfig.hasEndFrequency()) {
+                    frontendMap[id].settingsExt1_1.endFrequency =
+                            (uint32_t)feConfig.getEndFrequency();
+                }
+                // TODO: b/182519645 complete the tune status config
+                frontendMap[id].tuneStatusTypes = types;
+                frontendMap[id].expectTuneStatuses = statuses;
+                getCiCamInfo(feConfig, frontendMap[id].canConnectToCiCam, frontendMap[id].ciCamId);
+            }
+        }
+    }
+
+    static void readFilterConfig1_1(map<string, FilterConfig1_1>& filterMap) {
+        map<string, FilterConfig> filterMap1_0;
+        TunerTestingConfigReader1_0::readFilterConfig1_0(filterMap1_0);
+        for (auto it = filterMap1_0.begin(); it != filterMap1_0.end(); it++) {
+            filterMap[it->first].config1_0 = it->second;
+        }
+        auto hardwareConfig = TunerTestingConfigReader1_0::getHardwareConfig();
+        if (hardwareConfig.hasFilters()) {
+            auto filters = *hardwareConfig.getFirstFilters();
+            for (auto filterConfig : filters.getFilter()) {
+                string id = filterConfig.getId();
+                if (filterConfig.hasMonitorEventTypes()) {
+                    filterMap[id].monitorEventTypes = (uint32_t)filterConfig.getMonitorEventTypes();
+                }
+                if (filterConfig.hasAvFilterSettings_optional()) {
+                    AvStreamType type;
+                    auto av = filterConfig.getFirstAvFilterSettings_optional();
+                    if (av->hasAudioStreamType_optional()) {
+                        type.audio(static_cast<AudioStreamType>(av->getAudioStreamType_optional()));
+                        filterMap[id].streamType = type;
+                    }
+                    if (av->hasVideoStreamType_optional()) {
+                        type.video(static_cast<VideoStreamType>(av->getVideoStreamType_optional()));
+                        filterMap[id].streamType = type;
+                    }
+                }
+                if (filterConfig.hasIpFilterConfig_optional()) {
+                    auto ip = filterConfig.getFirstIpFilterConfig_optional();
+                    if (ip->hasIpCid()) {
+                        filterMap[id].ipCid = ip->getIpCid();
+                    }
+                }
+            }
+        }
+    }
+
+  private:
+    static void getCiCamInfo(Frontend feConfig, bool& canConnectToCiCam, uint32_t& ciCamId) {
+        if (!feConfig.hasConnectToCicamId()) {
+            canConnectToCiCam = false;
+            ciCamId = -1;
+        }
+        canConnectToCiCam = true;
+        ciCamId = static_cast<uint32_t>(feConfig.getConnectToCicamId());
+    }
+
+    static FrontendDvbsSettingsExt1_1 readDvbsFrontendSettings1_1(Frontend feConfig) {
+        FrontendDvbsSettingsExt1_1 dvbsSettings;
+        if (!feConfig.hasDvbsFrontendSettings_optional()) {
+            return dvbsSettings;
+        }
+        auto dvbs = feConfig.getFirstDvbsFrontendSettings_optional();
+        if (dvbs->hasScanType()) {
+            dvbsSettings.scanType = static_cast<FrontendDvbsScanType>(dvbs->getScanType());
+        }
+        if (dvbs->hasIsDiseqcRxMessage()) {
+            dvbsSettings.isDiseqcRxMessage = dvbs->getIsDiseqcRxMessage();
+        }
+        return dvbsSettings;
+    }
+
+    static FrontendDvbtSettingsExt1_1 readDvbtFrontendSettings1_1(Frontend feConfig) {
+        FrontendDvbtSettingsExt1_1 dvbtSettings;
+        if (!feConfig.hasDvbtFrontendSettings_optional()) {
+            return dvbtSettings;
+        }
+        auto dvbt = feConfig.getFirstDvbtFrontendSettings_optional();
+        auto trans = dvbt->getTransmissionMode();
+        dvbtSettings.transmissionMode =
+                static_cast<android::hardware::tv::tuner::V1_1::FrontendDvbtTransmissionMode>(
+                        trans);
+        if (dvbt->hasConstellation()) {
+            dvbtSettings.constellation =
+                    static_cast<android::hardware::tv::tuner::V1_1::FrontendDvbtConstellation>(
+                            dvbt->getConstellation());
+        }
+        return dvbtSettings;
+    }
+};
\ No newline at end of file
diff --git a/tv/tuner/config/api/current.txt b/tv/tuner/config/api/current.txt
index 4255a60..a9602e7 100644
--- a/tv/tuner/config/api/current.txt
+++ b/tv/tuner/config/api/current.txt
@@ -3,8 +3,12 @@
 
   public class AvFilterSettings {
     ctor public AvFilterSettings();
+    method @Nullable public short getAudioStreamType_optional();
     method @Nullable public boolean getIsPassthrough();
+    method @Nullable public short getVideoStreamType_optional();
+    method public void setAudioStreamType_optional(@Nullable short);
     method public void setIsPassthrough(@Nullable boolean);
+    method public void setVideoStreamType_optional(@Nullable short);
   }
 
   public class DataFlowConfiguration {
@@ -32,12 +36,14 @@
     method @Nullable public String getAudioFilterConnection();
     method @Nullable public String getDvrSoftwareFeConnection();
     method @Nullable public String getFrontendConnection();
+    method @Nullable public String getIpFilterConnection();
     method @Nullable public String getPcrFilterConnection();
     method @Nullable public String getSectionFilterConnection();
     method @Nullable public String getVideoFilterConnection();
     method public void setAudioFilterConnection(@Nullable String);
     method public void setDvrSoftwareFeConnection(@Nullable String);
     method public void setFrontendConnection(@Nullable String);
+    method public void setIpFilterConnection(@Nullable String);
     method public void setPcrFilterConnection(@Nullable String);
     method public void setSectionFilterConnection(@Nullable String);
     method public void setVideoFilterConnection(@Nullable String);
@@ -144,17 +150,32 @@
   public class DvbsFrontendSettings {
     ctor public DvbsFrontendSettings();
     method @Nullable public java.math.BigInteger getInputStreamId();
+    method @Nullable public boolean getIsDiseqcRxMessage();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.DvbsScanType getScanType();
     method @Nullable public java.math.BigInteger getSymbolRate();
     method public void setInputStreamId(@Nullable java.math.BigInteger);
+    method public void setIsDiseqcRxMessage(@Nullable boolean);
+    method public void setScanType(@Nullable android.media.tuner.testing.configuration.V1_0.DvbsScanType);
     method public void setSymbolRate(@Nullable java.math.BigInteger);
   }
 
+  public enum DvbsScanType {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.DvbsScanType DIRECT;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.DvbsScanType DISEQC;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.DvbsScanType JESS;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.DvbsScanType UNDEFINED;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.DvbsScanType UNICABLE;
+  }
+
   public class DvbtFrontendSettings {
     ctor public DvbtFrontendSettings();
     method @Nullable public java.math.BigInteger getBandwidth();
+    method @Nullable public java.math.BigInteger getConstellation();
     method @Nullable public java.math.BigInteger getIsHighPriority();
     method @Nullable public java.math.BigInteger getTransmissionMode();
     method public void setBandwidth(@Nullable java.math.BigInteger);
+    method public void setConstellation(@Nullable java.math.BigInteger);
     method public void setIsHighPriority(@Nullable java.math.BigInteger);
     method public void setTransmissionMode(@Nullable java.math.BigInteger);
   }
@@ -208,7 +229,9 @@
     method @Nullable public android.media.tuner.testing.configuration.V1_0.AvFilterSettings getAvFilterSettings_optional();
     method @Nullable public java.math.BigInteger getBufferSize();
     method @Nullable public String getId();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.IpFilterConfig getIpFilterConfig_optional();
     method @Nullable public android.media.tuner.testing.configuration.V1_0.FilterMainTypeEnum getMainType();
+    method @Nullable public java.math.BigInteger getMonitorEventTypes();
     method @Nullable public java.math.BigInteger getPid();
     method @Nullable public android.media.tuner.testing.configuration.V1_0.RecordFilterSettings getRecordFilterSettings_optional();
     method @Nullable public android.media.tuner.testing.configuration.V1_0.SectionFilterSettings getSectionFilterSettings_optional();
@@ -217,7 +240,9 @@
     method public void setAvFilterSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.AvFilterSettings);
     method public void setBufferSize(@Nullable java.math.BigInteger);
     method public void setId(@Nullable String);
+    method public void setIpFilterConfig_optional(@Nullable android.media.tuner.testing.configuration.V1_0.IpFilterConfig);
     method public void setMainType(@Nullable android.media.tuner.testing.configuration.V1_0.FilterMainTypeEnum);
+    method public void setMonitorEventTypes(@Nullable java.math.BigInteger);
     method public void setPid(@Nullable java.math.BigInteger);
     method public void setRecordFilterSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.RecordFilterSettings);
     method public void setSectionFilterSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.SectionFilterSettings);
@@ -227,6 +252,7 @@
 
   public enum FilterMainTypeEnum {
     method @NonNull public String getRawName();
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterMainTypeEnum IP;
     enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterMainTypeEnum MMTP;
     enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterMainTypeEnum TS;
   }
@@ -235,7 +261,11 @@
     method @NonNull public String getRawName();
     enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum AUDIO;
     enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum DOWNLOAD;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum IP;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum IP_PAYLOAD;
     enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum MMTP;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum NTP;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum PAYLOAD_THROUGH;
     enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum PCR;
     enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum PES;
     enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum RECORD;
@@ -334,6 +364,30 @@
     method @Nullable public java.util.List<android.media.tuner.testing.configuration.V1_0.TimeFilter> getTimeFilter();
   }
 
+  public class IpAddress {
+    ctor public IpAddress();
+    method @Nullable public java.util.List<java.lang.Short> getIp();
+    method @Nullable public boolean getIsIpV4();
+    method public void setIp(@Nullable java.util.List<java.lang.Short>);
+    method public void setIsIpV4(@Nullable boolean);
+  }
+
+  public class IpFilterConfig {
+    ctor public IpFilterConfig();
+    method @Nullable public boolean getDataPassthrough();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.IpAddress getDestIpAddress();
+    method @Nullable public long getDestPort();
+    method @Nullable public java.math.BigInteger getIpCid();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.IpAddress getSrcIpAddress();
+    method @Nullable public long getSrcPort();
+    method public void setDataPassthrough(@Nullable boolean);
+    method public void setDestIpAddress(@Nullable android.media.tuner.testing.configuration.V1_0.IpAddress);
+    method public void setDestPort(@Nullable long);
+    method public void setIpCid(@Nullable java.math.BigInteger);
+    method public void setSrcIpAddress(@Nullable android.media.tuner.testing.configuration.V1_0.IpAddress);
+    method public void setSrcPort(@Nullable long);
+  }
+
   public class Lnb {
     ctor public Lnb();
     method @Nullable public String getId();
diff --git a/tv/tuner/config/sample_tuner_vts_config.xml b/tv/tuner/config/sample_tuner_vts_config_1_0.xml
similarity index 100%
rename from tv/tuner/config/sample_tuner_vts_config.xml
rename to tv/tuner/config/sample_tuner_vts_config_1_0.xml
diff --git a/tv/tuner/config/sample_tuner_vts_config_1_1.xml b/tv/tuner/config/sample_tuner_vts_config_1_1.xml
new file mode 100644
index 0000000..191e51c
--- /dev/null
+++ b/tv/tuner/config/sample_tuner_vts_config_1_1.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- The Sample Tuner Testing Configuration.
+    Name the customized xml with "tuner_vts_config.xml" and push into the device
+    "/vendor/etc" path. Please use "tuner_testing_dynamic_configuration.xsd" to verify the xml.
+    The version section contains a “version” tag in the form “major.minor” e.g version=”1.0”
+    This shows the tuner dynamic configuration version. -->
+<TunerConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <!-- Hardware Configuration section contains the configurations of all the hardwares
+        that would be used in the tests. In the "dataFlowConfiguration" section, each data flow
+        under test has its required/optional hardwares. The ids configured in the
+        "dataFlowConfiguration" would be used to connect the hardware to each data flow test. -->
+    <hardwareConfiguration>
+        <!-- Frontends section:
+            This section contains configurations of all the frontends that would be used
+                in the tests.
+                - This section is optional and can be skipped to use the default fe settings.
+                - The default settings can be found in the sample_tuner_vts_configurations.xml.
+                - The users can also override the default frontend settings using id="FE_DEFAULT".
+                - The users can configure 1 or more frontend elements in the frontends sections.
+
+            Each frontend element contain the following attributes:
+                "id": unique id of the frontend that could be used to connect to the test the
+                    "dataFlowConfiguration"
+                "type": the frontend type. The enums are defined in the xsd.
+                "isSoftwareFrontend": if the test environment is using hardware or software
+                    frontend. If using software, a ts input file path needs to be configured.
+                "softwareFeInputPath": used as the source of the software frontend.
+                "connectToCicamId": if the device supports frontend connecting to cicam, the target
+                    cicam id needs to be configured here. Supported in Tuner 1.1 or higher.
+                "frequency": the frequency used to configure tune and scan.
+                "endFrequency": the end frequency of scan. Supported in Tuner 1.1 or higher.
+
+            Each frontend element also contains one and only one type-related "frontendSettings".
+                - The settings type should match the frontend "type" attribute.
+                - For example, when frontend type="DVBT", dvbtFrontendSettings can be configured.
+                - This is optional and skipping the settings would pass a setting with frequency
+                    config only to the hal.
+        -->
+        <frontends>
+            <frontend id="FE_DEFAULT" type="DVBT" isSoftwareFrontend="true"
+                      connectToCicamId="0" frequency="578000" endFrequency="800000">
+                <dvbtFrontendSettings bandwidth="8" transmissionMode="128" isHighPriority="1"/>
+            </frontend>
+            <frontend id="FE_DVBS_0" type="DVBS" isSoftwareFrontend="true"
+                      connectToCicamId="0" frequency="578000" endFrequency="800000">
+            </frontend>
+        </frontends>
+        <!-- Filter section:
+            This section contains configurations of all the filters that would be used in the tests.
+                - This section is optional and can be skipped to use the default filter settings.
+                - The default settings can be found in the sample_tuner_vts_configurations.xml.
+                - The users can also override the default filter settings using
+                - id="FILTER_AUDIO_DEFAULT" or "FILTER_VIDEO_DEFAULT".
+                - The users can configure 1 or more filter elements in the filters sections.
+
+            Each filter element contain the following attributes:
+                "id": unique id of the filter that could be used to connect to the test the
+                    "dataFlowConfiguration"
+                "mainType": the main filter type. The enums are defined in the xsd.
+                "subType": the sub filter type. The enums are defined in the xsd.
+                "bufferSize": the buffer size of the filter in hex.
+                "pid": the pid that would be used to configure the filter.
+                "useFMQ": if the filter uses FMQ.
+
+            Each filter element also contains at most one type-related "filterSettings".
+                - The settings type should match the filter "subType" attribute.
+                - For example, when filter subType is audio or video, the avFilterSettings can be
+                    configured.
+                - This is optional and skipping the settings would pass a setting with tpid config
+                    only to the hal.
+        -->
+        <filters>
+            <filter id="FILTER_AUDIO_DEFAULT" mainType="TS" subType="AUDIO"
+                    bufferSize="16777216" pid="257" useFMQ="false" monitorEventTypes="3">
+                <avFilterSettings isPassthrough="false">
+                    <audioStreamType>2</audioStreamType>
+                </avFilterSettings>
+            </filter>
+            <filter id="FILTER_VIDEO_DEFAULT" mainType="TS" subType="VIDEO"
+                    bufferSize="16777216" pid="256" useFMQ="false" monitorEventTypes="3">
+                <avFilterSettings isPassthrough="false">
+                    <videoStreamType>2</videoStreamType>
+                </avFilterSettings>
+            </filter>
+            <filter id="FILTER_TS_RECORD_0" mainType="TS" subType="RECORD"
+                    bufferSize="16777216" pid="257" useFMQ="false">
+                <recordFilterSettings tsIndexMask="1" scIndexType="NONE"/>
+            </filter>
+            <filter id="FILTER_IP_IP_0" mainType="IP" subType="IP" bufferSize="16777216" useFMQ="false">
+                <ipFilterConfig ipCid="1">
+                    <srcIpAddress isIpV4="true" ip="192 168 1 1"/>
+                    <destIpAddress isIpV4="true" ip="192 168 1 1"/>
+                </ipFilterConfig>
+            </filter>
+        </filters>
+        <!-- Dvr section:
+            This section contains configurations of all the dvrs that would be used in the tests.
+                - This section is optional and can be skipped if DVR is not supported.
+                - The users can configure 1 or more dvr elements in the dvrs sections.
+
+            Each dvr element contain the following attributes:
+                "id": unique id of the dvr that could be used to connect to the test the
+                    "dataFlowConfiguration"
+                "type": the dvr type.
+                "bufferSize": the dvr buffer size.
+                "statusMask": register callbacks of specific status.
+                "lowThreshold": the dvr status low threshold.
+                "highThreshold": the dvr status high threshold.
+                "dataFormat": the dvr data format.
+                "packetSize": the dvr packet size.
+                "inputFilePath": the dvr playback input file path. Only required in playback dvr.
+        -->
+        <dvrs>
+            <dvr id="DVR_PLAYBACK_0" type="PLAYBACK" bufferSize="4194304"
+                 statusMask="15" lowThreshold="4096" highThreshold="32767"
+                 dataFormat="TS" packetSize="188" inputFilePath="/data/local/tmp/segment000000.ts"/>
+            <dvr id="DVR_RECORD_0" type="RECORD" bufferSize="4194304"
+                 statusMask="15" lowThreshold="4096" highThreshold="32767"
+                 dataFormat="TS" packetSize="188"/>
+            <dvr id="DVR_PLAYBACK_1" type="PLAYBACK" bufferSize="4194304"
+                 statusMask="15" lowThreshold="4096" highThreshold="32767"
+                 dataFormat="ES" packetSize="188" inputFilePath="/data/local/tmp/test.es"/>
+        </dvrs>
+    </hardwareConfiguration>
+
+    <!-- Data flow configuration section connects each data flow under test to the ids of the
+        hardwares that would be used during the tests. -->
+    <dataFlowConfiguration>
+        <clearLiveBroadcast frontendConnection="FE_DEFAULT"
+                            audioFilterConnection="FILTER_AUDIO_DEFAULT"
+                            videoFilterConnection="FILTER_VIDEO_DEFAULT"
+                            ipFilterConnection="FILTER_IP_IP_0"
+                            dvrSoftwareFeConnection="DVR_PLAYBACK_0"/>
+        <scan frontendConnection="FE_DEFAULT"/>
+        <dvrPlayback dvrConnection="DVR_PLAYBACK_0"
+                     audioFilterConnection="FILTER_AUDIO_DEFAULT"
+                     videoFilterConnection="FILTER_VIDEO_DEFAULT"/>
+        <dvrRecord frontendConnection="FE_DEFAULT"
+                   recordFilterConnection="FILTER_TS_RECORD_0"
+                   dvrRecordConnection="DVR_RECORD_0"
+                   dvrSoftwareFeConnection="DVR_PLAYBACK_0"/>
+    </dataFlowConfiguration>
+</TunerConfiguration>
diff --git a/tv/tuner/config/tuner_testing_dynamic_configuration.xsd b/tv/tuner/config/tuner_testing_dynamic_configuration.xsd
index 3fe93ff..3303657 100644
--- a/tv/tuner/config/tuner_testing_dynamic_configuration.xsd
+++ b/tv/tuner/config/tuner_testing_dynamic_configuration.xsd
@@ -49,15 +49,27 @@
             <xs:enumeration value="DTMB"/>
         </xs:restriction>
     </xs:simpleType>
+    <xs:simpleType name="dvbsScanType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="UNDEFINED" />
+            <xs:enumeration value="DIRECT" />
+            <xs:enumeration value="DISEQC" />
+            <xs:enumeration value="UNICABLE"/>
+            <xs:enumeration value="JESS"/>
+        </xs:restriction>
+    </xs:simpleType>
 
     <xs:complexType name="dvbtFrontendSettings">
         <xs:attribute name="bandwidth" type="xs:nonNegativeInteger" use="required"/>
         <xs:attribute name="transmissionMode" type="xs:nonNegativeInteger" use="required"/>
         <xs:attribute name="isHighPriority" type="xs:nonNegativeInteger" use="required"/>
+        <xs:attribute name="constellation" type="xs:nonNegativeInteger" use="optional"/>
     </xs:complexType>
     <xs:complexType name="dvbsFrontendSettings">
         <xs:attribute name="inputStreamId" type="xs:nonNegativeInteger" use="required"/>
         <xs:attribute name="symbolRate" type="xs:nonNegativeInteger" use="required"/>
+        <xs:attribute name="scanType" type="dvbsScanType" use="optional"/>
+        <xs:attribute name="isDiseqcRxMessage" type="xs:boolean" use="optional"/>
     </xs:complexType>
 
     <xs:complexType name="frontend">
@@ -137,13 +149,19 @@
             <xs:enumeration value="SC_HEVC"/>
         </xs:restriction>
     </xs:simpleType>
+    <xs:simpleType name="monitoEvents">
+        <xs:restriction base="xs:integer">
+            <xs:minInclusive value="0"/>
+            <xs:maxInclusive value="3"/>
+        </xs:restriction>
+    </xs:simpleType>
 
     <xs:simpleType name="filterMainTypeEnum">
         <xs:restriction base="xs:string">
             <xs:enumeration value="TS" />
             <xs:enumeration value="MMTP" />
-            <!-- TODO: b/182519645 Support IP/TLV/ALP filter config
             <xs:enumeration value="IP"/>
+            <!-- TODO: b/182519645 Support TLV/ALP filter config
             <xs:enumeration value="TLV"/>
             <xs:enumeration value="ALP"/-->
         </xs:restriction>
@@ -161,10 +179,37 @@
             <xs:enumeration value="TEMI"/>
             <xs:enumeration value="MMTP"/>
             <xs:enumeration value="DOWNLOAD"/>
+            <xs:enumeration value="IP"/>
+            <xs:enumeration value="NTP"/>
+            <xs:enumeration value="IP_PAYLOAD"/>
+            <xs:enumeration value="PAYLOAD_THROUGH"/>            
         </xs:restriction>
     </xs:simpleType>
 
+    <xs:simpleType name="ip">
+        <xs:list itemType="xs:unsignedByte"/>
+    </xs:simpleType>
+    <xs:complexType name="ipAddress">
+        <xs:attribute name="isIpV4" type="xs:boolean" use="required"/>
+        <xs:attribute name="ip" type="ip" use="required"/>
+    </xs:complexType>
+    <xs:complexType name="ipFilterConfig">
+        <xs:sequence>
+            <xs:element name="srcIpAddress" type="ipAddress" minOccurs="1" maxOccurs="1"/>
+            <xs:element name="destIpAddress" type="ipAddress" minOccurs="1" maxOccurs="1"/>
+        </xs:sequence>
+        <xs:attribute name="srcPort" type="xs:unsignedInt" use="optional"/>
+        <xs:attribute name="destPort" type="xs:unsignedInt" use="optional"/>
+        <!-- True if the ip filter data goes to the next filter directly -->
+        <xs:attribute name="dataPassthrough" type="xs:boolean" use="optional"/>
+        <xs:attribute name="ipCid" type="xs:nonNegativeInteger" use="optional"/>
+    </xs:complexType>
+
     <xs:complexType name="avFilterSettings">
+        <xs:choice minOccurs="0" maxOccurs="1">
+            <xs:element name="audioStreamType" type="xs:unsignedByte"/>
+            <xs:element name="videoStreamType" type="xs:unsignedByte"/>
+        </xs:choice>
         <xs:attribute name="isPassthrough" type="xs:boolean" use="required"/>
     </xs:complexType>
     <xs:complexType name="sectionFilterSettings">
@@ -197,20 +242,28 @@
                         config only to the hal.
             </xs:documentation>
         </xs:annotation>
-        <xs:choice minOccurs="0" maxOccurs="1">
-            <!-- TODO: b/182519645 finish all the filter settings structures. -->
-            <xs:element name="sectionFilterSettings" type="sectionFilterSettings"/>
-            <xs:element name="avFilterSettings" type="avFilterSettings"/>
-            <xs:element name="recordFilterSettings" type="recordFilterSettings"/>
-            <!--xs:element name="pes" type="pesFilterSettings"/>
-            <xs:element name="download" type="downloadFilterSettings"/-->
-        </xs:choice>
+        <xs:sequence>
+            <!-- Main filter type related config -->
+            <xs:choice minOccurs="0" maxOccurs="1">
+                <xs:element name="ipFilterConfig" type="ipFilterConfig"/>
+            </xs:choice>
+            <!-- Sub filter type related config -->
+            <xs:choice minOccurs="0" maxOccurs="1">
+                <!-- TODO: b/182519645 finish all the filter settings structures. -->
+                <xs:element name="sectionFilterSettings" type="sectionFilterSettings"/>
+                <xs:element name="avFilterSettings" type="avFilterSettings"/>
+                <xs:element name="recordFilterSettings" type="recordFilterSettings"/>
+                <!--xs:element name="pes" type="pesFilterSettings"/>
+                <xs:element name="download" type="downloadFilterSettings"/-->
+            </xs:choice>
+        </xs:sequence>
         <xs:attribute name="id" type="filterId" use="required"/>
         <xs:attribute name="mainType" type="filterMainTypeEnum" use="required"/>
         <xs:attribute name="subType" type="filterSubTypeEnum" use="required"/>
         <xs:attribute name="bufferSize" type="xs:nonNegativeInteger" use="required"/>
         <xs:attribute name="pid" type="xs:nonNegativeInteger" use="optional"/>
         <xs:attribute name="useFMQ" type="xs:boolean" use="required"/>
+        <xs:attribute name="monitorEventTypes" type="monitoEvents" use="optional"/>
     </xs:complexType>
 
     <!-- DVR SESSION -->
@@ -396,7 +449,7 @@
         </xs:annotation>
         <xs:attribute name="id" type="descramblerId" use="required"/>
         <xs:attribute name="casSystemId" type="xs:nonNegativeInteger" use="required"/>
-        <xs:attribute name="provisionStr" type="xs:string" use="required"/>
+        <xs:attribute name="provisionStr" type="xs:string" use="optional"/>
         <xs:attribute name="sesstionPrivatData" type="sessionPrivateData" use="optional"/>
     </xs:complexType>
 
@@ -541,6 +594,7 @@
                     <xs:attribute name="videoFilterConnection" type="filterId" use="required"/>
                     <xs:attribute name="pcrFilterConnection" type="filterId" use="optional"/>
                     <xs:attribute name="sectionFilterConnection" type="filterId" use="optional"/>
+                    <xs:attribute name="ipFilterConnection" type="filterId" use="optional"/>
                     <!-- TODO: b/182519645 allow the users to insert extra filters -->
                     <!-- DVR is only required when the frontend is using the software input -->
                     <xs:attribute name="dvrSoftwareFeConnection" type="dvrId" use="optional"/>