Merge "Modifies EVS shader programs"
diff --git a/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h b/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h
index 1357f20..40e3552 100644
--- a/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h
+++ b/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h
@@ -41,6 +41,7 @@
 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport;
 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq;
 using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaMirror;
 using ::aidl::android::hardware::automotive::vehicle::VehicleAreaWindow;
 using ::aidl::android::hardware::automotive::vehicle::VehicleGear;
 using ::aidl::android::hardware::automotive::vehicle::VehicleHvacFanDirection;
@@ -183,6 +184,68 @@
                  },
          .initialValue = {.int32Values = {toInt(VehicleUnit::KILOWATT_HOUR)}}},
 
+        {.config = {.prop = toInt(VehicleProperty::SEAT_BELT_BUCKLED),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER}}},
+         .initialAreaValues = {{SEAT_1_LEFT, {.int32Values = {0}}},
+                               {SEAT_1_RIGHT, {.int32Values = {0}}},
+                               {SEAT_2_LEFT, {.int32Values = {0}}},
+                               {SEAT_2_RIGHT, {.int32Values = {0}}},
+                               {SEAT_2_CENTER, {.int32Values = {0}}}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_BELT_HEIGHT_POS),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10}}},
+         .initialAreaValues = {{SEAT_1_LEFT, {.int32Values = {10}}},
+                               {SEAT_1_RIGHT, {.int32Values = {10}}},
+                               {SEAT_2_LEFT, {.int32Values = {10}}},
+                               {SEAT_2_RIGHT, {.int32Values = {10}}},
+                               {SEAT_2_CENTER, {.int32Values = {10}}}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_BELT_HEIGHT_MOVE),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1}}},
+         .initialAreaValues = {{SEAT_1_LEFT, {.int32Values = {0}}},
+                               {SEAT_1_RIGHT, {.int32Values = {0}}},
+                               {SEAT_2_LEFT, {.int32Values = {0}}},
+                               {SEAT_2_RIGHT, {.int32Values = {0}}},
+                               {SEAT_2_CENTER, {.int32Values = {0}}}}},
+
         {.config =
                  {
                          .prop = toInt(VehicleProperty::SEAT_OCCUPANCY),
@@ -654,6 +717,22 @@
                                     }}},
          .initialValue = {.int32Values = {0}}},  // +ve values for heating and -ve for cooling
 
+        {.config = {.prop = toInt(VehicleProperty::HVAC_SIDE_MIRROR_HEAT),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{
+                                            .areaId = toInt(VehicleAreaMirror::DRIVER_LEFT),
+                                            .minInt32Value = 0,
+                                            .maxInt32Value = 2,
+                                    },
+                                    VehicleAreaConfig{
+                                            .areaId = toInt(VehicleAreaMirror::DRIVER_RIGHT),
+                                            .minInt32Value = 0,
+                                            .maxInt32Value = 2,
+                                    }}},
+         .initialAreaValues = {{toInt(VehicleAreaMirror::DRIVER_LEFT), {.int32Values = {2}}},
+                               {toInt(VehicleAreaMirror::DRIVER_RIGHT), {.int32Values = {1}}}}},
+
         {.config = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
                     .access = VehiclePropertyAccess::READ_WRITE,
                     .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h
index 6af1223..08e1990 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h
@@ -43,6 +43,7 @@
 #include <aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReq.h>
 #include <aidl/android/hardware/automotive/vehicle/VehicleArea.h>
 #include <aidl/android/hardware/automotive/vehicle/VehicleAreaDoor.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleAreaMirror.h>
 #include <aidl/android/hardware/automotive/vehicle/VehicleAreaSeat.h>
 #include <aidl/android/hardware/automotive/vehicle/VehicleAreaWheel.h>
 #include <aidl/android/hardware/automotive/vehicle/VehicleAreaWindow.h>
diff --git a/gnss/aidl/vts/AndroidTest.xml b/gnss/aidl/vts/AndroidTest.xml
new file mode 100644
index 0000000..d203402
--- /dev/null
+++ b/gnss/aidl/vts/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 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.
+-->
+<configuration description="Runs VtsHalGnssTargetTest.">
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="VtsHalGnssTargetTest->/data/local/tmp/VtsHalGnssTargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalGnssTargetTest" />
+        <option name="native-test-timeout" value="2m" />
+    </test>
+</configuration>
diff --git a/tv/tuner/aidl/default/Dvr.cpp b/tv/tuner/aidl/default/Dvr.cpp
index c591d07..9928a59 100644
--- a/tv/tuner/aidl/default/Dvr.cpp
+++ b/tv/tuner/aidl/default/Dvr.cpp
@@ -427,7 +427,7 @@
     map<int64_t, std::shared_ptr<IFilter>>::iterator it;
     // Handle the output data per filter type
     for (it = mFilters.begin(); it != mFilters.end(); it++) {
-        if (mDemux->startFilterHandler(it->first).isOk()) {
+        if (!mDemux->startFilterHandler(it->first).isOk()) {
             return false;
         }
     }
diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
index 07e3e3c..e6c6691 100644
--- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
@@ -494,23 +494,32 @@
     if (!lnbLive.support) {
         return;
     }
-    if (lnbMap[lnbLive.lnbId].name.compare(emptyHardwareId) == 0) {
-        vector<int32_t> ids;
-        ASSERT_TRUE(mLnbTests.getLnbIds(ids));
-        ASSERT_TRUE(ids.size() > 0);
-        ASSERT_TRUE(mLnbTests.openLnbById(ids[0]));
-    } else {
-        int32_t id;
-        ASSERT_TRUE(mLnbTests.openLnbByName(lnbMap[lnbLive.lnbId].name, id));
+    vector<LnbLiveHardwareConnections> lnbLive_configs = generateLnbLiveConfigurations();
+    if (lnbLive_configs.empty()) {
+        ALOGD("No frontends that support satellites.");
+        return;
     }
-    ASSERT_TRUE(mLnbTests.setLnbCallback());
-    ASSERT_TRUE(mLnbTests.setVoltage(lnbMap[lnbLive.lnbId].voltage));
-    ASSERT_TRUE(mLnbTests.setTone(lnbMap[lnbLive.lnbId].tone));
-    ASSERT_TRUE(mLnbTests.setSatellitePosition(lnbMap[lnbLive.lnbId].position));
-    for (auto msgName : lnbLive.diseqcMsgs) {
-        ASSERT_TRUE(mLnbTests.sendDiseqcMessage(diseqcMsgMap[msgName]));
+    for (auto& combination : lnbLive_configs) {
+        lnbLive = combination;
+
+        if (lnbMap[lnbLive.lnbId].name.compare(emptyHardwareId) == 0) {
+            vector<int32_t> ids;
+            ASSERT_TRUE(mLnbTests.getLnbIds(ids));
+            ASSERT_TRUE(ids.size() > 0);
+            ASSERT_TRUE(mLnbTests.openLnbById(ids[0]));
+        } else {
+            int32_t id;
+            ASSERT_TRUE(mLnbTests.openLnbByName(lnbMap[lnbLive.lnbId].name, id));
+        }
+        ASSERT_TRUE(mLnbTests.setLnbCallback());
+        ASSERT_TRUE(mLnbTests.setVoltage(lnbMap[lnbLive.lnbId].voltage));
+        ASSERT_TRUE(mLnbTests.setTone(lnbMap[lnbLive.lnbId].tone));
+        ASSERT_TRUE(mLnbTests.setSatellitePosition(lnbMap[lnbLive.lnbId].position));
+        for (auto msgName : lnbLive.diseqcMsgs) {
+            ASSERT_TRUE(mLnbTests.sendDiseqcMessage(diseqcMsgMap[msgName]));
+        }
+        ASSERT_TRUE(mLnbTests.closeLnb());
     }
-    ASSERT_TRUE(mLnbTests.closeLnb());
 }
 
 TEST_P(TunerDemuxAidlTest, openDemux) {
@@ -839,10 +848,16 @@
 
 TEST_P(TunerPlaybackAidlTest, PlaybackDataFlowWithTsSectionFilterTest) {
     description("Feed ts data from playback and configure Ts section filter to get output");
-    if (!playback.support || playback.sectionFilterId.compare(emptyHardwareId) == 0) {
+    if (!playback.support) {
         return;
     }
-    playbackSingleFilterTest(filterMap[playback.sectionFilterId], dvrMap[playback.dvrId]);
+    vector<DvrPlaybackHardwareConnections> playback_configs = generatePlaybackConfigs();
+    for (auto& configuration : playback_configs) {
+        if (configuration.sectionFilterId.compare(emptyHardwareId) != 0) {
+            playback = configuration;
+            playbackSingleFilterTest(filterMap[playback.sectionFilterId], dvrMap[playback.dvrId]);
+        }
+    }
 }
 
 TEST_P(TunerPlaybackAidlTest, PlaybackDataFlowWithTsAudioFilterTest) {
@@ -850,7 +865,11 @@
     if (!playback.support) {
         return;
     }
-    playbackSingleFilterTest(filterMap[playback.audioFilterId], dvrMap[playback.dvrId]);
+    vector<DvrPlaybackHardwareConnections> playback_configs = generatePlaybackConfigs();
+    for (auto& configuration : playback_configs) {
+        playback = configuration;
+        playbackSingleFilterTest(filterMap[playback.audioFilterId], dvrMap[playback.dvrId]);
+    }
 }
 
 TEST_P(TunerPlaybackAidlTest, PlaybackDataFlowWithTsVideoFilterTest) {
@@ -858,7 +877,11 @@
     if (!playback.support) {
         return;
     }
-    playbackSingleFilterTest(filterMap[playback.videoFilterId], dvrMap[playback.dvrId]);
+    vector<DvrPlaybackHardwareConnections> playback_configs = generatePlaybackConfigs();
+    for (auto& configuration : playback_configs) {
+        playback = configuration;
+        playbackSingleFilterTest(filterMap[playback.videoFilterId], dvrMap[playback.dvrId]);
+    }
 }
 
 TEST_P(TunerRecordAidlTest, RecordDataFlowWithTsRecordFilterTest) {
@@ -885,9 +908,17 @@
     if (!lnbRecord.support) {
         return;
     }
-    recordSingleFilterTestWithLnb(filterMap[lnbRecord.recordFilterId],
-                                  frontendMap[lnbRecord.frontendId], dvrMap[lnbRecord.dvrRecordId],
-                                  lnbMap[lnbRecord.lnbId]);
+    vector<LnbRecordHardwareConnections> lnbRecord_configs = generateLnbRecordConfigurations();
+    if (lnbRecord_configs.empty()) {
+        ALOGD("No frontends that support satellites.");
+        return;
+    }
+    for (auto& configuration : lnbRecord_configs) {
+        lnbRecord = configuration;
+        recordSingleFilterTestWithLnb(filterMap[lnbRecord.recordFilterId],
+                                      frontendMap[lnbRecord.frontendId],
+                                      dvrMap[lnbRecord.dvrRecordId], lnbMap[lnbRecord.lnbId]);
+    }
 }
 
 TEST_P(TunerFrontendAidlTest, TuneFrontend) {
@@ -903,7 +934,11 @@
     if (!scan.hasFrontendConnection) {
         return;
     }
-    mFrontendTests.scanTest(frontendMap[scan.frontendId], FrontendScanType::SCAN_AUTO);
+    vector<ScanHardwareConnections> scan_configs = generateScanConfigurations();
+    for (auto& configuration : scan_configs) {
+        scan = configuration;
+        mFrontendTests.scanTest(frontendMap[scan.frontendId], FrontendScanType::SCAN_AUTO);
+    }
 }
 
 TEST_P(TunerFrontendAidlTest, BlindScanFrontend) {
@@ -911,7 +946,11 @@
     if (!scan.hasFrontendConnection) {
         return;
     }
-    mFrontendTests.scanTest(frontendMap[scan.frontendId], FrontendScanType::SCAN_BLIND);
+    vector<ScanHardwareConnections> scan_configs = generateScanConfigurations();
+    for (auto& configuration : scan_configs) {
+        scan = configuration;
+        mFrontendTests.scanTest(frontendMap[scan.frontendId], FrontendScanType::SCAN_BLIND);
+    }
 }
 
 TEST_P(TunerFrontendAidlTest, TuneFrontendWithFrontendSettings) {
@@ -927,7 +966,11 @@
     if (!scan.hasFrontendConnection) {
         return;
     }
-    mFrontendTests.scanTest(frontendMap[scan.frontendId], FrontendScanType::SCAN_BLIND);
+    vector<ScanHardwareConnections> scan_configs = generateScanConfigurations();
+    for (auto& configuration : scan_configs) {
+        scan = configuration;
+        mFrontendTests.scanTest(frontendMap[scan.frontendId], FrontendScanType::SCAN_BLIND);
+    }
 }
 
 TEST_P(TunerFrontendAidlTest, LinkToCiCam) {
@@ -1005,8 +1048,16 @@
     if (!lnbLive.support) {
         return;
     }
-    broadcastSingleFilterTestWithLnb(filterMap[lnbLive.videoFilterId],
-                                     frontendMap[lnbLive.frontendId], lnbMap[lnbLive.lnbId]);
+    vector<LnbLiveHardwareConnections> lnbLive_configs = generateLnbLiveConfigurations();
+    if (lnbLive_configs.empty()) {
+        ALOGD("No frontends that support satellites.");
+        return;
+    }
+    for (auto& combination : lnbLive_configs) {
+        lnbLive = combination;
+        broadcastSingleFilterTestWithLnb(filterMap[lnbLive.videoFilterId],
+                                         frontendMap[lnbLive.frontendId], lnbMap[lnbLive.lnbId]);
+    }
 }
 
 TEST_P(TunerBroadcastAidlTest, MediaFilterWithSharedMemoryHandle) {
@@ -1022,25 +1073,34 @@
     if (!descrambling.support) {
         return;
     }
-    int32_t demuxId;
-    std::shared_ptr<IDemux> demux;
-    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
-
-    if (descrambling.hasFrontendConnection) {
-        int32_t feId;
-        mFrontendTests.getFrontendIdByType(frontendMap[descrambling.frontendId].type, feId);
-        ASSERT_TRUE(feId != INVALID_ID);
-        ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
-        ASSERT_TRUE(mFrontendTests.setFrontendCallback());
-        ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+    vector<DescramblingHardwareConnections> descrambling_configs =
+            generateDescramblingConfigurations();
+    if (descrambling_configs.empty()) {
+        ALOGD("No valid descrambling combinations in the configuration file.");
+        return;
     }
+    for (auto& combination : descrambling_configs) {
+        descrambling = combination;
+        int32_t demuxId;
+        std::shared_ptr<IDemux> demux;
+        ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
 
-    ASSERT_TRUE(mDescramblerTests.openDescrambler(demuxId));
-    ASSERT_TRUE(mDescramblerTests.closeDescrambler());
-    ASSERT_TRUE(mDemuxTests.closeDemux());
+        if (descrambling.hasFrontendConnection) {
+            int32_t feId;
+            mFrontendTests.getFrontendIdByType(frontendMap[descrambling.frontendId].type, feId);
+            ASSERT_TRUE(feId != INVALID_ID);
+            ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+            ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+            ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+        }
 
-    if (descrambling.hasFrontendConnection) {
-        ASSERT_TRUE(mFrontendTests.closeFrontend());
+        ASSERT_TRUE(mDescramblerTests.openDescrambler(demuxId));
+        ASSERT_TRUE(mDescramblerTests.closeDescrambler());
+        ASSERT_TRUE(mDemuxTests.closeDemux());
+
+        if (descrambling.hasFrontendConnection) {
+            ASSERT_TRUE(mFrontendTests.closeFrontend());
+        }
     }
 }
 
@@ -1049,11 +1109,20 @@
     if (!descrambling.support) {
         return;
     }
-    set<FilterConfig> filterConfs;
-    filterConfs.insert(static_cast<FilterConfig>(filterMap[descrambling.audioFilterId]));
-    filterConfs.insert(static_cast<FilterConfig>(filterMap[descrambling.videoFilterId]));
-    scrambledBroadcastTest(filterConfs, frontendMap[descrambling.frontendId],
-                           descramblerMap[descrambling.descramblerId]);
+    vector<DescramblingHardwareConnections> descrambling_configs =
+            generateDescramblingConfigurations();
+    if (descrambling_configs.empty()) {
+        ALOGD("No valid descrambling combinations in the configuration file.");
+        return;
+    }
+    for (auto& combination : descrambling_configs) {
+        descrambling = combination;
+        set<FilterConfig> filterConfs;
+        filterConfs.insert(static_cast<FilterConfig>(filterMap[descrambling.audioFilterId]));
+        filterConfs.insert(static_cast<FilterConfig>(filterMap[descrambling.videoFilterId]));
+        scrambledBroadcastTest(filterConfs, frontendMap[descrambling.frontendId],
+                               descramblerMap[descrambling.descramblerId]);
+    }
 }
 
 INSTANTIATE_TEST_SUITE_P(PerInstance, TunerBroadcastAidlTest,
diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h
index 57c7592..6ffa18f 100644
--- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h
@@ -65,11 +65,16 @@
 }
 
 void clearIds() {
+    lnbIds.clear();
+    diseqcMsgs.clear();
+    frontendIds.clear();
     recordDvrIds.clear();
+    descramblerIds.clear();
     audioFilterIds.clear();
     videoFilterIds.clear();
     playbackDvrIds.clear();
     recordFilterIds.clear();
+    sectionFilterIds.clear();
 }
 
 class TunerLnbAidlTest : public testing::TestWithParam<std::string> {
diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTestConfigurations.h b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTestConfigurations.h
index c4b0962..de12dc0 100644
--- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTestConfigurations.h
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTestConfigurations.h
@@ -75,6 +75,309 @@
 static LnbRecordHardwareConnections lnbRecord;
 static TimeFilterHardwareConnections timeFilter;
 
+/*
+ * This function takes in a 2d vector of device Id's
+ * The n vectors correlate to the ids for n different devices (eg frontends, filters)
+ * The resultant 2d vector is every combination of id's with 1 id from each vector
+ */
+inline vector<vector<string>> generateIdCombinations(vector<vector<string>>& ids) {
+    vector<vector<string>> combinations;
+
+    // The index of each vector in ids that will be used in the next combination
+    // EG {0, 2} means combo {ids[0][0] ids[1][2]} will be next
+    const int size = static_cast<int>(ids.size());
+    vector<int> indexes_used_in_combination(size, 0);
+
+    // The vector number from ids whose elements we will cycle through to make combinations.
+    // First, start at the right most vector
+    int cycled_vector = size - 1;
+
+    while (cycled_vector >= 0) {
+        // Make a combination (one at a time)
+        vector<string> combo;
+        for (size_t i = 0; i < indexes_used_in_combination.size(); ++i) {
+            const int combo_index = indexes_used_in_combination[i];
+            combo.push_back(ids[i][combo_index]);
+        }
+        combinations.push_back(combo);
+
+        // Find the right most vector that still has space [elements left] to cycle through and
+        // create a combination
+        while (cycled_vector >= 0 &&
+               indexes_used_in_combination[cycled_vector] == ids[cycled_vector].size() - 1) {
+            cycled_vector--;
+        }
+
+        // Use this check to avoid segmentation faults
+        if (cycled_vector >= 0) {
+            // Once found, we have a vector we can cycle through, so increase to its next element
+            indexes_used_in_combination[cycled_vector]++;
+
+            // Reset the other vectors to the right to their first element so we can cycle through
+            // them again with the new element from cycled vector
+            for (size_t i = cycled_vector + 1; i < indexes_used_in_combination.size(); ++i) {
+                indexes_used_in_combination[i] = 0;
+            }
+
+            // all the vectors to the right were reset, so we can cycle through them again
+            // Start at the furthest right vector
+            cycled_vector = size - 1;
+        }
+    }
+
+    return combinations;
+}
+
+/*
+ * index 0 - playback dvr
+ * index 1 - audio filters
+ * index 2 - video filters
+ * index 3 - optional section filters
+ */
+static inline vector<DvrPlaybackHardwareConnections> generatePlaybackCombinations() {
+    vector<DvrPlaybackHardwareConnections> combinations;
+    vector<string> sectionFilterIds_optional = sectionFilterIds;
+    sectionFilterIds_optional.push_back(emptyHardwareId);
+    vector<vector<string>> deviceIds{playbackDvrIds, audioFilterIds, videoFilterIds,
+                                     sectionFilterIds_optional};
+
+    const int dvrIndex = 0;
+    const int audioFilterIndex = 1;
+    const int videoFilterIndex = 2;
+    const int sectionFilterIndex = 3;
+
+    auto idCombinations = generateIdCombinations(deviceIds);
+    for (auto& combo : idCombinations) {
+        DvrPlaybackHardwareConnections mPlayback;
+        mPlayback.dvrId = combo[dvrIndex];
+        mPlayback.audioFilterId = combo[audioFilterIndex];
+        mPlayback.videoFilterId = combo[videoFilterIndex];
+        mPlayback.sectionFilterId = combo[sectionFilterIndex];
+        combinations.push_back(mPlayback);
+    }
+
+    return combinations;
+}
+
+static inline vector<DvrPlaybackHardwareConnections> generatePlaybackConfigs() {
+    vector<DvrPlaybackHardwareConnections> playback_configs;
+    if (configuredPlayback) {
+        ALOGD("Using DVR playback configuration provided.");
+        playback_configs = {playback};
+    } else {
+        ALOGD("Dvr playback not provided. Generating possible combinations. Consider adding it to "
+              "the configuration file.");
+        playback_configs = generatePlaybackCombinations();
+    }
+
+    return playback_configs;
+}
+
+/*
+ * index 0 - frontends
+ * index 1 - audio filters
+ * index 2 - video filters
+ * index 3 - lnbs
+ */
+static inline vector<LnbLiveHardwareConnections> generateLnbLiveCombinations() {
+    vector<LnbLiveHardwareConnections> combinations;
+    vector<vector<string>> deviceIds{frontendIds, audioFilterIds, videoFilterIds, lnbIds};
+
+    const int frontendIndex = 0;
+    const int audioFilterIndex = 1;
+    const int videoFilterIndex = 2;
+    const int lnbIndex = 3;
+
+    // TODO: Find a better way to vary diseqcMsgs, if at all
+    auto idCombinations = generateIdCombinations(deviceIds);
+    for (auto& combo : idCombinations) {
+        const string feId = combo[frontendIndex];
+        auto type = frontendMap[feId].type;
+        if (type == FrontendType::DVBS || type == FrontendType::ISDBS ||
+            type == FrontendType::ISDBS3) {
+            LnbLiveHardwareConnections mLnbLive;
+            mLnbLive.frontendId = feId;
+            mLnbLive.audioFilterId = combo[audioFilterIndex];
+            mLnbLive.videoFilterId = combo[videoFilterIndex];
+            mLnbLive.lnbId = combo[lnbIndex];
+            mLnbLive.diseqcMsgs = diseqcMsgs;
+            combinations.push_back(mLnbLive);
+        }
+    }
+
+    return combinations;
+}
+
+static inline vector<LnbLiveHardwareConnections> generateLnbLiveConfigurations() {
+    vector<LnbLiveHardwareConnections> lnbLive_configs;
+    if (configuredLnbLive) {
+        ALOGD("Using LnbLive configuration provided.");
+        lnbLive_configs = {lnbLive};
+    } else {
+        ALOGD("LnbLive not provided. Generating possible combinations. Consider adding it to the "
+              "configuration file.");
+        lnbLive_configs = generateLnbLiveCombinations();
+    }
+
+    return lnbLive_configs;
+}
+
+static inline vector<ScanHardwareConnections> generateScanCombinations() {
+    vector<ScanHardwareConnections> combinations;
+
+    for (auto& id : frontendIds) {
+        ScanHardwareConnections mScan;
+        mScan.frontendId = id;
+        combinations.push_back(mScan);
+    }
+
+    return combinations;
+}
+
+static inline vector<ScanHardwareConnections> generateScanConfigurations() {
+    vector<ScanHardwareConnections> scan_configs;
+    if (configuredScan) {
+        ALOGD("Using scan configuration provided.");
+        scan_configs = {scan};
+    } else {
+        ALOGD("Scan not provided. Generating possible combinations. Consider adding it to "
+              "the configuration file.");
+        scan_configs = generateScanCombinations();
+    }
+
+    return scan_configs;
+}
+
+/*
+ * index 0 - frontends
+ * index 1 - record filter
+ * index 2 - Record Dvr
+ * index 3 - Lnb
+ */
+static inline vector<LnbRecordHardwareConnections> generateLnbRecordCombinations() {
+    vector<LnbRecordHardwareConnections> combinations;
+    vector<vector<string>> deviceIds{frontendIds, recordFilterIds, recordDvrIds, lnbIds};
+
+    const int frontendIndex = 0;
+    const int recordFilterIndex = 1;
+    const int dvrIndex = 2;
+    const int lnbIndex = 3;
+
+    auto idCombinations = generateIdCombinations(deviceIds);
+    // TODO : Find a better way to vary diseqcMsgs, if at all
+    for (auto& combo : idCombinations) {
+        const string feId = combo[frontendIndex];
+        auto type = frontendMap[feId].type;
+        if (type == FrontendType::DVBS || type == FrontendType::ISDBS ||
+            type == FrontendType::ISDBS3) {
+            LnbRecordHardwareConnections mLnbRecord;
+            mLnbRecord.frontendId = feId;
+            mLnbRecord.recordFilterId = combo[recordFilterIndex];
+            mLnbRecord.dvrRecordId = combo[dvrIndex];
+            mLnbRecord.lnbId = combo[lnbIndex];
+            mLnbRecord.diseqcMsgs = diseqcMsgs;
+            combinations.push_back(mLnbRecord);
+        }
+    }
+
+    return combinations;
+}
+
+static inline vector<LnbRecordHardwareConnections> generateLnbRecordConfigurations() {
+    vector<LnbRecordHardwareConnections> lnbRecord_configs;
+    if (configuredLnbRecord) {
+        ALOGD("Using LnbRecord configuration provided.");
+        lnbRecord_configs = {lnbRecord};
+    } else {
+        ALOGD("LnbRecord not provided. Generating possible combinations. Consider adding it to "
+              "the configuration file.");
+        lnbRecord_configs = generateLnbRecordCombinations();
+    }
+
+    return lnbRecord_configs;
+}
+
+/*
+ * index 0 - decramblers
+ * index 1 - frontends
+ * index 2 - audio filters
+ * index 3 - video filters
+ * index 4 - Dvr SW Fe Connections
+ * index 5 - DVR Source Connections
+ */
+static inline vector<DescramblingHardwareConnections> generateDescramblingCombinations() {
+    vector<DescramblingHardwareConnections> combinations;
+    vector<string> mfrontendIds = frontendIds;
+    vector<string> mDvrFeConnectionIds = playbackDvrIds;
+    vector<string> mDvrSourceConnectionIds = playbackDvrIds;
+
+    // Add the empty hardware id to each vector to include combinations where these 3 fields might
+    // be optional
+    mfrontendIds.push_back(emptyHardwareId);
+    mDvrFeConnectionIds.push_back(emptyHardwareId);
+    mDvrSourceConnectionIds.push_back(emptyHardwareId);
+
+    const int descramblerIndex = 0;
+    const int frontendIndex = 1;
+    const int audioFilterIndex = 2;
+    const int videoFilterIndex = 3;
+    const int dvrFeIdIndex = 4;
+    const int dvrSourceIdIndex = 5;
+
+    vector<vector<string>> deviceIds{descramblerIds, mfrontendIds,        audioFilterIds,
+                                     videoFilterIds, mDvrFeConnectionIds, mDvrSourceConnectionIds};
+    auto idCombinations = generateIdCombinations(deviceIds);
+    for (auto& combo : idCombinations) {
+        DescramblingHardwareConnections mDescrambling;
+        const string feId = combo[frontendIndex];
+        const string dvrSwFeId = combo[dvrFeIdIndex];
+        const string dvrSourceId = combo[dvrSourceIdIndex];
+        mDescrambling.hasFrontendConnection = feId.compare(emptyHardwareId) == 0 ? false : true;
+        if (!mDescrambling.hasFrontendConnection) {
+            if (dvrSourceId.compare(emptyHardwareId) == 0) {
+                // If combination does not have a frontend or dvr source connection, do not include
+                // it
+                continue;
+            }
+        } else {
+            if (frontendMap[feId].isSoftwareFe && dvrSwFeId.compare(emptyHardwareId) == 0) {
+                // If combination has a software frontend and no dvr->software frontend connection,
+                // do not include it
+                continue;
+            }
+        }
+        if (dvrSwFeId.compare(dvrSourceId) == 0) {
+            // If dvr->software frontend connection is the same as dvr source input to tuner, do not
+            // include it.
+            continue;
+        }
+        mDescrambling.frontendId = feId;
+        mDescrambling.audioFilterId = combo[audioFilterIndex];
+        mDescrambling.videoFilterId = combo[videoFilterIndex];
+        mDescrambling.dvrSoftwareFeId = dvrSwFeId;
+        mDescrambling.dvrSourceId = dvrSourceId;
+        mDescrambling.descramblerId = combo[descramblerIndex];
+        combinations.push_back(mDescrambling);
+    }
+
+    return combinations;
+}
+
+static inline vector<DescramblingHardwareConnections> generateDescramblingConfigurations() {
+    vector<DescramblingHardwareConnections> descrambling_configs;
+    if (configuredDescrambling) {
+        ALOGD("Using Descrambling configuration provided.");
+        descrambling_configs = {descrambling};
+    } else {
+        ALOGD("Descrambling not provided. Generating possible combinations. Consider adding it to "
+              "the "
+              "configuration file.");
+        descrambling_configs = generateDescramblingCombinations();
+    }
+
+    return descrambling_configs;
+}
+
 /** 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
@@ -252,7 +555,7 @@
         return;
     }
     if (frontendMap.empty() && playbackDvrIds.empty()) {
-        ALOGD("Cannot support dvr record. No frontends and  no playback dvr's");
+        ALOGD("Cannot support dvr record. No frontends and no playback dvr's");
         return;
     }
     if (hasSwFe && !hasHwFe && playbackDvrIds.empty()) {
diff --git a/tv/tuner/config/TunerTestingConfigAidlReaderV1_0.h b/tv/tuner/config/TunerTestingConfigAidlReaderV1_0.h
index d964d60..6fafd59 100644
--- a/tv/tuner/config/TunerTestingConfigAidlReaderV1_0.h
+++ b/tv/tuner/config/TunerTestingConfigAidlReaderV1_0.h
@@ -83,6 +83,11 @@
 static vector<string> audioFilterIds;
 static vector<string> videoFilterIds;
 static vector<string> recordFilterIds;
+static vector<string> sectionFilterIds;
+static vector<string> frontendIds;
+static vector<string> lnbIds;
+static vector<string> diseqcMsgs;
+static vector<string> descramblerIds;
 
 #define PROVISION_STR                                      \
     "{                                                   " \
@@ -268,6 +273,7 @@
             auto frontends = *hardwareConfig.getFirstFrontends();
             for (auto feConfig : frontends.getFrontend()) {
                 string id = feConfig.getId();
+                frontendIds.push_back(id);
                 if (id.compare(string("FE_DEFAULT")) == 0) {
                     // overrid default
                     frontendMap.erase(string("FE_DEFAULT"));
@@ -438,6 +444,7 @@
             auto lnbs = *hardwareConfig.getFirstLnbs();
             for (auto lnbConfig : lnbs.getLnb()) {
                 string id = lnbConfig.getId();
+                lnbIds.push_back(id);
                 if (lnbConfig.hasName()) {
                     lnbMap[id].name = lnbConfig.getName();
                 } else {
@@ -456,6 +463,7 @@
             auto descramblers = *hardwareConfig.getFirstDescramblers();
             for (auto descramblerConfig : descramblers.getDescrambler()) {
                 string id = descramblerConfig.getId();
+                descramblerIds.push_back(id);
                 descramblerMap[id].casSystemId =
                         static_cast<int32_t>(descramblerConfig.getCasSystemId());
                 if (descramblerConfig.hasProvisionStr()) {
@@ -481,6 +489,7 @@
             auto msgs = *hardwareConfig.getFirstDiseqcMessages();
             for (auto msgConfig : msgs.getDiseqcMessage()) {
                 string name = msgConfig.getMsgName();
+                diseqcMsgs.push_back(name);
                 for (uint8_t atom : msgConfig.getMsgBody()) {
                     diseqcMsgMap[name].push_back(atom);
                 }
@@ -739,17 +748,17 @@
             ALOGW("[ConfigReader] no more dvbs settings");
             return dvbsSettings;
         }
-        dvbsSettings.symbolRate = static_cast<int32_t>(
-                feConfig.getFirstDvbsFrontendSettings_optional()->getSymbolRate());
-        dvbsSettings.inputStreamId = static_cast<int32_t>(
-                feConfig.getFirstDvbsFrontendSettings_optional()->getInputStreamId());
         auto dvbs = feConfig.getFirstDvbsFrontendSettings_optional();
-        if (dvbs->hasScanType()) {
-            dvbsSettings.scanType = static_cast<FrontendDvbsScanType>(dvbs->getScanType());
-        }
-        if (dvbs->hasIsDiseqcRxMessage()) {
-            dvbsSettings.isDiseqcRxMessage = dvbs->getIsDiseqcRxMessage();
-        }
+        dvbsSettings.symbolRate = static_cast<int32_t>(dvbs->getSymbolRate());
+        dvbsSettings.inputStreamId = static_cast<int32_t>(dvbs->getInputStreamId());
+        dvbsSettings.scanType = static_cast<FrontendDvbsScanType>(dvbs->getScanType());
+        dvbsSettings.isDiseqcRxMessage = dvbs->getIsDiseqcRxMessage();
+        dvbsSettings.inversion = static_cast<FrontendSpectralInversion>(dvbs->getInversion());
+        dvbsSettings.modulation = static_cast<FrontendDvbsModulation>(dvbs->getModulation());
+        dvbsSettings.rolloff = static_cast<FrontendDvbsRolloff>(dvbs->getRolloff());
+        dvbsSettings.pilot = static_cast<FrontendDvbsPilot>(dvbs->getPilot());
+        dvbsSettings.standard = static_cast<FrontendDvbsStandard>(dvbs->getStandard());
+        dvbsSettings.vcmMode = static_cast<FrontendDvbsVcmMode>(dvbs->getVcmMode());
         return dvbsSettings;
     }
 
@@ -840,6 +849,8 @@
             videoFilterIds.push_back(filterConfig.getId());
         } else if (subType == FilterSubTypeEnum::RECORD) {
             recordFilterIds.push_back(filterConfig.getId());
+        } else if (subType == FilterSubTypeEnum::SECTION) {
+            sectionFilterIds.push_back(filterConfig.getId());
         }
 
         switch (mainType) {
diff --git a/tv/tuner/config/api/current.txt b/tv/tuner/config/api/current.txt
index 7ad7dcf..79efb1b 100644
--- a/tv/tuner/config/api/current.txt
+++ b/tv/tuner/config/api/current.txt
@@ -178,13 +178,25 @@
   public class DvbsFrontendSettings {
     ctor public DvbsFrontendSettings();
     method @Nullable public java.math.BigInteger getInputStreamId();
+    method @Nullable public java.math.BigInteger getInversion();
     method @Nullable public boolean getIsDiseqcRxMessage();
+    method @Nullable public java.math.BigInteger getModulation();
+    method @Nullable public java.math.BigInteger getPilot();
+    method @Nullable public java.math.BigInteger getRolloff();
     method @Nullable public android.media.tuner.testing.configuration.V1_0.DvbsScanType getScanType();
+    method @Nullable public java.math.BigInteger getStandard();
     method @Nullable public java.math.BigInteger getSymbolRate();
+    method @Nullable public java.math.BigInteger getVcmMode();
     method public void setInputStreamId(@Nullable java.math.BigInteger);
+    method public void setInversion(@Nullable java.math.BigInteger);
     method public void setIsDiseqcRxMessage(@Nullable boolean);
+    method public void setModulation(@Nullable java.math.BigInteger);
+    method public void setPilot(@Nullable java.math.BigInteger);
+    method public void setRolloff(@Nullable java.math.BigInteger);
     method public void setScanType(@Nullable android.media.tuner.testing.configuration.V1_0.DvbsScanType);
+    method public void setStandard(@Nullable java.math.BigInteger);
     method public void setSymbolRate(@Nullable java.math.BigInteger);
+    method public void setVcmMode(@Nullable java.math.BigInteger);
   }
 
   public enum DvbsScanType {
diff --git a/tv/tuner/config/sample_tuner_vts_config_aidl_V1.xml b/tv/tuner/config/sample_tuner_vts_config_aidl_V1.xml
index 90f3c9b..1a148a4 100644
--- a/tv/tuner/config/sample_tuner_vts_config_aidl_V1.xml
+++ b/tv/tuner/config/sample_tuner_vts_config_aidl_V1.xml
@@ -68,7 +68,8 @@
             <frontend id="FE_DVBS_0" type="DVBS" isSoftwareFrontend="true"
                       connectToCicamId="0" removeOutputPid="10" frequency="578000000"
                       endFrequency="800000000">
-              <dvbsFrontendSettings inputStreamId="0" symbolRate="0"/>
+              <dvbsFrontendSettings inputStreamId="0" symbolRate="0" inversion="0" modulation="0" coderate="0"
+                                    rolloff="0" pilot="0" standard="0" vcmMode="0" scanType="0" isDiseqcRxMessage="true"/>
             </frontend>
             <frontend id="FE_DVBT_0" type="DVBT" isSoftwareFrontend="true"
                       connectToCicamId="0" removeOutputPid="10" frequency="578000000"
diff --git a/tv/tuner/config/tuner_testing_dynamic_configuration.xsd b/tv/tuner/config/tuner_testing_dynamic_configuration.xsd
index e67f623..e0f2579 100644
--- a/tv/tuner/config/tuner_testing_dynamic_configuration.xsd
+++ b/tv/tuner/config/tuner_testing_dynamic_configuration.xsd
@@ -77,8 +77,14 @@
     <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:attribute name="scanType" type="dvbsScanType" use="required"/>
+        <xs:attribute name="isDiseqcRxMessage" type="xs:boolean" use="required"/>
+        <xs:attribute name="inversion" type="xs:nonNegativeInteger" use="required"/>
+        <xs:attribute name="modulation" type="xs:nonNegativeInteger" use="required"/>
+        <xs:attribute name="pilot" type="xs:nonNegativeInteger" use="required"/>
+        <xs:attribute name="standard" type="xs:nonNegativeInteger" use="required"/>
+        <xs:attribute name="vcmMode" type="xs:nonNegativeInteger" use="required"/>
+        <xs:attribute name="rolloff" type="xs:nonNegativeInteger" use="required"/>
     </xs:complexType>
     <xs:complexType name="atscFrontendSettings">
         <xs:attribute name="inversion" type="xs:nonNegativeInteger" use="required"/>