[automerge] Fix array out of bound in audioTransportToHal. 2p: f16c6d3a57 am: 377e999d1b

Original change: https://googleplex-android-review.googlesource.com/c/platform/hardware/interfaces/+/19214732

Change-Id: I3247e21feeec867a71694e2ed3e13d930cc54d8d
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/atrace/1.0/default/android.hardware.atrace@1.0-service.rc b/atrace/1.0/default/android.hardware.atrace@1.0-service.rc
index 7110b45..31459b4 100644
--- a/atrace/1.0/default/android.hardware.atrace@1.0-service.rc
+++ b/atrace/1.0/default/android.hardware.atrace@1.0-service.rc
@@ -14,4 +14,4 @@
     interface android.hardware.atrace@1.0::IAtraceDevice default
     class early_hal
     user system
-    group system
+    group system readtracefs
diff --git a/audio/core/all-versions/default/Android.bp b/audio/core/all-versions/default/Android.bp
index 901b7ee..b170ff4 100644
--- a/audio/core/all-versions/default/Android.bp
+++ b/audio/core/all-versions/default/Android.bp
@@ -48,6 +48,8 @@
         "libhidlbase",
         "liblog",
         "libmedia_helper",
+        "libmediautils_vendor",
+        "libmemunreachable",
         "libutils",
         "android.hardware.audio.common-util",
     ],
@@ -138,8 +140,8 @@
     defaults: ["android.hardware.audio@6.0-impl_default"],
 }
 
-cc_library_shared {
-    name: "android.hardware.audio@7.0-impl",
+cc_defaults {
+    name: "android.hardware.audio@7.0-impl_default",
     defaults: ["android.hardware.audio-impl_default"],
     shared_libs: [
         "android.hardware.audio@7.0",
@@ -155,3 +157,8 @@
         "-include common/all-versions/VersionMacro.h",
     ],
 }
+
+cc_library_shared {
+    name: "android.hardware.audio@7.0-impl",
+    defaults: ["android.hardware.audio@7.0-impl_default"],
+}
diff --git a/audio/core/all-versions/default/Device.cpp b/audio/core/all-versions/default/Device.cpp
index 130dfba..c33e6f3 100644
--- a/audio/core/all-versions/default/Device.cpp
+++ b/audio/core/all-versions/default/Device.cpp
@@ -30,6 +30,8 @@
 #include <algorithm>
 
 #include <android/log.h>
+#include <mediautils/MemoryLeakTrackUtil.h>
+#include <memunreachable/memunreachable.h>
 
 #include <HidlUtils.h>
 
@@ -456,9 +458,32 @@
 }
 #endif
 
-Return<void> Device::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /* options */) {
+Return<void> Device::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
     if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
-        analyzeStatus("dump", mDevice->dump(mDevice, fd->data[0]));
+        const int fd0 = fd->data[0];
+        bool dumpMem = false;
+        bool unreachableMemory = false;
+        for (const auto& option : options) {
+            if (option == "-m") {
+                dumpMem = true;
+            } else if (option == "--unreachable") {
+                unreachableMemory = true;
+            }
+        }
+
+        if (dumpMem) {
+            dprintf(fd0, "\nDumping memory:\n");
+            std::string s = dumpMemoryAddresses(100 /* limit */);
+            write(fd0, s.c_str(), s.size());
+        }
+        if (unreachableMemory) {
+            dprintf(fd0, "\nDumping unreachable memory:\n");
+            // TODO - should limit be an argument parameter?
+            std::string s = GetUnreachableMemoryString(true /* contents */, 100 /* limit */);
+            write(fd0, s.c_str(), s.size());
+        }
+
+        analyzeStatus("dump", mDevice->dump(mDevice, fd0));
     }
     return Void();
 }
diff --git a/audio/core/all-versions/vts/functional/6.0/Generators.cpp b/audio/core/all-versions/vts/functional/6.0/Generators.cpp
index 6b4dbc1..e3b98c9 100644
--- a/audio/core/all-versions/vts/functional/6.0/Generators.cpp
+++ b/audio/core/all-versions/vts/functional/6.0/Generators.cpp
@@ -36,9 +36,14 @@
 std::vector<DeviceConfigParameter> generateOutputDeviceConfigParameters(bool oneProfilePerDevice) {
     std::vector<DeviceConfigParameter> result;
     for (const auto& device : getDeviceParameters()) {
-        auto module =
-                getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
+        const std::string moduleName = std::get<PARAM_DEVICE_NAME>(device);
+        auto module = getCachedPolicyConfig().getModuleFromName(moduleName);
         for (const auto& ioProfile : module->getOutputProfiles()) {
+            if (getCachedPolicyConfig()
+                        .getAttachedSinkDeviceForMixPort(moduleName, ioProfile->getName())
+                        .empty()) {
+                continue;  // no attached device
+            }
             for (const auto& profile : ioProfile->getAudioProfiles()) {
                 const auto& channels = profile->getChannels();
                 const auto& sampleRates = profile->getSampleRates();
@@ -94,9 +99,14 @@
 std::vector<DeviceConfigParameter> generateInputDeviceConfigParameters(bool oneProfilePerDevice) {
     std::vector<DeviceConfigParameter> result;
     for (const auto& device : getDeviceParameters()) {
-        auto module =
-                getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
+        const std::string moduleName = std::get<PARAM_DEVICE_NAME>(device);
+        auto module = getCachedPolicyConfig().getModuleFromName(moduleName);
         for (const auto& ioProfile : module->getInputProfiles()) {
+            if (getCachedPolicyConfig()
+                        .getAttachedSourceDeviceForMixPort(moduleName, ioProfile->getName())
+                        .empty()) {
+                continue;  // no attached device
+            }
             for (const auto& profile : ioProfile->getAudioProfiles()) {
                 const auto& channels = profile->getChannels();
                 const auto& sampleRates = profile->getSampleRates();
diff --git a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
index 0cc6a5b..2759801 100644
--- a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
@@ -499,18 +499,10 @@
             return xsd::isLinearPcm(std::get<PARAM_CONFIG>(cfg).base.format)
                    // MMAP NOIRQ and HW A/V Sync profiles use special writing protocols.
                    &&
-                   std::find_if(flags.begin(), flags.end(),
-                                [](const auto& flag) {
-                                    return flag == toString(xsd::AudioInOutFlag::
-                                                                    AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) ||
-                                           flag == toString(xsd::AudioInOutFlag::
-                                                                    AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
-                                }) == flags.end() &&
-                   !getCachedPolicyConfig()
-                            .getAttachedSinkDeviceForMixPort(
-                                    std::get<PARAM_DEVICE_NAME>(std::get<PARAM_DEVICE>(cfg)),
-                                    std::get<PARAM_PORT_NAME>(cfg))
-                            .empty();
+                   std::find_if(flags.begin(), flags.end(), [](const auto& flag) {
+                       return flag == toString(xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) ||
+                              flag == toString(xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
+                   }) == flags.end();
         });
         return pcmParams;
     }();
@@ -677,20 +669,13 @@
                            // reading h/w hotword might require Soundtrigger to be active.
                            &&
                            std::find_if(
-                                   flags.begin(), flags.end(),
-                                   [](const auto& flag) {
+                                   flags.begin(), flags.end(), [](const auto& flag) {
                                        return flag == toString(
                                                               xsd::AudioInOutFlag::
                                                                       AUDIO_INPUT_FLAG_MMAP_NOIRQ) ||
                                               flag == toString(xsd::AudioInOutFlag::
                                                                        AUDIO_INPUT_FLAG_HW_HOTWORD);
-                                   }) == flags.end() &&
-                           !getCachedPolicyConfig()
-                                    .getAttachedSourceDeviceForMixPort(
-                                            std::get<PARAM_DEVICE_NAME>(
-                                                    std::get<PARAM_DEVICE>(cfg)),
-                                            std::get<PARAM_PORT_NAME>(cfg))
-                                    .empty();
+                                   }) == flags.end();
                 });
         return pcmParams;
     }();
diff --git a/audio/core/all-versions/vts/functional/7.0/Generators.cpp b/audio/core/all-versions/vts/functional/7.0/Generators.cpp
index d2ba339..42bf1d3 100644
--- a/audio/core/all-versions/vts/functional/7.0/Generators.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/Generators.cpp
@@ -95,13 +95,21 @@
 std::vector<DeviceConfigParameter> generateOutputDeviceConfigParameters(bool oneProfilePerDevice) {
     std::vector<DeviceConfigParameter> result;
     for (const auto& device : getDeviceParameters()) {
-        auto module =
-                getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
+        const std::string moduleName = std::get<PARAM_DEVICE_NAME>(device);
+        auto module = getCachedPolicyConfig().getModuleFromName(moduleName);
         if (!module || !module->getFirstMixPorts()) break;
         for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
             if (mixPort.getRole() != xsd::Role::source) continue;  // not an output profile
+            if (getCachedPolicyConfig()
+                        .getAttachedSinkDeviceForMixPort(moduleName, mixPort.getName())
+                        .empty()) {
+                continue;  // no attached device
+            }
             auto [flags, isOffload] = generateOutFlags(mixPort);
             for (const auto& profile : mixPort.getProfile()) {
+                if (!profile.hasFormat() || !profile.hasSamplingRates() ||
+                    !profile.hasChannelMasks())
+                    continue;
                 auto configs = combineAudioConfig(profile.getChannelMasks(),
                                                   profile.getSamplingRates(), profile.getFormat());
                 for (auto& config : configs) {
@@ -220,17 +228,25 @@
 std::vector<DeviceConfigParameter> generateInputDeviceConfigParameters(bool oneProfilePerDevice) {
     std::vector<DeviceConfigParameter> result;
     for (const auto& device : getDeviceParameters()) {
-        auto module =
-                getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
+        const std::string moduleName = std::get<PARAM_DEVICE_NAME>(device);
+        auto module = getCachedPolicyConfig().getModuleFromName(moduleName);
         if (!module || !module->getFirstMixPorts()) break;
         for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
             if (mixPort.getRole() != xsd::Role::sink) continue;  // not an input profile
+            if (getCachedPolicyConfig()
+                        .getAttachedSourceDeviceForMixPort(moduleName, mixPort.getName())
+                        .empty()) {
+                continue;  // no attached device
+            }
             std::vector<AudioInOutFlag> flags;
             if (mixPort.hasFlags()) {
                 std::transform(mixPort.getFlags().begin(), mixPort.getFlags().end(),
                                std::back_inserter(flags), [](auto flag) { return toString(flag); });
             }
             for (const auto& profile : mixPort.getProfile()) {
+                if (!profile.hasFormat() || !profile.hasSamplingRates() ||
+                    !profile.hasChannelMasks())
+                    continue;
                 auto configs = combineAudioConfig(profile.getChannelMasks(),
                                                   profile.getSamplingRates(), profile.getFormat());
                 for (const auto& config : configs) {
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index e446a7f..cfee26a 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -211,6 +211,7 @@
     data: [
         "tests/apm_config_no_vx.xml",
         "tests/apm_config_with_vx.xml",
+        "tests/apm_config_b_205808571_6_0.xml",
     ],
     test_config: "tests/HalAudioV6_0GeneratorTest.xml",
 }
@@ -239,6 +240,8 @@
     data: [
         "tests/apm_config_no_vx_7_0.xml",
         "tests/apm_config_with_vx_7_0.xml",
+        "tests/apm_config_b_204314749_7_0.xml",
+        "tests/apm_config_b_205808571_7_0.xml",
     ],
     test_config: "tests/HalAudioV7_0GeneratorTest.xml",
 }
diff --git a/audio/core/all-versions/vts/functional/PolicyConfig.h b/audio/core/all-versions/vts/functional/PolicyConfig.h
index a94041c..171d03f 100644
--- a/audio/core/all-versions/vts/functional/PolicyConfig.h
+++ b/audio/core/all-versions/vts/functional/PolicyConfig.h
@@ -76,6 +76,16 @@
     const std::set<std::string>& getModulesWithDevicesNames() const {
         return mModulesWithDevicesNames;
     }
+    std::string getAttachedSinkDeviceForMixPort(const std::string& moduleName,
+                                                const std::string& mixPortName) const {
+        return findAttachedDevice(getAttachedDevices(moduleName),
+                                  getSinkDevicesForMixPort(moduleName, mixPortName));
+    }
+    std::string getAttachedSourceDeviceForMixPort(const std::string& moduleName,
+                                                  const std::string& mixPortName) const {
+        return findAttachedDevice(getAttachedDevices(moduleName),
+                                  getSourceDevicesForMixPort(moduleName, mixPortName));
+    }
     bool haveInputProfilesInModule(const std::string& name) const {
         auto module = getModuleFromName(name);
         return module && !module->getInputProfiles().empty();
@@ -92,6 +102,8 @@
                 for (const auto& module : hwModules) {
                     if (module->getDeclaredDevices().indexOf(device) >= 0) {
                         mModulesWithDevicesNames.insert(module->getName());
+                        mAttachedDevicesPerModule[module->getName()].push_back(
+                                device->getTagName());
                         break;
                     }
                 }
@@ -100,16 +112,64 @@
                 for (const auto& module : hwModules) {
                     if (module->getDeclaredDevices().indexOf(device) >= 0) {
                         mModulesWithDevicesNames.insert(module->getName());
+                        mAttachedDevicesPerModule[module->getName()].push_back(
+                                device->getTagName());
                         break;
                     }
                 }
             }
         }
     }
+    std::string findAttachedDevice(const std::vector<std::string>& attachedDevices,
+                                   const std::set<std::string>& possibleDevices) const {
+        for (const auto& device : attachedDevices) {
+            if (possibleDevices.count(device)) return device;
+        }
+        return {};
+    }
+    std::vector<std::string> getAttachedDevices(const std::string& moduleName) const {
+        if (auto iter = mAttachedDevicesPerModule.find(moduleName);
+            iter != mAttachedDevicesPerModule.end()) {
+            return iter->second;
+        }
+        return {};
+    }
+    std::set<std::string> getSinkDevicesForMixPort(const std::string& moduleName,
+                                                   const std::string& mixPortName) const {
+        std::set<std::string> result;
+        auto module = getModuleFromName(moduleName);
+        if (module != nullptr) {
+            for (const auto& route : module->getRoutes()) {
+                for (const auto& source : route->getSources()) {
+                    if (source->getTagName() == mixPortName) {
+                        result.insert(route->getSink()->getTagName());
+                    }
+                }
+            }
+        }
+        return result;
+    }
+    std::set<std::string> getSourceDevicesForMixPort(const std::string& moduleName,
+                                                     const std::string& mixPortName) const {
+        std::set<std::string> result;
+        auto module = getModuleFromName(moduleName);
+        if (module != nullptr) {
+            for (const auto& route : module->getRoutes()) {
+                if (route->getSink()->getTagName() == mixPortName) {
+                    const auto& sources = route->getSources();
+                    std::transform(sources.begin(), sources.end(),
+                                   std::inserter(result, result.end()),
+                                   [](const auto& source) { return source->getTagName(); });
+                }
+            }
+        }
+        return result;
+    }
 
     const std::string mConfigFileName;
     status_t mStatus = android::NO_INIT;
     std::string mFilePath;
     sp<const android::HwModule> mPrimaryModule = nullptr;
     std::set<std::string> mModulesWithDevicesNames;
+    std::map<std::string, std::vector<std::string>> mAttachedDevicesPerModule;
 };
diff --git a/audio/core/all-versions/vts/functional/VtsHalAudioV6_0TargetTest.xml b/audio/core/all-versions/vts/functional/VtsHalAudioV6_0TargetTest.xml
index f035baf..ae57125 100644
--- a/audio/core/all-versions/vts/functional/VtsHalAudioV6_0TargetTest.xml
+++ b/audio/core/all-versions/vts/functional/VtsHalAudioV6_0TargetTest.xml
@@ -34,5 +34,6 @@
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="VtsHalAudioV6_0TargetTest" />
+        <option name="native-test-timeout" value="5m" />
     </test>
 </configuration>
diff --git a/audio/core/all-versions/vts/functional/VtsHalAudioV7_0TargetTest.xml b/audio/core/all-versions/vts/functional/VtsHalAudioV7_0TargetTest.xml
index 6635f31..55dbaf1 100644
--- a/audio/core/all-versions/vts/functional/VtsHalAudioV7_0TargetTest.xml
+++ b/audio/core/all-versions/vts/functional/VtsHalAudioV7_0TargetTest.xml
@@ -34,5 +34,6 @@
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="VtsHalAudioV7_0TargetTest" />
+        <option name="native-test-timeout" value="5m" />
     </test>
 </configuration>
diff --git a/audio/core/all-versions/vts/functional/tests/HalAudioV6_0GeneratorTest.xml b/audio/core/all-versions/vts/functional/tests/HalAudioV6_0GeneratorTest.xml
index 0c85a05..0230447 100644
--- a/audio/core/all-versions/vts/functional/tests/HalAudioV6_0GeneratorTest.xml
+++ b/audio/core/all-versions/vts/functional/tests/HalAudioV6_0GeneratorTest.xml
@@ -24,6 +24,7 @@
         <option name="cleanup" value="true" />
         <option name="push" value="apm_config_no_vx.xml->/data/local/tmp/apm_config_no_vx.xml" />
         <option name="push" value="apm_config_with_vx.xml->/data/local/tmp/apm_config_with_vx.xml" />
+        <option name="push" value="apm_config_b_205808571_6_0.xml->/data/local/tmp/apm_config_b_205808571_6_0.xml" />
         <option name="push" value="HalAudioV6_0GeneratorTest->/data/local/tmp/HalAudioV6_0GeneratorTest" />
     </target_preparer>
 
diff --git a/audio/core/all-versions/vts/functional/tests/HalAudioV7_0GeneratorTest.xml b/audio/core/all-versions/vts/functional/tests/HalAudioV7_0GeneratorTest.xml
index 2e79455..0d8abd3 100644
--- a/audio/core/all-versions/vts/functional/tests/HalAudioV7_0GeneratorTest.xml
+++ b/audio/core/all-versions/vts/functional/tests/HalAudioV7_0GeneratorTest.xml
@@ -24,6 +24,8 @@
         <option name="cleanup" value="true" />
         <option name="push" value="apm_config_no_vx_7_0.xml->/data/local/tmp/apm_config_no_vx.xml" />
         <option name="push" value="apm_config_with_vx_7_0.xml->/data/local/tmp/apm_config_with_vx.xml" />
+        <option name="push" value="apm_config_b_204314749_7_0.xml->/data/local/tmp/apm_config_b_204314749_7_0.xml" />
+        <option name="push" value="apm_config_b_205808571_7_0.xml->/data/local/tmp/apm_config_b_205808571_7_0.xml" />
         <option name="push" value="HalAudioV7_0GeneratorTest->/data/local/tmp/HalAudioV7_0GeneratorTest" />
     </target_preparer>
 
diff --git a/audio/core/all-versions/vts/functional/tests/apm_config_b_204314749_7_0.xml b/audio/core/all-versions/vts/functional/tests/apm_config_b_204314749_7_0.xml
new file mode 100644
index 0000000..5bdca9a
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/tests/apm_config_b_204314749_7_0.xml
@@ -0,0 +1,263 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<audioPolicyConfiguration version="7.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <!-- version section contains a “version” tag in the form “major.minor” e.g. version=”1.0” -->
+
+    <!-- Global configuration Decalaration -->
+    <globalConfiguration speaker_drc_enabled="false"/>
+
+
+    <!-- Modules section:
+        There is one section per audio HW module present on the platform.
+        Each module section will contains two mandatory tags for audio HAL “halVersion” and “name”.
+        The module names are the same as in current .conf file:
+                “primary”, “A2DP”, “remote_submix”, “USB”
+        Each module will contain the following sections:
+        “devicePorts”: a list of device descriptors for all input and output devices accessible via this
+        module.
+        This contains both permanently attached devices and removable devices.
+        “mixPorts”: listing all output and input streams exposed by the audio HAL
+        “routes”: list of possible connections between input and output devices or between stream and
+        devices.
+            "route": is defined by an attribute:
+                -"type": <mux|mix> means all sources are mutual exclusive (mux) or can be mixed (mix)
+                -"sink": the sink involved in this route
+                -"sources": all the sources than can be connected to the sink via vis route
+        “attachedDevices”: permanently attached devices.
+        The attachedDevices section is a list of devices names. The names correspond to device names
+        defined in <devicePorts> section.
+        “defaultOutputDevice”: device to be used by default when no policy rule applies
+    -->
+    <modules>
+        <!-- Primary Audio HAL -->
+        <module name="primary" halVersion="3.0">
+            <attachedDevices>
+                <item>Speaker</item>
+                <item>Built-In Mic</item>
+                <item>Built-In Back Mic</item>
+                <item>Echo Reference</item>
+                <item>Tuner</item>
+            </attachedDevices>
+            <defaultOutputDevice>Speaker</defaultOutputDevice>
+            <mixPorts>
+                <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="tunnel pcm" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_HW_AV_SYNC">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="32000 44100 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="direct pcm" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="32000 44100 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="direct output" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT">
+                    <profile name=""/>
+                </mixPort>
+                <mixPort name="tunnel direct output" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_HW_AV_SYNC">
+                    <profile name=""/>
+                </mixPort>
+                <mixPort name="mmap_no_irq_out" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_MMAP_NOIRQ">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                            samplingRates="48000"
+                            channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="primary input" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
+                </mixPort>
+                <mixPort name="tunnel a2dp" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_HW_AV_SYNC">
+                    <profile name=""/>
+                </mixPort>
+                <mixPort name="direct a2dp" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT">
+                    <profile name=""/>
+                </mixPort>
+                <mixPort name="echo reference" role="sink">
+                    <profile name="echo_reference" format="AUDIO_FORMAT_PCM_32_BIT"
+                             samplingRates="48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
+                </mixPort>
+                <mixPort name="built-in mic" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_32_BIT"
+                             samplingRates="16000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
+                </mixPort>
+                <mixPort name="ble_in" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+                </mixPort>
+            </mixPorts>
+            <devicePorts>
+                <!-- Output devices declaration, i.e. Sink DEVICE PORT -->
+                <devicePort tagName="Speaker" role="sink" type="AUDIO_DEVICE_OUT_SPEAKER">
+                    <gains>
+                        <gain name="gain_1" mode="AUDIO_GAIN_MODE_JOINT"
+                              minValueMB="-10000"
+                              maxValueMB="0"
+                              defaultValueMB="-6000"
+                              stepValueMB="100"/>
+                    </gains>
+                </devicePort>
+                <devicePort tagName="HDMI Out" type="AUDIO_DEVICE_OUT_AUX_DIGITAL" role="sink">
+                </devicePort>
+                <devicePort tagName="Tuner" role="source" type="AUDIO_DEVICE_IN_TV_TUNER">
+                    <gains>
+                        <gain name="gain_1" mode="AUDIO_GAIN_MODE_JOINT"
+                              minValueMB="-10000"
+                              maxValueMB="0"
+                              defaultValueMB="-6000"
+                              stepValueMB="100"/>
+                    </gains>
+                </devicePort>
+                <devicePort tagName="Wired Headset" type="AUDIO_DEVICE_OUT_WIRED_HEADSET" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="Wired Headphones" type="AUDIO_DEVICE_OUT_WIRED_HEADPHONE" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="BT SCO" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+                </devicePort>
+                <devicePort tagName="BT SCO Headset" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+                </devicePort>
+                <devicePort tagName="BT A2DP Out" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="44100"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="BT A2DP Headphones" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="44100"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="BT A2DP Speaker" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="44100"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+
+                <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source" address="top">
+                    <profile name="" format="AUDIO_FORMAT_PCM_32_BIT"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </devicePort>
+                <devicePort tagName="Built-In Back Mic" type="AUDIO_DEVICE_IN_BACK_MIC" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </devicePort>
+                <devicePort tagName="Wired Headset Mic" type="AUDIO_DEVICE_IN_WIRED_HEADSET" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </devicePort>
+                <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+                </devicePort>
+                <devicePort tagName="Echo Reference" type="AUDIO_DEVICE_IN_ECHO_REFERENCE" role="source">
+                    <profile name="echo_reference" format="AUDIO_FORMAT_PCM_32_BIT"
+                             samplingRates="48000"
+                             channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+                </devicePort>
+                <devicePort tagName="BLE-In" type="AUDIO_DEVICE_IN_BLUETOOTH_BLE" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+                </devicePort>
+            </devicePorts>
+            <!-- route declaration, i.e. list all available sources for a given sink -->
+            <routes>
+                <route type="mix" sink="HDMI Out"
+                       sources="primary output,tunnel pcm,direct output,Tuner,mmap_no_irq_out,tunnel direct output"/>
+                <route type="mix" sink="Speaker"
+                       sources="primary output,tunnel pcm,direct pcm,BT SCO Headset Mic,Tuner,mmap_no_irq_out"/>
+                <route type="mix" sink="BT SCO"
+                       sources="primary output,BT SCO Headset Mic,Tuner,mmap_no_irq_out"/>
+                <route type="mix" sink="BT SCO Headset"
+                       sources="primary output,BT SCO Headset Mic,Tuner,mmap_no_irq_out"/>
+                <route type="mix" sink="Wired Headset"
+                       sources="primary output,tunnel pcm,BT SCO Headset Mic,Tuner,mmap_no_irq_out"/>
+                <route type="mix" sink="Wired Headphones"
+                       sources="primary output,tunnel pcm,BT SCO Headset Mic,Tuner,mmap_no_irq_out"/>
+                <route type="mix" sink="primary input"
+                       sources="Built-In Back Mic,Wired Headset Mic,BT SCO Headset Mic,Tuner"/>
+                <route type="mix" sink="BT A2DP Out"
+                       sources="primary output,tunnel a2dp,direct a2dp,Tuner,mmap_no_irq_out"/>
+                <route type="mix" sink="BT A2DP Headphones"
+                       sources="primary output,tunnel a2dp,direct a2dp,Tuner,mmap_no_irq_out"/>
+                <route type="mix" sink="BT A2DP Speaker"
+                       sources="primary output,tunnel a2dp,direct a2dp,Tuner,mmap_no_irq_out"/>
+                <route type="mix" sink="echo reference"
+                       sources="Echo Reference"/>
+                <route type="mix" sink="built-in mic"
+                       sources="Built-In Mic"/>
+                <route type="mix" sink="ble_in"
+                       sources="BLE-In"/>
+            </routes>
+
+        </module>
+
+        <!-- A2dp Audio HAL -->
+        <!-- <xi:include href="a2dp_audio_policy_configuration.xml"/> -->
+
+        <!-- Usb Audio HAL -->
+        <!-- <xi:include href="usb_audio_policy_configuration.xml"/> -->
+
+        <!-- Remote Submix Audio HAL -->
+        <!-- <xi:include href="r_submix_audio_policy_configuration.xml"/> -->
+
+        <!-- Hearing aid Audio HAL -->
+        <!-- <xi:include href="hearing_aid_audio_policy_configuration.xml"/> -->
+
+        <!-- MSD Audio HAL (optional) -->
+        <!-- <xi:include href="msd_audio_policy_configuration.xml"/> -->
+
+    </modules>
+    <!-- End of Modules section -->
+
+    <!-- Volume section -->
+
+    <!-- <xi:include href="audio_policy_volumes.xml"/> -->
+    <!-- <xi:include href="default_volume_tables.xml"/> -->
+
+    <!-- End of Volume section -->
+
+    <!-- Surround Sound configuration -->
+
+    <surroundSound>
+    <!-- Each of the listed formats gets an entry in Surround Settings dialog on TV devices.
+        There must be a corresponding Java ENCODING_... constant defined in AudioFormat.java,
+        and a display name defined in AudioFormat.toDisplayName. For the formats that don't
+        need a dedicated Surrond Settings dialog entry, a subformats list has to be used. -->
+        <formats>
+            <format name="AUDIO_FORMAT_AC3" />
+            <format name="AUDIO_FORMAT_E_AC3" />
+            <format name="AUDIO_FORMAT_E_AC3_JOC" />
+            <format name="AUDIO_FORMAT_DTS" />
+        </formats>
+    </surroundSound>
+
+    <!-- End of Surround Sound configuration -->
+
+</audioPolicyConfiguration>
diff --git a/audio/core/all-versions/vts/functional/tests/apm_config_b_205808571_6_0.xml b/audio/core/all-versions/vts/functional/tests/apm_config_b_205808571_6_0.xml
new file mode 100644
index 0000000..0f7bf7f
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/tests/apm_config_b_205808571_6_0.xml
@@ -0,0 +1,451 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (c) 2016-2021, The Linux Foundation. All rights reserved
+     Not a Contribution.
+-->
+<!-- Copyright (C) 2015 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.
+-->
+
+<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <!-- version section contains a “version” tag in the form “major.minor” e.g. version=”1.0” -->
+
+    <!-- Global configuration Decalaration -->
+    <globalConfiguration speaker_drc_enabled="true" call_screen_mode_supported="true"/>
+
+
+    <!-- Modules section:
+        There is one section per audio HW module present on the platform.
+        Each module section will contains two mandatory tags for audio HAL “halVersion” and “name”.
+        The module names are the same as in current .conf file:
+                “primary”, “A2DP”, “remote_submix”, “USB”
+        Each module will contain the following sections:
+        “devicePorts”: a list of device descriptors for all input and output devices accessible via this
+        module.
+        This contains both permanently attached devices and removable devices.
+        “mixPorts”: listing all output and input streams exposed by the audio HAL
+        “routes”: list of possible connections between input and output devices or between stream and
+        devices.
+            "route": is defined by an attribute:
+                -"type": <mux|mix> means all sources are mutual exclusive (mux) or can be mixed (mix)
+                -"sink": the sink involved in this route
+                -"sources": all the sources than can be connected to the sink via vis route
+        “attachedDevices”: permanently attached devices.
+        The attachedDevices section is a list of devices names. The names correspond to device names
+        defined in <devicePorts> section.
+        “defaultOutputDevice”: device to be used by default when no policy rule applies
+    -->
+    <modules>
+        <!-- Primary Audio HAL -->
+        <module name="primary" halVersion="2.0">
+            <attachedDevices>
+                <item>Earpiece</item>
+                <item>Speaker</item>
+                <item>Telephony Tx</item>
+                <item>Built-In Mic</item>
+                <item>Built-In Back Mic</item>
+                <item>FM Tuner</item>
+                <item>Telephony Rx</item>
+            </attachedDevices>
+            <defaultOutputDevice>Speaker</defaultOutputDevice>
+            <mixPorts>
+                <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_FAST|AUDIO_OUTPUT_FLAG_PRIMARY">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="raw" role="source"
+                        flags="AUDIO_OUTPUT_FLAG_FAST|AUDIO_OUTPUT_FLAG_RAW">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="haptics output" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A"/>
+                </mixPort>
+                <mixPort name="deep_buffer" role="source"
+                        flags="AUDIO_OUTPUT_FLAG_DEEP_BUFFER">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="mmap_no_irq_out" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="hifi_playback" role="source" />
+                <mixPort name="compress_passthrough" role="source"
+                        flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING">
+                </mixPort>
+                <mixPort name="direct_pcm" role="source"
+                        flags="AUDIO_OUTPUT_FLAG_DIRECT">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,128000,176400,192000"
+                             channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
+                    <profile name="" format="AUDIO_FORMAT_PCM_8_24_BIT"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,128000,176400,192000,352800,384000"
+                             channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
+                    <profile name="" format="AUDIO_FORMAT_PCM_24_BIT_PACKED"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,128000,176400,192000,352800,384000"
+                             channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
+                  <profile name="" format="AUDIO_FORMAT_PCM_32_BIT"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,128000,176400,192000,352800,384000"
+                             channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
+                </mixPort>
+                <mixPort name="compressed_offload" role="source"
+                         flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING">
+                    <profile name="" format="AUDIO_FORMAT_MP3"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+                    <profile name="" format="AUDIO_FORMAT_FLAC"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,128000,176400,192000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+                    <profile name="" format="AUDIO_FORMAT_ALAC"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,128000,176400,192000"
+                             channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
+                    <profile name="" format="AUDIO_FORMAT_APE"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,128000,176400,192000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+                    <profile name="" format="AUDIO_FORMAT_AAC_LC"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+                    <profile name="" format="AUDIO_FORMAT_AAC_HE_V1"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+                    <profile name="" format="AUDIO_FORMAT_AAC_HE_V2"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+                    <profile name="" format="AUDIO_FORMAT_DTS"
+                             samplingRates="32000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1"/>
+                    <profile name="" format="AUDIO_FORMAT_DTS_HD"
+                             samplingRates="32000,44100,48000,64000,88200,96000,128000,176400,192000"
+                             channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
+                    <profile name="" format="AUDIO_FORMAT_WMA"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
+                    <profile name="" format="AUDIO_FORMAT_WMA_PRO"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"
+                             channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_2POINT1,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_PENTA,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_6POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
+                    <profile name="" format="AUDIO_FORMAT_VORBIS"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000,128000,176400,192000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+                    <profile name="" format="AUDIO_FORMAT_AAC_ADTS_LC"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+                    <profile name="" format="AUDIO_FORMAT_AAC_ADTS_HE_V1"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+                    <profile name="" format="AUDIO_FORMAT_AAC_ADTS_HE_V2"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+                </mixPort>
+                <mixPort name="voice_tx" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000,48000" channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="voip_rx" role="source"
+                         flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_VOIP_RX">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000,32000,48000" channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="incall_music_uplink" role="source"
+                        flags="AUDIO_OUTPUT_FLAG_INCALL_MUSIC">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000,48000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+
+                <mixPort name="primary input" role="sink" maxOpenCount="2" maxActiveCount="2">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </mixPort>
+                <mixPort name="fast input" role="sink"
+                         flags="AUDIO_INPUT_FLAG_FAST">
+                     <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                              samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+                              channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </mixPort>
+                <mixPort name="quad mic" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                        samplingRates="48000"
+                        channelMasks="AUDIO_CHANNEL_INDEX_MASK_4"/>
+                </mixPort>
+                <mixPort name="voip_tx" role="sink"
+                         flags="AUDIO_INPUT_FLAG_VOIP_TX">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000,32000,48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+                </mixPort>
+                <mixPort name="usb_surround_sound" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,88200,96000,176400,192000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK,AUDIO_CHANNEL_INDEX_MASK_3,AUDIO_CHANNEL_INDEX_MASK_4,AUDIO_CHANNEL_IN_5POINT1,AUDIO_CHANNEL_INDEX_MASK_6,AUDIO_CHANNEL_IN_7POINT1,AUDIO_CHANNEL_INDEX_MASK_8"/>
+                    <profile name="" format="AUDIO_FORMAT_PCM_32_BIT"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,88200,96000,176400,192000"
+                             channelMasks="AUDIO_CHANNEL_IN_5POINT1,AUDIO_CHANNEL_INDEX_MASK_6,AUDIO_CHANNEL_IN_7POINT1,AUDIO_CHANNEL_INDEX_MASK_8"/>
+                    <profile name="" format="AUDIO_FORMAT_PCM_FLOAT"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,88200,96000,176400,192000"
+                             channelMasks="AUDIO_CHANNEL_IN_5POINT1,AUDIO_CHANNEL_INDEX_MASK_6,AUDIO_CHANNEL_IN_7POINT1,AUDIO_CHANNEL_INDEX_MASK_8"/>
+                </mixPort>
+                <mixPort name="record_24" role="sink" maxOpenCount="2" maxActiveCount="2">
+                    <profile name="" format="AUDIO_FORMAT_PCM_24_BIT_PACKED"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,96000,192000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK,AUDIO_CHANNEL_INDEX_MASK_3,AUDIO_CHANNEL_INDEX_MASK_4"/>
+                    <profile name="" format="AUDIO_FORMAT_PCM_8_24_BIT"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,96000,192000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK,AUDIO_CHANNEL_INDEX_MASK_3,AUDIO_CHANNEL_INDEX_MASK_4"/>
+                    <profile name="" format="AUDIO_FORMAT_PCM_FLOAT"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,96000,192000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK,AUDIO_CHANNEL_INDEX_MASK_3,AUDIO_CHANNEL_INDEX_MASK_4"/>
+                </mixPort>
+                <mixPort name="voice_rx" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000,48000" channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
+                </mixPort>
+                <mixPort name="mmap_no_irq_in" role="sink" flags="AUDIO_INPUT_FLAG_MMAP_NOIRQ">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK,AUDIO_CHANNEL_INDEX_MASK_3"/>
+                </mixPort>
+                <mixPort name="hifi_input" role="sink" />
+            </mixPorts>
+
+            <devicePorts>
+                <!-- Output devices declaration, i.e. Sink DEVICE PORT -->
+                <devicePort tagName="Earpiece" type="AUDIO_DEVICE_OUT_EARPIECE" role="sink">
+                   <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                            samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+                </devicePort>
+                <devicePort tagName="Speaker" role="sink" type="AUDIO_DEVICE_OUT_SPEAKER" address="">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="Wired Headset" type="AUDIO_DEVICE_OUT_WIRED_HEADSET" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="Wired Headphones" type="AUDIO_DEVICE_OUT_WIRED_HEADPHONE" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="Line" type="AUDIO_DEVICE_OUT_LINE" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="BT SCO" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+                </devicePort>
+                <devicePort tagName="BT SCO Headset" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+                </devicePort>
+                <devicePort tagName="BT SCO Car Kit" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+                </devicePort>
+                <devicePort tagName="Telephony Tx" type="AUDIO_DEVICE_OUT_TELEPHONY_TX" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="HDMI" type="AUDIO_DEVICE_OUT_AUX_DIGITAL" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,11025,16000,22050,32000,44100,48000,64000,88200,96000,128000,176400,192000"/>
+                </devicePort>
+                <devicePort tagName="Proxy" type="AUDIO_DEVICE_OUT_PROXY" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,11025,16000,22050,32000,44100,48000,64000,88200,96000,128000,176400,192000"/>
+                </devicePort>
+                <devicePort tagName="FM" type="AUDIO_DEVICE_OUT_FM" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="BT A2DP Out" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP" role="sink"
+                            encodedFormats="AUDIO_FORMAT_SBC AUDIO_FORMAT_AAC AUDIO_FORMAT_APTX AUDIO_FORMAT_APTX_HD AUDIO_FORMAT_LDAC AUDIO_FORMAT_CELT AUDIO_FORMAT_APTX_ADAPTIVE AUDIO_FORMAT_APTX_TWSP VX_AUDIO_FORMAT_LC3">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="BT A2DP Headphones" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES" role="sink"
+                            encodedFormats="AUDIO_FORMAT_SBC AUDIO_FORMAT_AAC AUDIO_FORMAT_APTX AUDIO_FORMAT_APTX_HD AUDIO_FORMAT_LDAC AUDIO_FORMAT_CELT AUDIO_FORMAT_APTX_ADAPTIVE AUDIO_FORMAT_APTX_TWSP VX_AUDIO_FORMAT_LC3">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="BT A2DP Speaker" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER" role="sink"
+                            encodedFormats="AUDIO_FORMAT_SBC AUDIO_FORMAT_AAC AUDIO_FORMAT_APTX AUDIO_FORMAT_APTX_HD AUDIO_FORMAT_LDAC AUDIO_FORMAT_CELT AUDIO_FORMAT_APTX_ADAPTIVE AUDIO_FORMAT_APTX_TWSP VX_AUDIO_FORMAT_LC3">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="USB Device Out" type="AUDIO_DEVICE_OUT_USB_DEVICE" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="44100,48000,64000,88200,96000,128000,176400,192000"/>
+                </devicePort>
+                <devicePort tagName="USB Headset Out" type="AUDIO_DEVICE_OUT_USB_HEADSET" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="44100,48000,64000,88200,96000,128000,176400,192000"/>
+                </devicePort>
+
+                <!-- Input devices declaration, i.e. Source DEVICE PORT -->
+                <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </devicePort>
+                <devicePort tagName="Built-In Back Mic" type="AUDIO_DEVICE_IN_BACK_MIC" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </devicePort>
+                <devicePort tagName="FM Tuner" type="AUDIO_DEVICE_IN_FM_TUNER" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
+                </devicePort>
+                <devicePort tagName="Wired Headset Mic" type="AUDIO_DEVICE_IN_WIRED_HEADSET" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </devicePort>
+                <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+                </devicePort>
+                <devicePort tagName="Telephony Rx" type="AUDIO_DEVICE_IN_TELEPHONY_RX" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000,48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+                </devicePort>
+                <devicePort tagName="USB Device In" type="AUDIO_DEVICE_IN_USB_DEVICE" role="source">
+                </devicePort>
+                <devicePort tagName="USB Headset In" type="AUDIO_DEVICE_IN_USB_HEADSET" role="source">
+                </devicePort>
+                <devicePort tagName="A2DP In" type="AUDIO_DEVICE_IN_BLUETOOTH_A2DP" role="source"
+                            encodedFormats="VX_AUDIO_FORMAT_LC3">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="44100,48000" channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
+                </devicePort>
+
+            </devicePorts>
+            <!-- route declaration, i.e. list all available sources for a given sink -->
+            <routes>
+                <route type="mix" sink="Earpiece"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,haptics output"/>
+                <route type="mix" sink="Speaker"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,haptics output"/>
+                <route type="mix" sink="Wired Headset"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,haptics output"/>
+                <route type="mix" sink="Wired Headphones"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,haptics output"/>
+                <route type="mix" sink="Line"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,haptics output"/>
+                <route type="mix" sink="HDMI"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,compress_passthrough,voip_rx,haptics output"/>
+                <route type="mix" sink="Proxy"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,haptics output"/>
+                <route type="mix" sink="FM"
+                       sources="primary output"/>
+                <route type="mix" sink="BT SCO"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+                <route type="mix" sink="BT SCO Headset"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+                <route type="mix" sink="BT SCO Car Kit"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+                <route type="mix" sink="USB Device Out"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,hifi_playback,haptics output"/>
+                <route type="mix" sink="USB Headset Out"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,hifi_playback,haptics output"/>
+                <route type="mix" sink="Telephony Tx"
+                       sources="voice_tx,incall_music_uplink"/>
+                <route type="mix" sink="voice_rx"
+                       sources="Telephony Rx"/>
+                <route type="mix" sink="primary input"
+                       sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,BT SCO Headset Mic,FM Tuner,Telephony Rx,A2DP In"/>
+                <route type="mix" sink="usb_surround_sound"
+                       sources="USB Device In,USB Headset In"/>
+                <route type="mix" sink="fast input"
+                       sources="Built-In Mic,Built-In Back Mic,BT SCO Headset Mic,Wired Headset Mic"/>
+                <route type="mix" sink="quad mic"
+                       sources="Built-In Mic,Built-In Back Mic,BT SCO Headset Mic,Wired Headset Mic"/>
+                <route type="mix" sink="voip_tx"
+                       sources="Built-In Mic,Built-In Back Mic,BT SCO Headset Mic,USB Device In,USB Headset In,Wired Headset Mic"/>
+                <route type="mix" sink="record_24"
+                       sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,A2DP In"/>
+                <route type="mix" sink="mmap_no_irq_in"
+                       sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,USB Device In,USB Headset In"/>
+                <route type="mix" sink="BT A2DP Out"
+                       sources="primary output,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+                <route type="mix" sink="BT A2DP Headphones"
+                       sources="primary output,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+                <route type="mix" sink="BT A2DP Speaker"
+                       sources="primary output,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+                <route type="mix" sink="hifi_input" sources="USB Device In,USB Headset In" />
+            </routes>
+
+        </module>
+
+        <!-- A2DP Audio HAL -->
+        <module name="a2dp" halVersion="2.0">
+            <mixPorts>
+                <mixPort name="a2dp input" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="44100,48000" channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
+                </mixPort>
+            </mixPorts>
+
+            <devicePorts>
+                <devicePort tagName="BT A2DP In" type="AUDIO_DEVICE_IN_BLUETOOTH_A2DP" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="44100,48000" channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
+                </devicePort>
+            </devicePorts>
+
+            <routes>
+                <route type="mix" sink="a2dp input"
+                       sources="BT A2DP In"/>
+            </routes>
+        </module>
+
+        <!-- Usb Audio HAL -->
+        <module name="usb" halVersion="2.0">
+            <mixPorts>
+                <mixPort name="usb_accessory output" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="44100" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+            </mixPorts>
+            <devicePorts>
+                <devicePort tagName="USB Host Out" type="AUDIO_DEVICE_OUT_USB_ACCESSORY" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="44100" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+            </devicePorts>
+            <routes>
+                <route type="mix" sink="USB Host Out"
+                       sources="usb_accessory output"/>
+            </routes>
+        </module>
+
+        <!-- Remote Submix Audio HAL -->
+        <!-- <xi:include href="/vendor/etc/r_submix_audio_policy_configuration.xml"/> -->
+
+        <!-- Bluetooth Audio HAL for hearing aid -->
+        <!-- <xi:include href="/vendor/etc/bluetooth_qti_hearing_aid_audio_policy_configuration.xml"/> -->
+
+    </modules>
+    <!-- End of Modules section -->
+
+    <!-- Volume section -->
+
+    <!-- <xi:include href="/vendor/etc/audio_policy_volumes.xml"/> -->
+    <!-- <xi:include href="/vendor/etc/default_volume_tables.xml"/> -->
+
+    <!-- End of Volume section -->
+
+</audioPolicyConfiguration>
diff --git a/audio/core/all-versions/vts/functional/tests/apm_config_b_205808571_7_0.xml b/audio/core/all-versions/vts/functional/tests/apm_config_b_205808571_7_0.xml
new file mode 100644
index 0000000..16427b6
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/tests/apm_config_b_205808571_7_0.xml
@@ -0,0 +1,446 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (c) 2016-2021, The Linux Foundation. All rights reserved
+     Not a Contribution.
+-->
+<!-- Copyright (C) 2015 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.
+-->
+
+<audioPolicyConfiguration version="7.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <!-- version section contains a “version” tag in the form “major.minor” e.g. version=”1.0” -->
+
+    <!-- Global configuration Decalaration -->
+    <globalConfiguration speaker_drc_enabled="true" call_screen_mode_supported="true"/>
+
+
+    <!-- Modules section:
+        There is one section per audio HW module present on the platform.
+        Each module section will contains two mandatory tags for audio HAL “halVersion” and “name”.
+        The module names are the same as in current .conf file:
+                “primary”, “A2DP”, “remote_submix”, “USB”
+        Each module will contain the following sections:
+        “devicePorts”: a list of device descriptors for all input and output devices accessible via this
+        module.
+        This contains both permanently attached devices and removable devices.
+        “mixPorts”: listing all output and input streams exposed by the audio HAL
+        “routes”: list of possible connections between input and output devices or between stream and
+        devices.
+            "route": is defined by an attribute:
+                -"type": <mux|mix> means all sources are mutual exclusive (mux) or can be mixed (mix)
+                -"sink": the sink involved in this route
+                -"sources": all the sources than can be connected to the sink via vis route
+        “attachedDevices”: permanently attached devices.
+        The attachedDevices section is a list of devices names. The names correspond to device names
+        defined in <devicePorts> section.
+        “defaultOutputDevice”: device to be used by default when no policy rule applies
+    -->
+    <modules>
+        <!-- Primary Audio HAL -->
+        <module name="primary" halVersion="2.0">
+            <attachedDevices>
+                <item>Earpiece</item>
+                <item>Speaker</item>
+                <item>Telephony Tx</item>
+                <item>Built-In Mic</item>
+                <item>Built-In Back Mic</item>
+                <item>FM Tuner</item>
+                <item>Telephony Rx</item>
+            </attachedDevices>
+            <defaultOutputDevice>Speaker</defaultOutputDevice>
+            <mixPorts>
+                <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_FAST AUDIO_OUTPUT_FLAG_PRIMARY">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="raw" role="source"
+                        flags="AUDIO_OUTPUT_FLAG_FAST AUDIO_OUTPUT_FLAG_RAW">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="haptics output" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A"/>
+                </mixPort>
+                <mixPort name="deep_buffer" role="source"
+                        flags="AUDIO_OUTPUT_FLAG_DEEP_BUFFER">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="mmap_no_irq_out" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_MMAP_NOIRQ">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="hifi_playback" role="source" />
+                <mixPort name="compress_passthrough" role="source"
+                        flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD AUDIO_OUTPUT_FLAG_NON_BLOCKING">
+                </mixPort>
+                <mixPort name="direct_pcm" role="source"
+                        flags="AUDIO_OUTPUT_FLAG_DIRECT">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000 128000 176400 192000"
+                             channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_2POINT1 AUDIO_CHANNEL_OUT_QUAD AUDIO_CHANNEL_OUT_PENTA AUDIO_CHANNEL_OUT_5POINT1 AUDIO_CHANNEL_OUT_6POINT1 AUDIO_CHANNEL_OUT_7POINT1"/>
+                    <profile name="" format="AUDIO_FORMAT_PCM_8_24_BIT"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000 128000 176400 192000 352800 384000"
+                             channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_2POINT1 AUDIO_CHANNEL_OUT_QUAD AUDIO_CHANNEL_OUT_PENTA AUDIO_CHANNEL_OUT_5POINT1 AUDIO_CHANNEL_OUT_6POINT1 AUDIO_CHANNEL_OUT_7POINT1"/>
+                    <profile name="" format="AUDIO_FORMAT_PCM_24_BIT_PACKED"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000 128000 176400 192000 352800 384000"
+                             channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_2POINT1 AUDIO_CHANNEL_OUT_QUAD AUDIO_CHANNEL_OUT_PENTA AUDIO_CHANNEL_OUT_5POINT1 AUDIO_CHANNEL_OUT_6POINT1 AUDIO_CHANNEL_OUT_7POINT1"/>
+                  <profile name="" format="AUDIO_FORMAT_PCM_32_BIT"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000 128000 176400 192000 352800 384000"
+                             channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_2POINT1 AUDIO_CHANNEL_OUT_QUAD AUDIO_CHANNEL_OUT_PENTA AUDIO_CHANNEL_OUT_5POINT1 AUDIO_CHANNEL_OUT_6POINT1 AUDIO_CHANNEL_OUT_7POINT1"/>
+                </mixPort>
+                <mixPort name="compressed_offload" role="source"
+                         flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD AUDIO_OUTPUT_FLAG_NON_BLOCKING">
+                    <profile name="" format="AUDIO_FORMAT_MP3"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/>
+                    <profile name="" format="AUDIO_FORMAT_FLAC"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000 128000 176400 192000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/>
+                    <profile name="" format="AUDIO_FORMAT_ALAC"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000 128000 176400 192000"
+                             channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_2POINT1 AUDIO_CHANNEL_OUT_QUAD AUDIO_CHANNEL_OUT_PENTA AUDIO_CHANNEL_OUT_5POINT1 AUDIO_CHANNEL_OUT_6POINT1 AUDIO_CHANNEL_OUT_7POINT1"/>
+                    <profile name="" format="AUDIO_FORMAT_APE"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000 128000 176400 192000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/>
+                    <profile name="" format="AUDIO_FORMAT_AAC_LC"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/>
+                    <profile name="" format="AUDIO_FORMAT_AAC_HE_V1"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/>
+                    <profile name="" format="AUDIO_FORMAT_AAC_HE_V2"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/>
+                    <profile name="" format="AUDIO_FORMAT_DTS"
+                             samplingRates="32000 44100 48000"
+                             channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_2POINT1 AUDIO_CHANNEL_OUT_QUAD AUDIO_CHANNEL_OUT_PENTA AUDIO_CHANNEL_OUT_5POINT1"/>
+                    <profile name="" format="AUDIO_FORMAT_DTS_HD"
+                             samplingRates="32000 44100 48000 64000 88200 96000 128000 176400 192000"
+                             channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_2POINT1 AUDIO_CHANNEL_OUT_QUAD AUDIO_CHANNEL_OUT_PENTA AUDIO_CHANNEL_OUT_5POINT1 AUDIO_CHANNEL_OUT_6POINT1 AUDIO_CHANNEL_OUT_7POINT1"/>
+                    <profile name="" format="AUDIO_FORMAT_WMA"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+                             channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_2POINT1 AUDIO_CHANNEL_OUT_QUAD AUDIO_CHANNEL_OUT_PENTA AUDIO_CHANNEL_OUT_5POINT1 AUDIO_CHANNEL_OUT_6POINT1 AUDIO_CHANNEL_OUT_7POINT1"/>
+                    <profile name="" format="AUDIO_FORMAT_WMA_PRO"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000"
+                             channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_2POINT1 AUDIO_CHANNEL_OUT_QUAD AUDIO_CHANNEL_OUT_PENTA AUDIO_CHANNEL_OUT_5POINT1 AUDIO_CHANNEL_OUT_6POINT1 AUDIO_CHANNEL_OUT_7POINT1"/>
+                    <profile name="" format="AUDIO_FORMAT_VORBIS"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000 128000 176400 192000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/>
+                    <profile name="" format="AUDIO_FORMAT_AAC_ADTS_LC"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/>
+                    <profile name="" format="AUDIO_FORMAT_AAC_ADTS_HE_V1"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/>
+                    <profile name="" format="AUDIO_FORMAT_AAC_ADTS_HE_V2"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/>
+                </mixPort>
+                <mixPort name="voice_tx" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 16000 48000" channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="voip_rx" role="source"
+                         flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_VOIP_RX">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 16000 32000 48000" channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="incall_music_uplink" role="source"
+                        flags="AUDIO_OUTPUT_FLAG_INCALL_MUSIC">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 16000 48000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+
+                <mixPort name="primary input" role="sink" maxOpenCount="2" maxActiveCount="2">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </mixPort>
+                <mixPort name="fast input" role="sink"
+                         flags="AUDIO_INPUT_FLAG_FAST">
+                     <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                              samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+                              channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </mixPort>
+                <mixPort name="quad mic" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                        samplingRates="48000"
+                        channelMasks="AUDIO_CHANNEL_INDEX_MASK_4"/>
+                </mixPort>
+                <mixPort name="voip_tx" role="sink"
+                         flags="AUDIO_INPUT_FLAG_VOIP_TX">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 16000 32000 48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+                </mixPort>
+                <mixPort name="usb_surround_sound" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 88200 96000 176400 192000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK AUDIO_CHANNEL_INDEX_MASK_3 AUDIO_CHANNEL_INDEX_MASK_4 AUDIO_CHANNEL_IN_5POINT1 AUDIO_CHANNEL_INDEX_MASK_6"/>
+                    <profile name="" format="AUDIO_FORMAT_PCM_32_BIT"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 88200 96000 176400 192000"
+                             channelMasks="AUDIO_CHANNEL_IN_5POINT1 AUDIO_CHANNEL_INDEX_MASK_6"/>
+                    <profile name="" format="AUDIO_FORMAT_PCM_FLOAT"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 88200 96000 176400 192000"
+                             channelMasks="AUDIO_CHANNEL_IN_5POINT1 AUDIO_CHANNEL_INDEX_MASK_6"/>
+                </mixPort>
+                <mixPort name="record_24" role="sink" maxOpenCount="2" maxActiveCount="2">
+                    <profile name="" format="AUDIO_FORMAT_PCM_24_BIT_PACKED"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 96000 192000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK AUDIO_CHANNEL_INDEX_MASK_3 AUDIO_CHANNEL_INDEX_MASK_4"/>
+                    <profile name="" format="AUDIO_FORMAT_PCM_8_24_BIT"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 96000 192000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK AUDIO_CHANNEL_INDEX_MASK_3 AUDIO_CHANNEL_INDEX_MASK_4"/>
+                    <profile name="" format="AUDIO_FORMAT_PCM_FLOAT"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 96000 192000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK AUDIO_CHANNEL_INDEX_MASK_3 AUDIO_CHANNEL_INDEX_MASK_4"/>
+                </mixPort>
+                <mixPort name="voice_rx" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 16000 48000" channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
+                </mixPort>
+                <mixPort name="mmap_no_irq_in" role="sink" flags="AUDIO_INPUT_FLAG_MMAP_NOIRQ">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK AUDIO_CHANNEL_INDEX_MASK_3"/>
+                </mixPort>
+                <mixPort name="hifi_input" role="sink" />
+            </mixPorts>
+
+            <devicePorts>
+                <!-- Output devices declaration, i.e. Sink DEVICE PORT -->
+                <devicePort tagName="Earpiece" type="AUDIO_DEVICE_OUT_EARPIECE" role="sink">
+                   <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                            samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+                </devicePort>
+                <devicePort tagName="Speaker" role="sink" type="AUDIO_DEVICE_OUT_SPEAKER" address="">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="Wired Headset" type="AUDIO_DEVICE_OUT_WIRED_HEADSET" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="Wired Headphones" type="AUDIO_DEVICE_OUT_WIRED_HEADPHONE" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="Line" type="AUDIO_DEVICE_OUT_LINE" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="BT SCO" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+                </devicePort>
+                <devicePort tagName="BT SCO Headset" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+                </devicePort>
+                <devicePort tagName="BT SCO Car Kit" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+                </devicePort>
+                <devicePort tagName="Telephony Tx" type="AUDIO_DEVICE_OUT_TELEPHONY_TX" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="HDMI" type="AUDIO_DEVICE_OUT_AUX_DIGITAL" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 11025 16000 22050 32000 44100 48000 64000 88200 96000 128000 176400 192000"/>
+                </devicePort>
+                <devicePort tagName="Proxy" type="AUDIO_DEVICE_OUT_PROXY" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 11025 16000 22050 32000 44100 48000 64000 88200 96000 128000 176400 192000"/>
+                </devicePort>
+                <devicePort tagName="FM" type="AUDIO_DEVICE_OUT_FM" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="BT A2DP Out" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP" role="sink"
+                            encodedFormats="AUDIO_FORMAT_SBC AUDIO_FORMAT_AAC AUDIO_FORMAT_APTX AUDIO_FORMAT_APTX_HD AUDIO_FORMAT_LDAC AUDIO_FORMAT_CELT AUDIO_FORMAT_APTX_ADAPTIVE AUDIO_FORMAT_APTX_TWSP VX_AUDIO_FORMAT_LC3">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="BT A2DP Headphones" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES" role="sink"
+                            encodedFormats="AUDIO_FORMAT_SBC AUDIO_FORMAT_AAC AUDIO_FORMAT_APTX AUDIO_FORMAT_APTX_HD AUDIO_FORMAT_LDAC AUDIO_FORMAT_CELT AUDIO_FORMAT_APTX_ADAPTIVE AUDIO_FORMAT_APTX_TWSP VX_AUDIO_FORMAT_LC3">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="BT A2DP Speaker" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER" role="sink"
+                            encodedFormats="AUDIO_FORMAT_SBC AUDIO_FORMAT_AAC AUDIO_FORMAT_APTX AUDIO_FORMAT_APTX_HD AUDIO_FORMAT_LDAC AUDIO_FORMAT_CELT AUDIO_FORMAT_APTX_ADAPTIVE AUDIO_FORMAT_APTX_TWSP VX_AUDIO_FORMAT_LC3">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="USB Device Out" type="AUDIO_DEVICE_OUT_USB_DEVICE" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="44100 48000 64000 88200 96000 128000 176400 192000"/>
+                </devicePort>
+                <devicePort tagName="USB Headset Out" type="AUDIO_DEVICE_OUT_USB_HEADSET" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="44100 48000 64000 88200 96000 128000 176400 192000"/>
+                </devicePort>
+
+                <!-- Input devices declaration, i.e. Source DEVICE PORT -->
+                <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </devicePort>
+                <devicePort tagName="Built-In Back Mic" type="AUDIO_DEVICE_IN_BACK_MIC" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </devicePort>
+                <devicePort tagName="FM Tuner" type="AUDIO_DEVICE_IN_FM_TUNER" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
+                </devicePort>
+                <devicePort tagName="Wired Headset Mic" type="AUDIO_DEVICE_IN_WIRED_HEADSET" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </devicePort>
+                <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+                </devicePort>
+                <devicePort tagName="Telephony Rx" type="AUDIO_DEVICE_IN_TELEPHONY_RX" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000 16000 48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+                </devicePort>
+                <devicePort tagName="USB Device In" type="AUDIO_DEVICE_IN_USB_DEVICE" role="source">
+                </devicePort>
+                <devicePort tagName="USB Headset In" type="AUDIO_DEVICE_IN_USB_HEADSET" role="source">
+                </devicePort>
+                <devicePort tagName="A2DP In" type="AUDIO_DEVICE_IN_BLUETOOTH_A2DP" role="source"
+                            encodedFormats="VX_AUDIO_FORMAT_LC3">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="44100 48000" channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
+                </devicePort>
+
+            </devicePorts>
+            <!-- route declaration, i.e. list all available sources for a given sink -->
+            <routes>
+                <route type="mix" sink="Earpiece"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,haptics output"/>
+                <route type="mix" sink="Speaker"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,haptics output"/>
+                <route type="mix" sink="Wired Headset"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,haptics output"/>
+                <route type="mix" sink="Wired Headphones"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,haptics output"/>
+                <route type="mix" sink="Line"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,haptics output"/>
+                <route type="mix" sink="HDMI"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,compress_passthrough,voip_rx,haptics output"/>
+                <route type="mix" sink="Proxy"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,haptics output"/>
+                <route type="mix" sink="FM"
+                       sources="primary output"/>
+                <route type="mix" sink="BT SCO"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+                <route type="mix" sink="BT SCO Headset"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+                <route type="mix" sink="BT SCO Car Kit"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+                <route type="mix" sink="USB Device Out"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,hifi_playback,haptics output"/>
+                <route type="mix" sink="USB Headset Out"
+                       sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx,mmap_no_irq_out,hifi_playback,haptics output"/>
+                <route type="mix" sink="Telephony Tx"
+                       sources="voice_tx,incall_music_uplink"/>
+                <route type="mix" sink="voice_rx"
+                       sources="Telephony Rx"/>
+                <route type="mix" sink="primary input"
+                       sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,BT SCO Headset Mic,FM Tuner,Telephony Rx,A2DP In"/>
+                <route type="mix" sink="usb_surround_sound"
+                       sources="USB Device In,USB Headset In"/>
+                <route type="mix" sink="fast input"
+                       sources="Built-In Mic,Built-In Back Mic,BT SCO Headset Mic,Wired Headset Mic"/>
+                <route type="mix" sink="quad mic"
+                       sources="Built-In Mic,Built-In Back Mic,BT SCO Headset Mic,Wired Headset Mic"/>
+                <route type="mix" sink="voip_tx"
+                       sources="Built-In Mic,Built-In Back Mic,BT SCO Headset Mic,USB Device In,USB Headset In,Wired Headset Mic"/>
+                <route type="mix" sink="record_24"
+                       sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,A2DP In"/>
+                <route type="mix" sink="mmap_no_irq_in"
+                       sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,USB Device In,USB Headset In"/>
+                <route type="mix" sink="BT A2DP Out"
+                       sources="primary output,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+                <route type="mix" sink="BT A2DP Headphones"
+                       sources="primary output,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+                <route type="mix" sink="BT A2DP Speaker"
+                       sources="primary output,deep_buffer,direct_pcm,compressed_offload,voip_rx,haptics output"/>
+                <route type="mix" sink="hifi_input" sources="USB Device In,USB Headset In" />
+            </routes>
+
+        </module>
+
+        <!-- A2DP Audio HAL -->
+        <module name="a2dp" halVersion="2.0">
+            <mixPorts>
+                <mixPort name="a2dp input" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="44100 48000" channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
+                </mixPort>
+            </mixPorts>
+
+            <devicePorts>
+                <devicePort tagName="BT A2DP In" type="AUDIO_DEVICE_IN_BLUETOOTH_A2DP" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="44100 48000" channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
+                </devicePort>
+            </devicePorts>
+
+            <routes>
+                <route type="mix" sink="a2dp input"
+                       sources="BT A2DP In"/>
+            </routes>
+        </module>
+
+        <!-- Usb Audio HAL -->
+        <module name="usb" halVersion="2.0">
+            <mixPorts>
+                <mixPort name="usb_accessory output" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="44100" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+            </mixPorts>
+            <devicePorts>
+                <devicePort tagName="USB Host Out" type="AUDIO_DEVICE_OUT_USB_ACCESSORY" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="44100" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+            </devicePorts>
+            <routes>
+                <route type="mix" sink="USB Host Out"
+                       sources="usb_accessory output"/>
+            </routes>
+        </module>
+
+        <!-- Remote Submix Audio HAL -->
+
+        <!-- Bluetooth Audio HAL for hearing aid -->
+
+    </modules>
+    <!-- End of Modules section -->
+
+    <!-- Volume section -->
+
+    <!-- End of Volume section -->
+
+</audioPolicyConfiguration>
diff --git a/audio/core/all-versions/vts/functional/tests/generators_tests.cpp b/audio/core/all-versions/vts/functional/tests/generators_tests.cpp
index 583ff01..3fdd8e6 100644
--- a/audio/core/all-versions/vts/functional/tests/generators_tests.cpp
+++ b/audio/core/all-versions/vts/functional/tests/generators_tests.cpp
@@ -128,5 +128,46 @@
 }
 
 // Target file names are the same for all versions, see 'HalAudioVx_0GeneratorTest.xml' test configs
+// clang-format off
 INSTANTIATE_TEST_SUITE_P(Generators, GeneratorsTest,
-                         ::testing::Values("apm_config_no_vx.xml", "apm_config_with_vx.xml"));
+                         ::testing::Values("apm_config_no_vx.xml", "apm_config_with_vx.xml"
+#if MAJOR_VERSION == 6
+                                         , "apm_config_b_205808571_6_0.xml"
+#elif MAJOR_VERSION == 7
+                                         , "apm_config_b_204314749_7_0.xml"
+                                         , "apm_config_b_205808571_7_0.xml"
+#endif
+                                           ));
+// clang-format on
+
+TEST(GeneratorsDeviceTest, AttachedDevicesOnly) {
+    static const std::string kTestFile =
+            "apm_config_b_205808571_" STRINGIFY(MAJOR_VERSION) "_0.xml";
+    ASSERT_TRUE(PolicyConfigManager::getInstance().init(kDataDir, kTestFile));
+    EXPECT_NE(nullptr, getCachedPolicyConfig().getPrimaryModule());
+    const auto allInConfigs = generateInputDeviceConfigParameters(false /*oneProfilePerDevice*/);
+    EXPECT_FALSE(allInConfigs.empty());
+    for (const auto& configParam : allInConfigs) {
+        const AudioConfig& config = std::get<PARAM_CONFIG>(configParam);
+        // The config contains multichannel masks for mixPort connected to
+        // input devicePorts that are not attached. These multichannel masks must
+        // not appear among generated masks.
+        const uint32_t channelCount =
+#if MAJOR_VERSION == 6
+                audio_channel_count_from_in_mask(
+                        static_cast<audio_channel_mask_t>(config.channelMask));
+#elif MAJOR_VERSION == 7
+                xsd::getChannelCount(config.base.channelMask);
+#endif
+        EXPECT_TRUE(channelCount <= 4) << "Unexpected channel count: " << channelCount << " " <<
+#if MAJOR_VERSION == 6
+                ::testing::PrintToString(config.format) << ", "
+                                       << ::testing::PrintToString(config.sampleRateHz) << ", "
+                                       << ::testing::PrintToString(config.channelMask);
+#elif MAJOR_VERSION == 7
+                ::testing::PrintToString(config.base.format) << ", "
+                                       << ::testing::PrintToString(config.base.sampleRateHz) << ", "
+                                       << ::testing::PrintToString(config.base.channelMask);
+#endif
+    }
+}
diff --git a/automotive/can/1.0/default/Android.bp b/automotive/can/1.0/default/Android.bp
index c0c17e2..163fdb7 100644
--- a/automotive/can/1.0/default/Android.bp
+++ b/automotive/can/1.0/default/Android.bp
@@ -64,4 +64,5 @@
         "android.hardware.automotive@libc++fs",
         "libnl++",
     ],
+    vintf_fragments: ["manifest_android.hardware.automotive.can@1.0.xml"],
 }
diff --git a/automotive/can/1.0/default/manifest_android.hardware.automotive.can@1.0.xml b/automotive/can/1.0/default/manifest_android.hardware.automotive.can@1.0.xml
new file mode 100644
index 0000000..2078ce5
--- /dev/null
+++ b/automotive/can/1.0/default/manifest_android.hardware.automotive.can@1.0.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<manifest version="1.0" type="device" >
+    <hal format="hidl">
+        <name>android.hardware.automotive.can</name>
+        <transport>hwbinder</transport>
+        <fqname>@1.0::ICanController/socketcan</fqname>
+    </hal>
+</manifest>
diff --git a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
index 8cc1882..1216d36 100644
--- a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
+++ b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
@@ -79,19 +79,24 @@
 using IEvsDisplay_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsDisplay;
 using IEvsDisplay_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsDisplay;
 
+namespace {
+
 /*
  * Plese note that this is different from what is defined in
  * libhardware/modules/camera/3_4/metadata/types.h; this has one additional
  * field to store a framerate.
  */
-const size_t kStreamCfgSz = 5;
 typedef struct {
+    int32_t id;
     int32_t width;
     int32_t height;
     int32_t format;
     int32_t direction;
     int32_t framerate;
 } RawStreamConfig;
+constexpr const size_t kStreamCfgSz = sizeof(RawStreamConfig) / sizeof(int32_t);
+
+} // anonymous namespace
 
 
 // The main test class for EVS
@@ -236,6 +241,28 @@
         return physicalCameras;
     }
 
+    Stream getFirstStreamConfiguration(camera_metadata_t* metadata) {
+        Stream targetCfg = {};
+        camera_metadata_entry_t streamCfgs;
+        if (!find_camera_metadata_entry(metadata,
+                 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+                 &streamCfgs)) {
+            // Stream configurations are found in metadata
+            RawStreamConfig *ptr = reinterpret_cast<RawStreamConfig *>(streamCfgs.data.i32);
+            for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
+                if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
+                    ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
+                    targetCfg.width = ptr->width;
+                    targetCfg.height = ptr->height;
+                    targetCfg.format = static_cast<PixelFormat>(ptr->format);
+                    break;
+                }
+                ++ptr;
+            }
+        }
+
+        return targetCfg;
+    }
 
     sp<IEvsEnumerator>              pEnumerator;   // Every test needs access to the service
     std::vector<CameraDesc>         cameraInfo;    // Empty unless/until loadCameraList() is called
@@ -265,10 +292,6 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Open and close each camera twice
     for (auto&& cam: cameraInfo) {
         bool isLogicalCam = false;
@@ -278,8 +301,14 @@
             continue;
         }
 
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
         for (int pass = 0; pass < 2; pass++) {
-            sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg);
+            sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
             ASSERT_NE(pCam, nullptr);
 
             for (auto&& devName : devices) {
@@ -343,10 +372,6 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Open and close each camera twice
     for (auto&& cam: cameraInfo) {
         bool isLogicalCam = false;
@@ -356,10 +381,14 @@
             continue;
         }
 
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
         activeCameras.clear();
-        sp<IEvsCamera_1_1> pCam =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam, nullptr);
 
         // Store a camera handle for a clean-up
@@ -372,9 +401,7 @@
                                 }
         );
 
-        sp<IEvsCamera_1_1> pCam2 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam2 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam2, nullptr);
 
         // Store a camera handle for a clean-up
@@ -422,10 +449,6 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Test each reported camera
     for (auto&& cam: cameraInfo) {
         bool isLogicalCam = false;
@@ -435,9 +458,13 @@
             continue;
         }
 
-        sp<IEvsCamera_1_1> pCam =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
+        sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam, nullptr);
 
         // Store a camera handle for a clean-up
@@ -519,10 +546,6 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Test each reported camera
     for (auto&& cam: cameraInfo) {
         bool isLogicalCam = false;
@@ -532,9 +555,13 @@
             continue;
         }
 
-        sp<IEvsCamera_1_1> pCam =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
+        sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam, nullptr);
 
         // Store a camera handle for a clean-up
@@ -601,10 +628,6 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Request available display IDs
     uint8_t targetDisplayId = 0;
     pEnumerator->getDisplayIdList([&targetDisplayId](auto ids) {
@@ -642,9 +665,13 @@
             continue;
         }
 
-        sp<IEvsCamera_1_1> pCam =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
+        sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam, nullptr);
 
         // Store a camera handle for a clean-up
@@ -708,24 +735,22 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Test each reported camera
     for (auto&& cam: cameraInfo) {
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
         // Create two camera clients.
-        sp<IEvsCamera_1_1> pCam0 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam0 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam0, nullptr);
 
         // Store a camera handle for a clean-up
         activeCameras.push_back(pCam0);
 
-        sp<IEvsCamera_1_1> pCam1 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam1, nullptr);
 
         // Store a camera handle for a clean-up
@@ -812,10 +837,6 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Test each reported camera
     Return<EvsResult> result = EvsResult::OK;
     for (auto&& cam: cameraInfo) {
@@ -828,10 +849,14 @@
             continue;
         }
 
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
         // Create a camera client
-        sp<IEvsCamera_1_1> pCam =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam, nullptr);
 
         // Store a camera
@@ -961,10 +986,6 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Test each reported camera
     for (auto&& cam: cameraInfo) {
         bool isLogicalCam = false;
@@ -976,18 +997,20 @@
             continue;
         }
 
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
         // Create two camera clients.
-        sp<IEvsCamera_1_1> pCamPrimary =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCamPrimary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCamPrimary, nullptr);
 
         // Store a camera handle for a clean-up
         activeCameras.push_back(pCamPrimary);
 
-        sp<IEvsCamera_1_1> pCamSecondary =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCamSecondary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCamSecondary, nullptr);
 
         // Store a camera handle for a clean-up
@@ -1142,10 +1165,6 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Test each reported camera
     for (auto&& cam: cameraInfo) {
         bool isLogicalCam = false;
@@ -1157,18 +1176,20 @@
             continue;
         }
 
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
         // Create two camera clients.
-        sp<IEvsCamera_1_1> pCamPrimary =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCamPrimary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCamPrimary, nullptr);
 
         // Store a camera handle for a clean-up
         activeCameras.push_back(pCamPrimary);
 
-        sp<IEvsCamera_1_1> pCamSecondary =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCamSecondary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCamSecondary, nullptr);
 
         // Store a camera handle for a clean-up
@@ -1615,28 +1636,26 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Request exclusive access to the EVS display
     sp<IEvsDisplay_1_0> pDisplay = pEnumerator->openDisplay();
     ASSERT_NE(pDisplay, nullptr);
 
     // Test each reported camera
     for (auto&& cam: cameraInfo) {
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
         // Create two clients
-        sp<IEvsCamera_1_1> pCam0 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam0 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam0, nullptr);
 
         // Store a camera handle for a clean-up
         activeCameras.push_back(pCam0);
 
-        sp<IEvsCamera_1_1> pCam1 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam1, nullptr);
 
         // Store a camera handle for a clean-up
@@ -2001,7 +2020,7 @@
                  &streamCfgs)) {
             // Stream configurations are found in metadata
             RawStreamConfig *ptr = reinterpret_cast<RawStreamConfig *>(streamCfgs.data.i32);
-            for (unsigned idx = 0; idx < streamCfgs.count; idx += kStreamCfgSz) {
+            for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
                 if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
                     ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
 
@@ -2026,9 +2045,7 @@
             continue;
         }
 
-        sp<IEvsCamera_1_1> pCam =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam, nullptr);
 
         // Store a camera handle for a clean-up
@@ -2106,7 +2123,7 @@
                  &streamCfgs)) {
             // Stream configurations are found in metadata
             RawStreamConfig *ptr = reinterpret_cast<RawStreamConfig *>(streamCfgs.data.i32);
-            for (unsigned idx = 0; idx < streamCfgs.count; idx += kStreamCfgSz) {
+            for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
                 if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
                     ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
 
@@ -2132,9 +2149,7 @@
         }
 
         // Create the first camera client with a selected stream configuration.
-        sp<IEvsCamera_1_1> pCam0 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam0 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam0, nullptr);
 
         // Store a camera handle for a clean-up
@@ -2144,9 +2159,7 @@
         // configuration.
         int32_t id = targetCfg.id;
         targetCfg.id += 1;  // EVS manager sees only the stream id.
-        sp<IEvsCamera_1_1> pCam1 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_EQ(pCam1, nullptr);
 
         // Store a camera handle for a clean-up
@@ -2154,9 +2167,7 @@
 
         // Try again with same stream configuration.
         targetCfg.id = id;
-        pCam1 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg))
-            .withDefault(nullptr);
+        pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam1, nullptr);
 
         // Set up per-client frame receiver objects which will fire up its own thread
@@ -2258,52 +2269,23 @@
     LOG(INFO) << "Starting CameraStreamExternalBuffering test";
 
     // Arbitrary constant (should be > 1 and not too big)
-    static const unsigned int kBuffersToHold = 6;
+    static const unsigned int kBuffersToHold = 3;
 
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Acquire the graphics buffer allocator
     android::GraphicBufferAllocator& alloc(android::GraphicBufferAllocator::get());
     const auto usage =
             GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_OFTEN;
-    const auto format = HAL_PIXEL_FORMAT_RGBA_8888;
-    uint32_t width = 640;
-    uint32_t height = 360;
-    camera_metadata_entry_t streamCfgs;
 
     // Test each reported camera
     for (auto&& cam : cameraInfo) {
-        bool foundCfg = false;
-        if (!find_camera_metadata_entry(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()),
-                                        ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
-                                        &streamCfgs)) {
-            // Stream configurations are found in metadata
-            RawStreamConfig* ptr = reinterpret_cast<RawStreamConfig*>(streamCfgs.data.i32);
-
-            LOG(DEBUG) << __LINE__ << " start searching " << streamCfgs.count;
-            for (unsigned idx = 0; idx < streamCfgs.count; idx++) {
-                LOG(DEBUG) << "ptr->direction= " << ptr->direction
-                           << " ptr->format= " << ptr->format;
-                if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
-                    ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
-                    width = ptr->width;
-                    height = ptr->height;
-                    foundCfg = true;
-                    // Always use the 1st available configuration
-                    break;
-                }
-                ++ptr;
-            }
-        }
-
-        if (!foundCfg) {
-            LOG(INFO) << "No configuration found. Use default stream configurations.";
-        }
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
 
         // Allocate buffers to use
         hidl_vec<BufferDesc> buffers;
@@ -2312,8 +2294,11 @@
             unsigned pixelsPerLine;
             buffer_handle_t memHandle = nullptr;
             android::status_t result =
-                    alloc.allocate(width, height, format, 1, usage, &memHandle, &pixelsPerLine, 0,
-                                   "CameraStreamExternalBufferingTest");
+                    alloc.allocate(targetCfg.width, targetCfg.height,
+                                   (android::PixelFormat)targetCfg.format,
+                                   /* layerCount = */ 1, usage, &memHandle, &pixelsPerLine,
+                                   /* graphicBufferId = */ 0,
+                                   /* requestorName = */ "CameraStreamExternalBufferingTest");
             if (result != android::NO_ERROR) {
                 LOG(ERROR) << __FUNCTION__ << " failed to allocate memory.";
                 // Release previous allocated buffers
@@ -2325,10 +2310,10 @@
                 BufferDesc buf;
                 AHardwareBuffer_Desc* pDesc =
                         reinterpret_cast<AHardwareBuffer_Desc*>(&buf.buffer.description);
-                pDesc->width = width;
-                pDesc->height = height;
+                pDesc->width = targetCfg.width;
+                pDesc->height = targetCfg.height;
                 pDesc->layers = 1;
-                pDesc->format = format;
+                pDesc->format = static_cast<uint32_t>(targetCfg.format);
                 pDesc->usage = usage;
                 pDesc->stride = pixelsPerLine;
                 buf.buffer.nativeHandle = memHandle;
@@ -2340,9 +2325,7 @@
         bool isLogicalCam = false;
         getPhysicalCameraIds(cam.v1.cameraId, isLogicalCam);
 
-        sp<IEvsCamera_1_1> pCam =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam, nullptr);
 
         // Store a camera handle for a clean-up
@@ -2362,7 +2345,7 @@
         }
 
         EXPECT_EQ(result, EvsResult::OK);
-        EXPECT_GE(delta, 0);
+        EXPECT_GE(delta, kBuffersToHold);
 
         // Set up a frame receiver object which will fire up its own thread.
         sp<FrameHandler> frameHandler = new FrameHandler(pCam, cam,
@@ -2378,7 +2361,7 @@
         sleep(1);   // 1 second should be enough for at least 5 frames to be delivered worst case
         unsigned framesReceived = 0;
         frameHandler->getFramesCounters(&framesReceived, nullptr);
-        ASSERT_EQ(kBuffersToHold, framesReceived) << "Stream didn't stall at expected buffer limit";
+        ASSERT_LE(kBuffersToHold, framesReceived) << "Stream didn't stall at expected buffer limit";
 
 
         // Give back one buffer
@@ -2387,9 +2370,10 @@
 
         // Once we return a buffer, it shouldn't take more than 1/10 second to get a new one
         // filled since we require 10fps minimum -- but give a 10% allowance just in case.
+        unsigned framesReceivedAfter = 0;
         usleep(110 * kMillisecondsToMicroseconds);
-        frameHandler->getFramesCounters(&framesReceived, nullptr);
-        EXPECT_EQ(kBuffersToHold+1, framesReceived) << "Stream should've resumed";
+        frameHandler->getFramesCounters(&framesReceivedAfter, nullptr);
+        EXPECT_EQ(framesReceived + 1, framesReceivedAfter) << "Stream should've resumed";
 
         // Even when the camera pointer goes out of scope, the FrameHandler object will
         // keep the stream alive unless we tell it to shutdown.
diff --git a/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp b/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp
index 583a455..58423c8 100644
--- a/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp
+++ b/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <fuzzer/FuzzedDataProvider.h>
 #include <cmath>
 #include <cstdlib>
 #include <cstring>
@@ -21,36 +22,43 @@
 #include "FormatConvert.h"
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, std::size_t size) {
-    if (size < 256) {
+    // 1 random value (4bytes) + min imagesize = 16*2 times bytes per pixel (worse case 2)
+    if (size < (4 + 16 * 2 * 2)) {
         return 0;
     }
+    FuzzedDataProvider fdp(data, size);
+    std::size_t image_pixel_size = size - 4;
+    image_pixel_size = (image_pixel_size & INT_MAX) / 2;
 
-    std::srand(std::time(nullptr));  // use current time as seed for random generator
-    int random_variable = std::rand() % 10;
-    int width = (int)sqrt(size);
-    int height = width * ((float)random_variable / 10.0);
+    // API have a requirement that width must be divied by 16 except yuyvtorgb
+    int min_height = 2;
+    int max_height = (image_pixel_size / 16) & ~(1);  // must be even number
+    int height = fdp.ConsumeIntegralInRange<uint32_t>(min_height, max_height);
+    int width = (image_pixel_size / height) & ~(16);  // must be divisible by 16
 
-    uint8_t* src = (uint8_t*)malloc(sizeof(uint8_t) * size);
-    memcpy(src, data, sizeof(uint8_t) * (size));
-    uint32_t* tgt = (uint32_t*)malloc(sizeof(uint32_t) * size);
+    uint8_t* src = (uint8_t*)(data + 4);
+    uint32_t* tgt = (uint32_t*)malloc(sizeof(uint32_t) * image_pixel_size);
 
 #ifdef COPY_NV21_TO_RGB32
-    android::hardware::automotive::evs::common::Utils::copyNV21toRGB32(width, height, src, tgt, 0);
+    android::hardware::automotive::evs::common::Utils::copyNV21toRGB32(width, height, src, tgt,
+                                                                       width);
 #elif COPY_NV21_TO_BGR32
-    android::hardware::automotive::evs::common::Utils::copyNV21toBGR32(width, height, src, tgt, 0);
+    android::hardware::automotive::evs::common::Utils::copyNV21toBGR32(width, height, src, tgt,
+                                                                       width);
 #elif COPY_YV12_TO_RGB32
-    android::hardware::automotive::evs::common::Utils::copyYV12toRGB32(width, height, src, tgt, 0);
+    android::hardware::automotive::evs::common::Utils::copyYV12toRGB32(width, height, src, tgt,
+                                                                       width);
 #elif COPY_YV12_TO_BGR32
-    android::hardware::automotive::evs::common::Utils::copyYV12toBGR32(width, height, src, tgt, 0);
+    android::hardware::automotive::evs::common::Utils::copyYV12toBGR32(width, height, src, tgt,
+                                                                       width);
 #elif COPY_YUYV_TO_RGB32
-    android::hardware::automotive::evs::common::Utils::copyYUYVtoRGB32(width, height, src, 0, tgt,
-                                                                       0);
+    android::hardware::automotive::evs::common::Utils::copyYUYVtoRGB32(width, height, src, width,
+                                                                       tgt, width);
 #elif COPY_YUYV_TO_BGR32
-    android::hardware::automotive::evs::common::Utils::copyYUYVtoBGR32(width, height, src, 0, tgt,
-                                                                       0);
+    android::hardware::automotive::evs::common::Utils::copyYUYVtoBGR32(width, height, src, width,
+                                                                       tgt, width);
 #endif
 
-    free(src);
     free(tgt);
 
     return 0;
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index ffa0c13..0b49ef9 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -182,6 +182,7 @@
     ],
     shared_libs: [
         "libbase",
+        "libcutils",
     ],
     header_libs: ["libbase_headers"],
     test_suites: ["general-tests"],
diff --git a/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc b/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc
index c8c89dc..44f9134 100644
--- a/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc
+++ b/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc
@@ -1,4 +1,4 @@
 service vendor.vehicle-hal-2.0 /vendor/bin/hw/android.hardware.automotive.vehicle@2.0-service
-    class hal
+    class early_hal
     user vehicle_network
     group system inet
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h
index fcfe761..6706258 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h
@@ -76,6 +76,9 @@
     Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
 
   private:
+    // Set unit test class as friend class to test private functions.
+    friend class VehicleHalManagerTestHelper;
+
     using VehiclePropValuePtr = VehicleHal::VehiclePropValuePtr;
     // Returns true if needs to call again shortly.
     using RetriableAction = std::function<bool()>;
@@ -105,14 +108,20 @@
     void cmdDumpOneProperty(int fd, int32_t prop, int32_t areaId);
     void cmdDumpOneProperty(int fd, int rowNumber, const VehiclePropConfig& config);
 
+    bool cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options);
+
     static bool checkArgumentsSize(int fd, const hidl_vec<hidl_string>& options, size_t minSize);
     static bool checkCallerHasWritePermissions(int fd);
-    static bool safelyParseInt(int fd, int index, std::string s, int* out);
+    template <typename T>
+    static bool safelyParseInt(int fd, int index, const std::string& s, T* out);
+    static bool safelyParseFloat(int fd, int index, const std::string& s, float* out);
+    // Parses "s" as a hex string and populate "*bytes". The hex string must be in the format of
+    // valid hex format, e.g. "0xABCD".
+    static bool parseHexString(int fd, const std::string& s, std::vector<uint8_t>* bytes);
     void cmdHelp(int fd) const;
     void cmdListAllProperties(int fd) const;
     void cmdDumpAllProperties(int fd);
     void cmdDumpSpecificProperties(int fd, const hidl_vec<hidl_string>& options);
-    void cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options);
 
     static bool isSubscribable(const VehiclePropConfig& config,
                                SubscribeFlags flags);
@@ -120,7 +129,18 @@
     static float checkSampleRate(const VehiclePropConfig& config,
                                  float sampleRate);
     static ClientId getClientId(const sp<IVehicleCallback>& callback);
-private:
+
+    // Parses the cmdline options for "--set" command. "*prop" would be populated with the
+    // the properties to be set. Returns true when the cmdline options are valid, false otherwise.
+    static bool parseSetPropOptions(int fd, const hidl_vec<hidl_string>& options,
+                                    VehiclePropValue* prop);
+    // Parses the options and get the values for the current option specified by "*index". "*index"
+    // would advance to the next option field (e.g., the next "-f"). Returns a list of values for
+    // the current option.
+    static std::vector<std::string> getOptionValues(const hidl_vec<hidl_string>& options,
+                                                    size_t* index);
+
+  private:
     VehicleHal* mHal;
     std::unique_ptr<VehiclePropConfigIndex> mConfigIndex;
     SubscriptionManager mSubscriptionManager;
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
index dc5d3d3..e34e692 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
@@ -20,7 +20,9 @@
 
 #include <cmath>
 #include <fstream>
+#include <unordered_set>
 
+#include <android-base/parsedouble.h>
 #include <android-base/parseint.h>
 #include <android-base/strings.h>
 #include <android/hardware/automotive/vehicle/2.0/BpHwVehicleCallback.h>
@@ -44,15 +46,34 @@
 using ::android::hardware::hidl_handle;
 using ::android::hardware::hidl_string;
 
+namespace {
+
 constexpr std::chrono::milliseconds kHalEventBatchingTimeWindow(10);
 
 const VehiclePropValue kEmptyValue{};
 
+// A list of supported options for "--set" command.
+const std::unordered_set<std::string> kSetPropOptions = {
+        // integer.
+        "-i",
+        // 64bit integer.
+        "-i64",
+        // float.
+        "-f",
+        // string.
+        "-s",
+        // bytes in hex format, e.g. 0xDEADBEEF.
+        "-b",
+        // Area id in integer.
+        "-a"};
+
+}  // namespace
+
 /**
  * Indicates what's the maximum size of hidl_vec<VehiclePropValue> we want
  * to store in reusable object pool.
  */
-constexpr auto kMaxHidlVecOfVehiclPropValuePoolSize = 20;
+constexpr auto kMaxHidlVecOfVehiclePropValuePoolSize = 20;
 
 Return<void> VehicleHalManager::getAllPropConfigs(getAllPropConfigs_cb _hidl_cb) {
     ALOGI("getAllPropConfigs called");
@@ -213,6 +234,11 @@
     } else if (EqualsIgnoreCase(option, "--get")) {
         cmdDumpSpecificProperties(fd, options);
     } else if (EqualsIgnoreCase(option, "--set")) {
+        if (!checkCallerHasWritePermissions(fd)) {
+            dprintf(fd, "Caller does not have write permission\n");
+            return;
+        }
+        // Ignore the return value for this.
         cmdSetOneProperty(fd, options);
     } else {
         dprintf(fd, "Invalid option: %s\n", option.c_str());
@@ -239,7 +265,8 @@
     return false;
 }
 
-bool VehicleHalManager::safelyParseInt(int fd, int index, std::string s, int* out) {
+template <typename T>
+bool VehicleHalManager::safelyParseInt(int fd, int index, const std::string& s, T* out) {
     if (!android::base::ParseInt(s, out)) {
         dprintf(fd, "non-integer argument at index %d: %s\n", index, s.c_str());
         return false;
@@ -247,19 +274,27 @@
     return true;
 }
 
+bool VehicleHalManager::safelyParseFloat(int fd, int index, const std::string& s, float* out) {
+    if (!android::base::ParseFloat(s, out)) {
+        dprintf(fd, "non-float argument at index %d: %s\n", index, s.c_str());
+        return false;
+    }
+    return true;
+}
+
 void VehicleHalManager::cmdHelp(int fd) const {
     dprintf(fd, "Usage: \n\n");
     dprintf(fd, "[no args]: dumps (id and value) all supported properties \n");
     dprintf(fd, "--help: shows this help\n");
     dprintf(fd, "--list: lists the ids of all supported properties\n");
     dprintf(fd, "--get <PROP1> [PROP2] [PROPN]: dumps the value of specific properties \n");
-    // TODO: support other formats (int64, float, bytes)
     dprintf(fd,
-            "--set <PROP> <i|s> <VALUE_1> [<i|s> <VALUE_N>] [a AREA_ID] : sets the value of "
-            "property PROP, using arbitrary number of key/value parameters (i for int32, "
-            "s for string) and an optional area.\n"
-            "Notice that the string value can be set just once, while the other can have multiple "
-            "values (so they're used in the respective array)\n");
+            "--set <PROP> [-i INT_VALUE [INT_VALUE ...]] [-i64 INT64_VALUE [INT64_VALUE ...]] "
+            "[-f FLOAT_VALUE [FLOAT_VALUE ...]] [-s STR_VALUE] "
+            "[-b BYTES_VALUE] [-a AREA_ID] : sets the value of property PROP. "
+            "Notice that the string, bytes and area value can be set just once, while the other can"
+            " have multiple values (so they're used in the respective array), "
+            "BYTES_VALUE is in the form of 0xXXXX, e.g. 0xdeadbeef.\n");
 }
 
 void VehicleHalManager::cmdListAllProperties(int fd) const {
@@ -337,102 +372,49 @@
     VehiclePropValue input;
     input.prop = prop;
     input.areaId = areaId;
-    auto callback = [&](StatusCode status, const VehiclePropValue& output) {
+    auto callback = [&fd, &prop](StatusCode status, const VehiclePropValue& output) {
         if (status == StatusCode::OK) {
             dprintf(fd, "%s\n", toString(output).c_str());
         } else {
             dprintf(fd, "Could not get property %d. Error: %s\n", prop, toString(status).c_str());
         }
     };
-    get(input, callback);
+
+    StatusCode status;
+    auto value = mHal->get(input, &status);
+    callback(status, value.get() ? *value : kEmptyValue);
 }
 
-void VehicleHalManager::cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
-    if (!checkCallerHasWritePermissions(fd) || !checkArgumentsSize(fd, options, 3)) return;
-
-    size_t size = options.size();
-
-    // Syntax is --set PROP Type1 Value1 TypeN ValueN, so number of arguments must be even
-    if (size % 2 != 0) {
-        dprintf(fd, "must pass even number of arguments (passed %zu)\n", size);
-        return;
+bool VehicleHalManager::cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
+    if (!checkArgumentsSize(fd, options, 4)) {
+        dprintf(fd, "Requires at least 4 options, see help\n");
+        return false;
     }
-    int numberValues = (size - 2) / 2;
 
-    VehiclePropValue prop;
-    if (!safelyParseInt(fd, 1, options[1], &prop.prop)) return;
-    prop.timestamp = elapsedRealtimeNano();
-    prop.status = VehiclePropertyStatus::AVAILABLE;
-
-    // First pass: calculate sizes
-    int sizeInt32 = 0;
-    int stringIndex = 0;
-    int areaIndex = 0;
-    for (int i = 2, kv = 1; kv <= numberValues; kv++) {
-        // iterate through the kv=1..n key/value pairs, accessing indexes i / i+1 at each step
-        std::string type = options[i];
-        std::string value = options[i + 1];
-        if (EqualsIgnoreCase(type, "i")) {
-            sizeInt32++;
-        } else if (EqualsIgnoreCase(type, "s")) {
-            if (stringIndex != 0) {
-                dprintf(fd,
-                        "defining string value (%s) again at index %d (already defined at %d=%s"
-                        ")\n",
-                        value.c_str(), i, stringIndex, options[stringIndex + 1].c_str());
-                return;
-            }
-            stringIndex = i;
-        } else if (EqualsIgnoreCase(type, "a")) {
-            if (areaIndex != 0) {
-                dprintf(fd,
-                        "defining area value (%s) again at index %d (already defined at %d=%s"
-                        ")\n",
-                        value.c_str(), i, areaIndex, options[areaIndex + 1].c_str());
-                return;
-            }
-            areaIndex = i;
-        } else {
-            dprintf(fd, "invalid (%s) type at index %d\n", type.c_str(), i);
-            return;
-        }
-        i += 2;
-    }
-    prop.value.int32Values.resize(sizeInt32);
-
-    // Second pass: populate it
-    int indexInt32 = 0;
-    for (int i = 2, kv = 1; kv <= numberValues; kv++) {
-        // iterate through the kv=1..n key/value pairs, accessing indexes i / i+1 at each step
-        int valueIndex = i + 1;
-        std::string type = options[i];
-        std::string value = options[valueIndex];
-        if (EqualsIgnoreCase(type, "i")) {
-            int safeInt;
-            if (!safelyParseInt(fd, valueIndex, value, &safeInt)) return;
-            prop.value.int32Values[indexInt32++] = safeInt;
-        } else if (EqualsIgnoreCase(type, "s")) {
-            prop.value.stringValue = value;
-        } else if (EqualsIgnoreCase(type, "a")) {
-            if (!safelyParseInt(fd, valueIndex, value, &prop.areaId)) return;
-        }
-        i += 2;
+    VehiclePropValue prop = {};
+    if (!parseSetPropOptions(fd, options, &prop)) {
+        return false;
     }
     ALOGD("Setting prop %s", toString(prop).c_str());
-    auto status = set(prop);
+
+    // Do not use VehicleHalManager::set here because we don't want to check write permission.
+    // Caller should be able to use the debug interface to set read-only properties.
+    handlePropertySetEvent(prop);
+    auto status = mHal->set(prop);
+
     if (status == StatusCode::OK) {
         dprintf(fd, "Set property %s\n", toString(prop).c_str());
-    } else {
-        dprintf(fd, "Failed to set property %s: %s\n", toString(prop).c_str(),
-                toString(status).c_str());
+        return true;
     }
+    dprintf(fd, "Failed to set property %s: %s\n", toString(prop).c_str(),
+            toString(status).c_str());
+    return false;
 }
 
 void VehicleHalManager::init() {
     ALOGI("VehicleHalManager::init");
 
-    mHidlVecOfVehiclePropValuePool.resize(kMaxHidlVecOfVehiclPropValuePoolSize);
-
+    mHidlVecOfVehiclePropValuePool.resize(kMaxHidlVecOfVehiclePropValuePoolSize);
 
     mBatchingConsumer.run(&mEventQueue,
                           kHalEventBatchingTimeWindow,
@@ -486,7 +468,7 @@
     for (const HalClientValues& cv : clientValues) {
         auto vecSize = cv.values.size();
         hidl_vec<VehiclePropValue> vec;
-        if (vecSize < kMaxHidlVecOfVehiclPropValuePoolSize) {
+        if (vecSize < kMaxHidlVecOfVehiclePropValuePoolSize) {
             vec.setToExternal(&mHidlVecOfVehiclePropValuePool[0], vecSize);
         } else {
             vec.resize(vecSize);
@@ -595,6 +577,158 @@
     }
 }
 
+std::vector<std::string> VehicleHalManager::getOptionValues(const hidl_vec<hidl_string>& options,
+                                                            size_t* index) {
+    std::vector<std::string> values;
+    while (*index < options.size()) {
+        std::string option = options[*index];
+        if (kSetPropOptions.find(option) != kSetPropOptions.end()) {
+            return std::move(values);
+        }
+        values.push_back(option);
+        (*index)++;
+    }
+    return std::move(values);
+}
+
+bool VehicleHalManager::parseSetPropOptions(int fd, const hidl_vec<hidl_string>& options,
+                                            VehiclePropValue* prop) {
+    // Options format:
+    // --set PROP [-f f1 f2...] [-i i1 i2...] [-i64 i1 i2...] [-s s1 s2...] [-b b1 b2...] [-a a]
+    size_t optionIndex = 1;
+    int propValue;
+    if (!safelyParseInt(fd, optionIndex, options[optionIndex], &propValue)) {
+        dprintf(fd, "property value: \"%s\" is not a valid int\n", options[optionIndex].c_str());
+        return false;
+    }
+    prop->prop = propValue;
+    prop->timestamp = elapsedRealtimeNano();
+    prop->status = VehiclePropertyStatus::AVAILABLE;
+    optionIndex++;
+    std::unordered_set<std::string> parsedOptions;
+
+    while (optionIndex < options.size()) {
+        std::string type = options[optionIndex];
+        optionIndex++;
+        size_t currentIndex = optionIndex;
+        std::vector<std::string> values = getOptionValues(options, &optionIndex);
+        if (parsedOptions.find(type) != parsedOptions.end()) {
+            dprintf(fd, "duplicate \"%s\" options\n", type.c_str());
+            return false;
+        }
+        parsedOptions.insert(type);
+        if (EqualsIgnoreCase(type, "-i")) {
+            if (values.size() == 0) {
+                dprintf(fd, "no values specified when using \"-i\"\n");
+                return false;
+            }
+            prop->value.int32Values.resize(values.size());
+            for (size_t i = 0; i < values.size(); i++) {
+                int32_t safeInt;
+                if (!safelyParseInt(fd, currentIndex + i, values[i], &safeInt)) {
+                    dprintf(fd, "value: \"%s\" is not a valid int\n", values[i].c_str());
+                    return false;
+                }
+                prop->value.int32Values[i] = safeInt;
+            }
+        } else if (EqualsIgnoreCase(type, "-i64")) {
+            if (values.size() == 0) {
+                dprintf(fd, "no values specified when using \"-i64\"\n");
+                return false;
+            }
+            prop->value.int64Values.resize(values.size());
+            for (size_t i = 0; i < values.size(); i++) {
+                int64_t safeInt;
+                if (!safelyParseInt(fd, currentIndex + i, values[i], &safeInt)) {
+                    dprintf(fd, "value: \"%s\" is not a valid int64\n", values[i].c_str());
+                    return false;
+                }
+                prop->value.int64Values[i] = safeInt;
+            }
+        } else if (EqualsIgnoreCase(type, "-f")) {
+            if (values.size() == 0) {
+                dprintf(fd, "no values specified when using \"-f\"\n");
+                return false;
+            }
+            prop->value.floatValues.resize(values.size());
+            for (size_t i = 0; i < values.size(); i++) {
+                float safeFloat;
+                if (!safelyParseFloat(fd, currentIndex + i, values[i], &safeFloat)) {
+                    dprintf(fd, "value: \"%s\" is not a valid float\n", values[i].c_str());
+                    return false;
+                }
+                prop->value.floatValues[i] = safeFloat;
+            }
+        } else if (EqualsIgnoreCase(type, "-s")) {
+            if (values.size() != 1) {
+                dprintf(fd, "expect exact one value when using \"-s\"\n");
+                return false;
+            }
+            prop->value.stringValue = values[0];
+        } else if (EqualsIgnoreCase(type, "-b")) {
+            if (values.size() != 1) {
+                dprintf(fd, "expect exact one value when using \"-b\"\n");
+                return false;
+            }
+            std::vector<uint8_t> bytes;
+            if (!parseHexString(fd, values[0], &bytes)) {
+                dprintf(fd, "value: \"%s\" is not a valid hex string\n", values[0].c_str());
+                return false;
+            }
+            prop->value.bytes = bytes;
+        } else if (EqualsIgnoreCase(type, "-a")) {
+            if (values.size() != 1) {
+                dprintf(fd, "expect exact one value when using \"-a\"\n");
+                return false;
+            }
+            if (!safelyParseInt(fd, currentIndex, values[0], &(prop->areaId))) {
+                dprintf(fd, "area ID: \"%s\" is not a valid int\n", values[0].c_str());
+                return false;
+            }
+        } else {
+            dprintf(fd, "unknown option: %s\n", type.c_str());
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool VehicleHalManager::parseHexString(int fd, const std::string& s, std::vector<uint8_t>* bytes) {
+    if (s.size() % 2 != 0) {
+        dprintf(fd, "invalid hex string: %s, should have even size\n", s.c_str());
+        return false;
+    }
+    if (strncmp(s.substr(0, 2).c_str(), "0x", 2)) {
+        dprintf(fd, "hex string should start with \"0x\", got %s\n", s.c_str());
+        return false;
+    }
+    std::string subs = s.substr(2);
+    std::transform(subs.begin(), subs.end(), subs.begin(),
+                   [](unsigned char c) { return std::tolower(c); });
+
+    bool highDigit = true;
+    for (size_t i = 0; i < subs.size(); i++) {
+        char c = subs[i];
+        uint8_t v;
+        if (c >= '0' && c <= '9') {
+            v = c - '0';
+        } else if (c >= 'a' && c <= 'f') {
+            v = c - 'a' + 10;
+        } else {
+            dprintf(fd, "invalid character %c in hex string %s\n", c, subs.c_str());
+            return false;
+        }
+        if (highDigit) {
+            (*bytes).push_back(v * 16);
+        } else {
+            (*bytes)[bytes->size() - 1] += v;
+        }
+        highDigit = !highDigit;
+    }
+    return true;
+}
+
 }  // namespace V2_0
 }  // namespace vehicle
 }  // namespace automotive
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index 8ff4924..55617be 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -307,6 +307,18 @@
                          .prop = toInt(VehicleProperty::CRITICALLY_LOW_TIRE_PRESSURE),
                          .access = VehiclePropertyAccess::READ,
                          .changeMode = VehiclePropertyChangeMode::STATIC,
+                         .areaConfigs = {VehicleAreaConfig{
+                                                 .areaId = WHEEL_FRONT_LEFT,
+                                         },
+                                         VehicleAreaConfig{
+                                                 .areaId = WHEEL_FRONT_RIGHT,
+                                         },
+                                         VehicleAreaConfig{
+                                                 .areaId = WHEEL_REAR_LEFT,
+                                         },
+                                         VehicleAreaConfig{
+                                                 .areaId = WHEEL_REAR_RIGHT,
+                                         }},
                  },
          .initialAreaValues = {{WHEEL_FRONT_LEFT, {.floatValues = {137.0f}}},
                                {WHEEL_FRONT_RIGHT, {.floatValues = {137.0f}}},
@@ -1032,14 +1044,6 @@
         {
                 .config =
                         {
-                                .prop = toInt(VehicleProperty::STORAGE_ENCRYPTION_BINDING_SEED),
-                                .access = VehiclePropertyAccess::READ_WRITE,
-                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-                        },
-        },
-        {
-                .config =
-                        {
                                 .prop = toInt(VehicleProperty::WATCHDOG_ALIVE),
                                 .access = VehiclePropertyAccess::WRITE,
                                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -1105,6 +1109,42 @@
                                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                         },
         },
+        {
+                .config =
+                        {
+                                .prop = PLACEHOLDER_PROPERTY_INT,
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+                .initialValue = {.int32Values = {0}},
+        },
+        {
+                .config =
+                        {
+                                .prop = PLACEHOLDER_PROPERTY_FLOAT,
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+                .initialValue = {.floatValues = {0.0f}},
+        },
+        {
+                .config =
+                        {
+                                .prop = PLACEHOLDER_PROPERTY_BOOLEAN,
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+                .initialValue = {.int32Values = {0 /* false */}},
+        },
+        {
+                .config =
+                        {
+                                .prop = PLACEHOLDER_PROPERTY_STRING,
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+                .initialValue = {.stringValue = {"Test"}},
+        },
 #ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
         // Vendor propetry for E2E ClusterHomeService testing.
         {
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h
index d5f6a18..51251a7 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h
@@ -189,6 +189,19 @@
     KeyPress = 100,
 };
 
+/**
+ * These properties are placeholder properties for developers to test new features without
+ * implementing a real property.
+ */
+constexpr int32_t PLACEHOLDER_PROPERTY_INT =
+        0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::INT32;
+constexpr int32_t PLACEHOLDER_PROPERTY_FLOAT =
+        0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::FLOAT;
+constexpr int32_t PLACEHOLDER_PROPERTY_BOOLEAN =
+        0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::BOOLEAN;
+constexpr int32_t PLACEHOLDER_PROPERTY_STRING =
+        0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::STRING;
+
 const int32_t kHvacPowerProperties[] = {
     toInt(VehicleProperty::HVAC_FAN_SPEED),
     toInt(VehicleProperty::HVAC_FAN_DIRECTION),
diff --git a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
index 0975071..bdf46fb 100644
--- a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
@@ -18,6 +18,7 @@
 #include <iostream>
 
 #include <android-base/macros.h>
+#include <cutils/native_handle.h>
 #include <utils/SystemClock.h>
 
 #include <gtest/gtest.h>
@@ -32,6 +33,18 @@
 namespace vehicle {
 namespace V2_0 {
 
+// A simple helper class to expose 'cmdSetOneProperty' to the unit tests.
+class VehicleHalManagerTestHelper {
+  public:
+    VehicleHalManagerTestHelper(VehicleHalManager* manager) { mManager = manager; }
+    bool cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
+        return mManager->cmdSetOneProperty(fd, options);
+    }
+
+  public:
+    VehicleHalManager* mManager;
+};
+
 namespace {
 
 using namespace std::placeholders;
@@ -57,33 +70,21 @@
         auto property = static_cast<VehicleProperty>(requestedPropValue.prop);
         int32_t areaId = requestedPropValue.areaId;
 
-        switch (property) {
-            case VehicleProperty::INFO_MAKE:
-                pValue = getValuePool()->obtainString(kCarMake);
-                break;
-            case VehicleProperty::INFO_FUEL_CAPACITY:
-                if (fuelCapacityAttemptsLeft-- > 0) {
-                    // Emulate property not ready yet.
-                    *outStatus = StatusCode::TRY_AGAIN;
-                } else {
-                    pValue = getValuePool()->obtainFloat(42.42);
-                }
-                break;
-            default:
-                if (requestedPropValue.prop == kCustomComplexProperty) {
-                    pValue = getValuePool()->obtainComplex();
-                    pValue->value.int32Values = hidl_vec<int32_t> { 10, 20 };
-                    pValue->value.int64Values = hidl_vec<int64_t> { 30, 40 };
-                    pValue->value.floatValues = hidl_vec<float_t> { 1.1, 2.2 };
-                    pValue->value.bytes = hidl_vec<uint8_t> { 1, 2, 3 };
-                    pValue->value.stringValue = kCarMake;
-                    break;
-                }
-                auto key = makeKey(toInt(property), areaId);
-                if (mValues.count(key) == 0) {
-                    ALOGW("");
-                }
-                pValue = getValuePool()->obtain(mValues[key]);
+        if (property == VehicleProperty::INFO_FUEL_CAPACITY) {
+            if (fuelCapacityAttemptsLeft-- > 0) {
+                // Emulate property not ready yet.
+                *outStatus = StatusCode::TRY_AGAIN;
+            } else {
+                pValue = getValuePool()->obtainFloat(42.42);
+            }
+        } else {
+            auto key = makeKey(requestedPropValue);
+            if (mValues.count(key) == 0) {
+                ALOGW("key not found\n");
+                *outStatus = StatusCode::INVALID_ARG;
+                return pValue;
+            }
+            pValue = getValuePool()->obtain(mValues[key]);
         }
 
         if (*outStatus == StatusCode::OK && pValue.get() != nullptr) {
@@ -100,7 +101,6 @@
                 && mirrorFoldAttemptsLeft-- > 0) {
             return StatusCode::TRY_AGAIN;
         }
-
         mValues[makeKey(propValue)] = propValue;
         return StatusCode::OK;
     }
@@ -181,6 +181,18 @@
         actualStatusCode = refStatus;
     }
 
+    MockedVehicleHal::VehiclePropValuePtr getComplexProperty() {
+        auto pValue = objectPool->obtainComplex();
+        pValue->prop = kCustomComplexProperty;
+        pValue->areaId = 0;
+        pValue->value.int32Values = hidl_vec<int32_t>{10, 20};
+        pValue->value.int64Values = hidl_vec<int64_t>{30, 40};
+        pValue->value.floatValues = hidl_vec<float_t>{1.1, 2.2};
+        pValue->value.bytes = hidl_vec<uint8_t>{1, 2, 3};
+        pValue->value.stringValue = kCarMake;
+        return pValue;
+    }
+
 public:
     VehiclePropValue actualValue;
     StatusCode actualStatusCode;
@@ -308,6 +320,8 @@
 }
 
 TEST_F(VehicleHalManagerTest, get_Complex) {
+    ASSERT_EQ(StatusCode::OK, hal->set(*getComplexProperty().get()));
+
     invokeGet(kCustomComplexProperty, 0);
 
     ASSERT_EQ(StatusCode::OK, actualStatusCode);
@@ -334,6 +348,11 @@
 }
 
 TEST_F(VehicleHalManagerTest, get_StaticString) {
+    auto pValue = objectPool->obtainString(kCarMake);
+    pValue->prop = toInt(VehicleProperty::INFO_MAKE);
+    pValue->areaId = 0;
+    ASSERT_EQ(StatusCode::OK, hal->set(*pValue.get()));
+
     invokeGet(toInt(VehicleProperty::INFO_MAKE), 0);
 
     ASSERT_EQ(StatusCode::OK, actualStatusCode);
@@ -458,6 +477,138 @@
     ASSERT_TRUE(clients.isEmpty());
 }
 
+TEST_F(VehicleHalManagerTest, debug) {
+    hidl_handle fd = {};
+    fd.setTo(native_handle_create(/*numFds=*/1, /*numInts=*/0), /*shouldOwn=*/true);
+
+    // Because debug function returns void, so no way to check return value.
+    manager->debug(fd, {});
+    manager->debug(fd, {"--help"});
+    manager->debug(fd, {"--list"});
+    manager->debug(fd, {"--get"});
+    manager->debug(fd, {"--set"});
+    manager->debug(fd, {"invalid"});
+}
+
+struct SetPropTestCase {
+    std::string test_name;
+    const hidl_vec<hidl_string> configs;
+    bool success;
+};
+
+class VehicleHalManagerSetPropTest : public VehicleHalManagerTest,
+                                     public testing::WithParamInterface<SetPropTestCase> {};
+
+TEST_P(VehicleHalManagerSetPropTest, cmdSetOneProperty) {
+    const SetPropTestCase& tc = GetParam();
+    VehicleHalManagerTestHelper helper(manager.get());
+    ASSERT_EQ(tc.success, helper.cmdSetOneProperty(STDERR_FILENO, tc.configs));
+}
+
+std::vector<SetPropTestCase> GenSetPropParams() {
+    char infoMakeProperty[100] = {};
+    snprintf(infoMakeProperty, sizeof(infoMakeProperty), "%d", toInt(VehicleProperty::INFO_MAKE));
+    return {
+            {"success_set_string", {"--set", infoMakeProperty, "-s", kCarMake}, true},
+            {"success_set_bytes", {"--set", infoMakeProperty, "-b", "0xdeadbeef"}, true},
+            {"success_set_bytes_caps", {"--set", infoMakeProperty, "-b", "0xDEADBEEF"}, true},
+            {"success_set_int", {"--set", infoMakeProperty, "-i", "2147483647"}, true},
+            {"success_set_ints",
+             {"--set", infoMakeProperty, "-i", "2147483647", "0", "-2147483648"},
+             true},
+            {"success_set_int64",
+             {"--set", infoMakeProperty, "-i64", "-9223372036854775808"},
+             true},
+            {"success_set_int64s",
+             {"--set", infoMakeProperty, "-i64", "-9223372036854775808", "0",
+              "9223372036854775807"},
+             true},
+            {"success_set_float", {"--set", infoMakeProperty, "-f", "1.175494351E-38"}, true},
+            {"success_set_floats",
+             {"--set", infoMakeProperty, "-f", "-3.402823466E+38", "0", "3.402823466E+38"},
+             true},
+            {"success_set_area", {"--set", infoMakeProperty, "-a", "2147483647"}, true},
+            {"fail_no_options", {}, false},
+            {"fail_less_than_4_options", {"--set", infoMakeProperty, "-i"}, false},
+            {"fail_unknown_options", {"--set", infoMakeProperty, "-s", kCarMake, "-abcd"}, false},
+            {"fail_invalid_property", {"--set", "not valid", "-s", kCarMake}, false},
+            {"fail_duplicate_string",
+             {"--set", infoMakeProperty, "-s", kCarMake, "-s", kCarMake},
+             false},
+            {"fail_multiple_strings", {"--set", infoMakeProperty, "-s", kCarMake, kCarMake}, false},
+            {"fail_no_string_value", {"--set", infoMakeProperty, "-s", "-a", "1234"}, false},
+            {"fail_duplicate_bytes",
+             {"--set", infoMakeProperty, "-b", "0xdeadbeef", "-b", "0xdeadbeef"},
+             false},
+            {"fail_multiple_bytes",
+             {"--set", infoMakeProperty, "-b", "0xdeadbeef", "0xdeadbeef"},
+             false},
+            {"fail_invalid_bytes", {"--set", infoMakeProperty, "-b", "0xgood"}, false},
+            {"fail_invalid_bytes_no_prefix", {"--set", infoMakeProperty, "-b", "deadbeef"}, false},
+            {"fail_invalid_int", {"--set", infoMakeProperty, "-i", "abc"}, false},
+            {"fail_int_out_of_range", {"--set", infoMakeProperty, "-i", "2147483648"}, false},
+            {"fail_no_int_value", {"--set", infoMakeProperty, "-i", "-s", kCarMake}, false},
+            {"fail_invalid_int64", {"--set", infoMakeProperty, "-i64", "abc"}, false},
+            {"fail_int64_out_of_range",
+             {"--set", infoMakeProperty, "-i64", "-9223372036854775809"},
+             false},
+            {"fail_no_int64_value", {"--set", infoMakeProperty, "-i64", "-s", kCarMake}, false},
+            {"fail_invalid_float", {"--set", infoMakeProperty, "-f", "abc"}, false},
+            {"fail_float_out_of_range",
+             {"--set", infoMakeProperty, "-f", "-3.402823466E+39"},
+             false},
+            {"fail_no_float_value", {"--set", infoMakeProperty, "-f", "-s", kCarMake}, false},
+            {"fail_multiple_areas", {"--set", infoMakeProperty, "-a", "2147483648", "0"}, false},
+            {"fail_invalid_area", {"--set", infoMakeProperty, "-a", "abc"}, false},
+            {"fail_area_out_of_range", {"--set", infoMakeProperty, "-a", "2147483648"}, false},
+            {"fail_no_area_value", {"--set", infoMakeProperty, "-a", "-s", kCarMake}, false},
+    };
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        VehicleHalManagerSetPropTests, VehicleHalManagerSetPropTest,
+        testing::ValuesIn(GenSetPropParams()),
+        [](const testing::TestParamInfo<VehicleHalManagerSetPropTest::ParamType>& info) {
+            return info.param.test_name;
+        });
+
+TEST_F(VehicleHalManagerTest, SetComplexPropTest) {
+    char infoMakeProperty[100] = {};
+    snprintf(infoMakeProperty, sizeof(infoMakeProperty), "%d", toInt(VehicleProperty::INFO_MAKE));
+    VehicleHalManagerTestHelper helper(manager.get());
+    ASSERT_TRUE(helper.cmdSetOneProperty(
+            STDERR_FILENO, {"--set", infoMakeProperty,      "-s",   kCarMake,
+                            "-b",    "0xdeadbeef",          "-i",   "2147483647",
+                            "0",     "-2147483648",         "-i64", "-9223372036854775808",
+                            "0",     "9223372036854775807", "-f",   "-3.402823466E+38",
+                            "0",     "3.402823466E+38",     "-a",   "123"}));
+    StatusCode status = StatusCode::OK;
+    VehiclePropValue requestProp;
+    requestProp.prop = toInt(VehicleProperty::INFO_MAKE);
+    requestProp.areaId = 123;
+    auto value = hal->get(requestProp, &status);
+    ASSERT_EQ(StatusCode::OK, status);
+    ASSERT_EQ(value->prop, toInt(VehicleProperty::INFO_MAKE));
+    ASSERT_EQ(value->areaId, 123);
+    ASSERT_STREQ(kCarMake, value->value.stringValue.c_str());
+    uint8_t bytes[] = {0xde, 0xad, 0xbe, 0xef};
+    ASSERT_FALSE(memcmp(bytes, value->value.bytes.data(), sizeof(bytes)));
+    ASSERT_EQ(3u, value->value.int32Values.size());
+    ASSERT_EQ(2147483647, value->value.int32Values[0]);
+    ASSERT_EQ(0, value->value.int32Values[1]);
+    ASSERT_EQ(-2147483648, value->value.int32Values[2]);
+    ASSERT_EQ(3u, value->value.int64Values.size());
+    // -9223372036854775808 is not a valid literal since '-' and '9223372036854775808' would be two
+    // tokens and the later does not fit in unsigned long long.
+    ASSERT_EQ(-9223372036854775807 - 1, value->value.int64Values[0]);
+    ASSERT_EQ(0, value->value.int64Values[1]);
+    ASSERT_EQ(9223372036854775807, value->value.int64Values[2]);
+    ASSERT_EQ(3u, value->value.floatValues.size());
+    ASSERT_EQ(-3.402823466E+38f, value->value.floatValues[0]);
+    ASSERT_EQ(0.0f, value->value.floatValues[1]);
+    ASSERT_EQ(3.402823466E+38f, value->value.floatValues[2]);
+}
+
 }  // namespace anonymous
 
 }  // namespace V2_0
diff --git a/automotive/vehicle/2.0/utils/UserHalHelper.cpp b/automotive/vehicle/2.0/utils/UserHalHelper.cpp
index abf59b7..dccdb2b 100644
--- a/automotive/vehicle/2.0/utils/UserHalHelper.cpp
+++ b/automotive/vehicle/2.0/utils/UserHalHelper.cpp
@@ -60,11 +60,22 @@
                        << int32Values.size();
     }
     userInfo->userId = int32Values[startPos];
-    auto userFlags = verifyAndCast<UserFlags>(int32Values[startPos + 1]);
-    if (!userFlags.ok()) {
-        return Error() << "Invalid user flags: " << userFlags.error();
+    int32_t intUserFlags = int32Values[startPos + 1];
+    int32_t expectedUserFlags = 0;
+    for (const auto& v : hidl_enum_range<UserFlags>()) {
+        int32_t intEnumUserFlag = static_cast<int32_t>(v);
+        if ((intUserFlags & intEnumUserFlag) != 0) {
+            expectedUserFlags |= intEnumUserFlag;
+        }
     }
-    userInfo->flags = *userFlags;
+    if (intUserFlags != expectedUserFlags) {
+        return Error() << "Invalid user flags: " << intUserFlags << ", must be '|' of UserFlags";
+    }
+    // intUserFlags is actually not a valid UserFlags enum, instead, it is a 'bit or' of possible
+    // multiple UserFlags. However, because the HAL interface was defined incorrectly, we have to
+    // cast it to UserFlags here, which is defined behavior because the underlying type for
+    // UserFlags is int32_t and our intUserFlags is within the range of int32_t.
+    userInfo->flags = static_cast<UserFlags>(intUserFlags);
     return {};
 }
 
diff --git a/automotive/vehicle/2.0/utils/tests/UserHalHelper_test.cpp b/automotive/vehicle/2.0/utils/tests/UserHalHelper_test.cpp
index 7da87a2..0562a54 100644
--- a/automotive/vehicle/2.0/utils/tests/UserHalHelper_test.cpp
+++ b/automotive/vehicle/2.0/utils/tests/UserHalHelper_test.cpp
@@ -54,6 +54,10 @@
 constexpr int32_t GUEST_USER = static_cast<int32_t>(UserFlags::GUEST);
 constexpr int32_t NONE_USER = static_cast<int32_t>(UserFlags::NONE);
 constexpr int32_t SYSTEM_USER = static_cast<int32_t>(UserFlags::SYSTEM);
+constexpr int32_t ADMIN_USER = static_cast<int32_t>(UserFlags::ADMIN);
+constexpr int32_t SYSTEM_ADMIN_USER = static_cast<int32_t>(UserFlags::SYSTEM | UserFlags::ADMIN);
+// 0x1111 is not a valid UserFlags combination.
+constexpr int32_t INVALID_USER_FLAG = 0x1111;
 
 constexpr int32_t USER_ID_ASSOC_KEY_FOB =
         static_cast<int32_t>(UserIdentificationAssociationType::KEY_FOB);
@@ -72,7 +76,7 @@
 
 }  // namespace
 
-TEST(UserHalHelperTest, TestToInitialUserInfoRequest) {
+TEST(UserHalHelperTest, TestToInitialUserInfoRequestSystemUser) {
     VehiclePropValue propValue{
             .prop = INITIAL_USER_INFO,
             .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, SYSTEM_USER,
@@ -92,6 +96,58 @@
     EXPECT_THAT(actual.value(), Eq(expected));
 }
 
+TEST(UserHalHelperTest, TestToInitialUserInfoRequestAdminUser) {
+    VehiclePropValue propValue{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, ADMIN_USER, 10,
+                                      NONE_USER}},
+    };
+    InitialUserInfoRequest expected{
+            .requestId = 23,
+            .requestType = InitialUserInfoRequestType::FIRST_BOOT_AFTER_OTA,
+            .usersInfo = {{10, UserFlags::NONE}, 2, {{0, UserFlags::ADMIN}, {10, UserFlags::NONE}}},
+    };
+
+    auto actual = toInitialUserInfoRequest(propValue);
+
+    ASSERT_TRUE(actual.ok()) << actual.error().message();
+    EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestToInitialUserInfoRequestUserFlagsBitCombination) {
+    // SYSTEM_ADMIN_USER is two UserFlags combined and is itself not a defined UserFlags enum.
+    VehiclePropValue propValue{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0,
+                                      SYSTEM_ADMIN_USER, 10, NONE_USER}},
+    };
+    InitialUserInfoRequest expected{
+            .requestId = 23,
+            .requestType = InitialUserInfoRequestType::FIRST_BOOT_AFTER_OTA,
+            .usersInfo = {{10, UserFlags::NONE},
+                          2,
+                          {{0, static_cast<UserFlags>(SYSTEM_ADMIN_USER)}, {10, UserFlags::NONE}}},
+    };
+
+    auto actual = toInitialUserInfoRequest(propValue);
+
+    ASSERT_TRUE(actual.ok()) << actual.error().message();
+    EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestToInitialUserInfoRequestUserInvalidUserFlag) {
+    // 0x1111 is not a valid UserFlags flag combination.
+    VehiclePropValue propValue{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0,
+                                      INVALID_USER_FLAG, 10, NONE_USER}},
+    };
+
+    auto actual = toInitialUserInfoRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on invalid user flags";
+}
+
 TEST(UserHalHelperTest, TestFailsToInitialUserInfoRequestWithMismatchingPropType) {
     VehiclePropValue propValue{
             .prop = INT32_MAX,
diff --git a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.xml b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.xml
index 09463c9..ea7adc9 100644
--- a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.xml
+++ b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.xml
@@ -22,8 +22,11 @@
     <target_preparer class="com.android.tradefed.targetprep.StopServicesSetup">
     </target_preparer>
 
-    <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
-        <option name="bluetooth" value="off" />
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="settings put global ble_scan_always_enabled 0" />
+        <option name="run-command" value="su u$(am get-current-user)_system svc bluetooth disable" />
+        <option name="teardown-command" value="su u$(am get-current-user)_system svc bluetooth enable" />
+        <option name="teardown-command" value="settings put global ble_scan_always_enabled 1" />
     </target_preparer>
 
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
diff --git a/broadcastradio/2.0/default/Android.bp b/broadcastradio/2.0/default/Android.bp
index 870c944..38eeb15 100644
--- a/broadcastradio/2.0/default/Android.bp
+++ b/broadcastradio/2.0/default/Android.bp
@@ -25,6 +25,9 @@
 
 cc_binary {
     name: "android.hardware.broadcastradio@2.0-service",
+    vintf_fragments: [
+        "android.hardware.broadcastradio@2.0-service.xml",
+    ],
     init_rc: ["android.hardware.broadcastradio@2.0-service.rc"],
     vendor: true,
     relative_install_path: "hw",
@@ -41,7 +44,7 @@
         "TunerSession.cpp",
         "VirtualProgram.cpp",
         "VirtualRadio.cpp",
-        "service.cpp"
+        "service.cpp",
     ],
     static_libs: [
         "android.hardware.broadcastradio@common-utils-2x-lib",
diff --git a/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.xml b/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.xml
new file mode 100644
index 0000000..97f2e4d
--- /dev/null
+++ b/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.xml
@@ -0,0 +1,12 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.broadcastradio</name>
+        <transport>hwbinder</transport>
+        <version>2.0</version>
+        <interface>
+            <name>IBroadcastRadio</name>
+            <instance>amfm</instance>
+            <instance>dab</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/camera/metadata/3.7/types.hal b/camera/metadata/3.7/types.hal
new file mode 100644
index 0000000..a09bdf9
--- /dev/null
+++ b/camera/metadata/3.7/types.hal
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+/*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+
+package android.hardware.camera.metadata@3.7;
+
+import android.hardware.camera.metadata@3.2;
+import android.hardware.camera.metadata@3.3;
+import android.hardware.camera.metadata@3.4;
+import android.hardware.camera.metadata@3.5;
+import android.hardware.camera.metadata@3.6;
+
+// No new metadata sections added in this revision
+
+/**
+ * Main enumeration for defining camera metadata tags added in this revision
+ *
+ * <p>Partial documentation is included for each tag; for complete documentation, reference
+ * '/system/media/camera/docs/docs.html' in the corresponding Android source tree.</p>
+ */
+enum CameraMetadataTag : @3.6::CameraMetadataTag {
+    /** android.info.deviceStateOrientations [static, int64[], ndk_public]
+     */
+    ANDROID_INFO_DEVICE_STATE_ORIENTATIONS = android.hardware.camera.metadata@3.4::CameraMetadataTag:ANDROID_INFO_END_3_4,
+
+    ANDROID_INFO_END_3_7,
+
+};
+
+/*
+ * Enumeration definitions for the various entries that need them
+ */
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 7727547..052103d 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -882,6 +882,7 @@
             camera_metadata* oldSessionParams, camera_metadata* newSessionParams);
 
     void verifyRequestTemplate(const camera_metadata_t* metadata, RequestTemplate requestTemplate);
+    static void overrideRotateAndCrop(::android::hardware::hidl_vec<uint8_t> *settings /*in/out*/);
 
     static bool isDepthOnly(const camera_metadata_t* staticMeta);
 
@@ -935,7 +936,9 @@
             camera_metadata_ro_entry* streamConfigs,
             camera_metadata_ro_entry* maxResolutionStreamConfigs,
             const camera_metadata_t* staticMetadata);
-    static bool isColorCamera(const camera_metadata_t *metadata);
+    void getPrivacyTestPatternModes(
+            const camera_metadata_t* staticMetadata,
+            std::unordered_set<int32_t>* privacyTestPatternModes/*out*/);
 
     static V3_2::DataspaceFlags getDataspace(PixelFormat format);
 
@@ -4660,6 +4663,7 @@
                                                            settings = req;
                                                        });
         ASSERT_TRUE(ret.isOk());
+        overrideRotateAndCrop(&settings);
 
         hidl_handle buffer_handle;
         StreamBuffer outputBuffer;
@@ -4836,6 +4840,7 @@
         settings.setToExternal(
                 reinterpret_cast<uint8_t *> (const_cast<camera_metadata_t *> (settingsBuffer)),
                 get_camera_metadata_size(settingsBuffer));
+        overrideRotateAndCrop(&settings);
 
         free_camera_metadata(staticMeta);
         ret = session->close();
@@ -4913,6 +4918,7 @@
                 reinterpret_cast<uint8_t *> (const_cast<camera_metadata_t *> (
                         filteredSettingsBuffer)),
                 get_camera_metadata_size(filteredSettingsBuffer));
+        overrideRotateAndCrop(&camSettings[0].settings);
         camSettings[0].fmqSettingsSize = 0;
         camSettings[0].physicalCameraId = physicalDeviceId;
 
@@ -5070,6 +5076,7 @@
         settings.setToExternal(
                 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(settingsBuffer)),
                 get_camera_metadata_size(settingsBuffer));
+        overrideRotateAndCrop(&settings);
 
         free_camera_metadata(staticMeta);
         ret = session->close();
@@ -5305,6 +5312,7 @@
             camera_metadata_t *metaBuffer = requestMeta.release();
             requestSettings[i].setToExternal(reinterpret_cast<uint8_t *> (metaBuffer),
                     get_camera_metadata_size(metaBuffer), true);
+            overrideRotateAndCrop(&requestSettings[i]);
 
             requests[i] = {frameNumber + i, 0 /* fmqSettingsSize */, requestSettings[i],
                 emptyInputBuffer, {outputBuffers[i]}};
@@ -5531,6 +5539,7 @@
             camera_metadata_t *metaBuffer = requestMeta.release();
             requestSettings[i].setToExternal(reinterpret_cast<uint8_t *> (metaBuffer),
                     get_camera_metadata_size(metaBuffer), true);
+            overrideRotateAndCrop(&requestSettings[i]);
 
             requests[i] = {frameNumber + i, 0 /* fmqSettingsSize */, requestSettings[i],
                 emptyInputBuffer, {outputBuffers[i]}};
@@ -5671,6 +5680,7 @@
                                                            settings = req;
                                                        });
         ASSERT_TRUE(ret.isOk());
+        overrideRotateAndCrop(&settings);
 
         ::android::hardware::hidl_vec<StreamBuffer> emptyOutputBuffers;
         StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr,
@@ -5755,6 +5765,7 @@
                                                            settings = req;
                                                        });
         ASSERT_TRUE(ret.isOk());
+        overrideRotateAndCrop(&settings);
 
         hidl_handle buffer_handle;
         if (useHalBufManager) {
@@ -6187,167 +6198,6 @@
     }
 }
 
-// Test the multi-camera API requirement for Google Requirement Freeze S
-// Note that this requirement can only be partially tested. If a vendor
-// device doesn't expose a physical camera in any shape or form, there is no way
-// the test can catch it.
-TEST_P(CameraHidlTest, grfSMultiCameraTest) {
-    const int socGrfApi = property_get_int32("ro.board.first_api_level", /*default*/ -1);
-    if (socGrfApi < 31 /*S*/) {
-        // Non-GRF devices, or version < 31 Skip
-        ALOGI("%s: socGrfApi level is %d. Skipping", __FUNCTION__, socGrfApi);
-        return;
-    }
-
-    // Test that if more than one color cameras facing the same direction are
-    // supported, there must be at least one logical camera facing that
-    // direction.
-    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
-    // Front and back facing non-logical color cameras
-    std::set<std::string> frontColorCameras, rearColorCameras;
-    // Front and back facing logical cameras' physical camera Id sets
-    std::set<std::set<std::string>> frontPhysicalIds, rearPhysicalIds;
-    for (const auto& name : cameraDeviceNames) {
-        std::string cameraId;
-        int deviceVersion = getCameraDeviceVersionAndId(name, mProviderType, &cameraId);
-        switch (deviceVersion) {
-            case CAMERA_DEVICE_API_VERSION_3_7:
-            case CAMERA_DEVICE_API_VERSION_3_6:
-            case CAMERA_DEVICE_API_VERSION_3_5:
-            case CAMERA_DEVICE_API_VERSION_3_4:
-            case CAMERA_DEVICE_API_VERSION_3_3:
-            case CAMERA_DEVICE_API_VERSION_3_2: {
-                ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_x;
-                ALOGI("getCameraCharacteristics: Testing camera device %s", name.c_str());
-                Return<void> ret;
-                ret = mProvider->getCameraDeviceInterface_V3_x(
-                        name, [&](auto status, const auto& device) {
-                            ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
-                            ASSERT_EQ(Status::OK, status);
-                            ASSERT_NE(device, nullptr);
-                            device3_x = device;
-                        });
-                ASSERT_TRUE(ret.isOk());
-
-                ret = device3_x->getCameraCharacteristics([&](auto status, const auto& chars) {
-                    ASSERT_EQ(Status::OK, status);
-                    const camera_metadata_t* metadata = (camera_metadata_t*)chars.data();
-
-                    // Skip if this is not a color camera.
-                    if (!CameraHidlTest::isColorCamera(metadata)) {
-                        return;
-                    }
-
-                    // Check camera facing. Skip if facing is neither FRONT
-                    // nor BACK. If this is not a logical camera, only note down
-                    // the camera ID, and skip.
-                    camera_metadata_ro_entry entry;
-                    int retcode = find_camera_metadata_ro_entry(
-                            metadata, ANDROID_LENS_FACING, &entry);
-                    ASSERT_EQ(retcode, 0);
-                    ASSERT_GT(entry.count, 0);
-                    uint8_t facing = entry.data.u8[0];
-                    bool isLogicalCamera = (isLogicalMultiCamera(metadata) == Status::OK);
-                    if (facing == ANDROID_LENS_FACING_FRONT) {
-                        if (!isLogicalCamera) {
-                            frontColorCameras.insert(cameraId);
-                            return;
-                        }
-                    } else if (facing == ANDROID_LENS_FACING_BACK) {
-                        if (!isLogicalCamera) {
-                            rearColorCameras.insert(cameraId);
-                            return;
-                        }
-                    } else {
-                        // Not FRONT or BACK facing. Skip.
-                        return;
-                    }
-
-                    // Check logical camera's physical camera IDs for color
-                    // cameras.
-                    std::unordered_set<std::string> physicalCameraIds;
-                    Status s = getPhysicalCameraIds(metadata, &physicalCameraIds);
-                    ASSERT_EQ(Status::OK, s);
-                    if (facing == ANDROID_LENS_FACING_FRONT) {
-                        frontPhysicalIds.emplace(physicalCameraIds.begin(), physicalCameraIds.end());
-                    } else {
-                        rearPhysicalIds.emplace(physicalCameraIds.begin(), physicalCameraIds.end());
-                    }
-                    for (const auto& physicalId : physicalCameraIds) {
-                        // Skip if the physicalId is publicly available
-                        for (auto& deviceName : cameraDeviceNames) {
-                            std::string publicVersion, publicId;
-                            ASSERT_TRUE(::matchDeviceName(deviceName, mProviderType,
-                                                          &publicVersion, &publicId));
-                            if (physicalId == publicId) {
-                                // Skip because public Ids will be iterated in outer loop.
-                                return;
-                            }
-                        }
-
-                        auto castResult = device::V3_5::ICameraDevice::castFrom(device3_x);
-                        ASSERT_TRUE(castResult.isOk());
-                        ::android::sp<::android::hardware::camera::device::V3_5::ICameraDevice>
-                                device3_5 = castResult;
-                        ASSERT_NE(device3_5, nullptr);
-
-                        // Check camera characteristics for hidden camera id
-                        Return<void> ret = device3_5->getPhysicalCameraCharacteristics(
-                                physicalId, [&](auto status, const auto& chars) {
-                            ASSERT_EQ(Status::OK, status);
-                            const camera_metadata_t* physicalMetadata =
-                                    (camera_metadata_t*)chars.data();
-
-                            if (CameraHidlTest::isColorCamera(physicalMetadata)) {
-                                if (facing == ANDROID_LENS_FACING_FRONT) {
-                                    frontColorCameras.insert(physicalId);
-                                } else if (facing == ANDROID_LENS_FACING_BACK) {
-                                    rearColorCameras.insert(physicalId);
-                                }
-                            }
-                        });
-                        ASSERT_TRUE(ret.isOk());
-                    }
-                });
-                ASSERT_TRUE(ret.isOk());
-            } break;
-            case CAMERA_DEVICE_API_VERSION_1_0: {
-                // Not applicable
-            } break;
-            default: {
-                ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
-                ADD_FAILURE();
-            } break;
-        }
-    }
-
-    // If there are more than one color cameras facing one direction, a logical
-    // multi-camera must be defined consisting of all color cameras facing that
-    // direction.
-    if (frontColorCameras.size() > 1) {
-        bool hasFrontLogical = false;
-        for (const auto& physicalIds : frontPhysicalIds) {
-            if (std::includes(physicalIds.begin(), physicalIds.end(),
-                    frontColorCameras.begin(), frontColorCameras.end())) {
-                hasFrontLogical = true;
-                break;
-            }
-        }
-        ASSERT_TRUE(hasFrontLogical);
-    }
-    if (rearColorCameras.size() > 1) {
-        bool hasRearLogical = false;
-        for (const auto& physicalIds : rearPhysicalIds) {
-            if (std::includes(physicalIds.begin(), physicalIds.end(),
-                    rearColorCameras.begin(), rearColorCameras.end())) {
-                hasRearLogical = true;
-                break;
-            }
-        }
-        ASSERT_TRUE(hasRearLogical);
-    }
-}
-
 // Retrieve all valid output stream resolutions from the camera
 // static characteristics.
 Status CameraHidlTest::getAvailableOutputStreams(const camera_metadata_t* staticMeta,
@@ -6779,6 +6629,25 @@
     ASSERT_TRUE(-ENOENT == retcode || 0 == retcode);
 }
 
+void CameraHidlTest::getPrivacyTestPatternModes(
+        const camera_metadata_t* staticMetadata,
+        std::unordered_set<int32_t>* privacyTestPatternModes/*out*/) {
+    ASSERT_NE(staticMetadata, nullptr);
+    ASSERT_NE(privacyTestPatternModes, nullptr);
+
+    camera_metadata_ro_entry entry;
+    int retcode = find_camera_metadata_ro_entry(
+            staticMetadata, ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES, &entry);
+    ASSERT_TRUE(0 == retcode);
+
+    for (auto i = 0; i < entry.count; i++) {
+        if (entry.data.i32[i] == ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR ||
+                entry.data.i32[i] == ANDROID_SENSOR_TEST_PATTERN_MODE_BLACK) {
+            privacyTestPatternModes->insert(entry.data.i32[i]);
+        }
+    }
+}
+
 // Select an appropriate dataspace given a specific pixel format.
 V3_2::DataspaceFlags CameraHidlTest::getDataspace(PixelFormat format) {
     switch (format) {
@@ -6820,23 +6689,6 @@
     return ret;
 }
 
-bool CameraHidlTest::isColorCamera(const camera_metadata_t *metadata) {
-    camera_metadata_ro_entry entry;
-    int retcode = find_camera_metadata_ro_entry(
-            metadata, ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &entry);
-    if ((0 == retcode) && (entry.count > 0)) {
-        bool isBackwardCompatible = (std::find(entry.data.u8, entry.data.u8 + entry.count,
-                ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) !=
-                entry.data.u8 + entry.count);
-        bool isMonochrome = (std::find(entry.data.u8, entry.data.u8 + entry.count,
-                ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) !=
-                entry.data.u8 + entry.count);
-        bool isColor = isBackwardCompatible && !isMonochrome;
-        return isColor;
-    }
-    return false;
-}
-
 // Retrieve the reprocess input-output format map from the static
 // camera characteristics.
 Status CameraHidlTest::getZSLInputOutputMap(camera_metadata_t *staticMeta,
@@ -7833,6 +7685,16 @@
         ASSERT_TRUE(isUltraHighResCamera && !isMultiCamera);
         physicalIds.insert(cameraId);
     }
+
+    std::unordered_set<int32_t> physicalRequestKeyIDs;
+    rc = getSupportedKeys(const_cast<camera_metadata_t *>(metadata),
+            ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS, &physicalRequestKeyIDs);
+    ASSERT_TRUE(Status::OK == rc);
+    bool hasTestPatternPhysicalRequestKey = physicalRequestKeyIDs.find(
+            ANDROID_SENSOR_TEST_PATTERN_MODE) != physicalRequestKeyIDs.end();
+    std::unordered_set<int32_t> privacyTestPatternModes;
+    getPrivacyTestPatternModes(metadata, &privacyTestPatternModes);
+
     // Map from image format to number of multi-resolution sizes for that format
     std::unordered_map<int32_t, size_t> multiResOutputFormatCounterMap;
     std::unordered_map<int32_t, size_t> multiResInputFormatCounterMap;
@@ -7854,6 +7716,7 @@
         camera_metadata_ro_entry physicalStreamConfigs;
         camera_metadata_ro_entry physicalMaxResolutionStreamConfigs;
         bool isUltraHighRes = false;
+        std::unordered_set<int32_t> subCameraPrivacyTestPatterns;
         if (isPublicId) {
             ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> subDevice;
             Return<void> ret;
@@ -7884,6 +7747,8 @@
                         &physicalMultiResStreamConfigs, &physicalStreamConfigs,
                         &physicalMaxResolutionStreamConfigs, staticMetadata);
                 isUltraHighRes = isUltraHighResolution(staticMetadata);
+
+                getPrivacyTestPatternModes(staticMetadata, &subCameraPrivacyTestPatterns);
             });
             ASSERT_TRUE(ret.isOk());
         } else {
@@ -7910,6 +7775,7 @@
                                 &physicalMultiResStreamConfigs, &physicalStreamConfigs,
                                 &physicalMaxResolutionStreamConfigs, staticMetadata);
                         isUltraHighRes = isUltraHighResolution(staticMetadata);
+                        getPrivacyTestPatternModes(staticMetadata, &subCameraPrivacyTestPatterns);
                     });
             ASSERT_TRUE(ret.isOk());
 
@@ -7926,6 +7792,10 @@
             ASSERT_TRUE(ret.isOk());
         }
 
+        if (hasTestPatternPhysicalRequestKey) {
+            ASSERT_TRUE(privacyTestPatternModes == subCameraPrivacyTestPatterns);
+        }
+
         if (physicalMultiResStreamConfigs.count > 0) {
             ASSERT_GE(deviceVersion, CAMERA_DEVICE_API_VERSION_3_7);
             ASSERT_EQ(physicalMultiResStreamConfigs.count % 4, 0);
@@ -8161,6 +8031,20 @@
                 poseReference >= ANDROID_LENS_POSE_REFERENCE_PRIMARY_CAMERA);
     }
 
+    retcode = find_camera_metadata_ro_entry(metadata,
+            ANDROID_INFO_DEVICE_STATE_ORIENTATIONS, &entry);
+    if (0 == retcode && entry.count > 0) {
+        ASSERT_TRUE((entry.count % 2) == 0);
+        uint64_t maxPublicState = ((uint64_t) provider::V2_5::DeviceState::FOLDED) << 1;
+        uint64_t vendorStateStart = 1UL << 31; // Reserved for vendor specific states
+        uint64_t stateMask = (1 << vendorStateStart) - 1;
+        stateMask &= ~((1 << maxPublicState) - 1);
+        for (int i = 0; i < entry.count; i += 2){
+            ASSERT_TRUE((entry.data.i64[i] & stateMask) == 0);
+            ASSERT_TRUE((entry.data.i64[i+1] % 90) == 0);
+        }
+    }
+
     verifyExtendedSceneModeCharacteristics(metadata);
     verifyZoomCharacteristics(metadata);
 }
@@ -8921,6 +8805,25 @@
     }
 }
 
+void CameraHidlTest::overrideRotateAndCrop(
+        ::android::hardware::hidl_vec<uint8_t> *settings /*in/out*/) {
+    if (settings == nullptr) {
+        return;
+    }
+
+    ::android::hardware::camera::common::V1_0::helper::CameraMetadata requestMeta;
+    requestMeta.append(reinterpret_cast<camera_metadata_t *> (settings->data()));
+    auto entry = requestMeta.find(ANDROID_SCALER_ROTATE_AND_CROP);
+    if ((entry.count > 0) && (entry.data.u8[0] == ANDROID_SCALER_ROTATE_AND_CROP_AUTO)) {
+        uint8_t disableRotateAndCrop = ANDROID_SCALER_ROTATE_AND_CROP_NONE;
+        requestMeta.update(ANDROID_SCALER_ROTATE_AND_CROP, &disableRotateAndCrop, 1);
+        settings->releaseData();
+        camera_metadata_t *metaBuffer = requestMeta.release();
+        settings->setToExternal(reinterpret_cast<uint8_t *> (metaBuffer),
+                get_camera_metadata_size(metaBuffer), true);
+    }
+}
+
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CameraHidlTest);
 INSTANTIATE_TEST_SUITE_P(
         PerInstance, CameraHidlTest,
diff --git a/current.txt b/current.txt
index 3893d07..2373c39 100644
--- a/current.txt
+++ b/current.txt
@@ -901,4 +901,7 @@
 4a087a308608d146b022ebc15633de989f5f4dfe1491a83fa41763290a82e40d android.hardware.automotive.vehicle@2.0::types
 70eb14415391f835fb218b43a1e25f5d6495f098f96fa2acaea70985e98e1ce8 android.hardware.automotive.vehicle@2.0::types
 
+# HALs released in Android SCv2
+77f6fcf3fd0dd3e424d8a0292094ebd17e4c35454bb9abbd3a6cbed1aba70765 android.hardware.camera.metadata@3.7::types
+
 # There should be no more HIDL HALs - please use AIDL instead.
diff --git a/gnss/aidl/default/GnssMeasurementInterface.cpp b/gnss/aidl/default/GnssMeasurementInterface.cpp
index fcc1f98..9e4f7c7 100644
--- a/gnss/aidl/default/GnssMeasurementInterface.cpp
+++ b/gnss/aidl/default/GnssMeasurementInterface.cpp
@@ -19,11 +19,17 @@
 #include "GnssMeasurementInterface.h"
 #include <aidl/android/hardware/gnss/BnGnss.h>
 #include <log/log.h>
+#include "DeviceFileReader.h"
+#include "GnssRawMeasurementParser.h"
+#include "GnssReplayUtils.h"
 #include "Utils.h"
 
 namespace aidl::android::hardware::gnss {
 
 using Utils = ::android::hardware::gnss::common::Utils;
+using ReplayUtils = ::android::hardware::gnss::common::ReplayUtils;
+using GnssRawMeasurementParser = ::android::hardware::gnss::common::GnssRawMeasurementParser;
+using DeviceFileReader = ::android::hardware::gnss::common::DeviceFileReader;
 
 std::shared_ptr<IGnssMeasurementCallback> GnssMeasurementInterface::sCallback = nullptr;
 
@@ -63,9 +69,22 @@
     mIsActive = true;
     mThread = std::thread([this, enableCorrVecOutputs]() {
         while (mIsActive == true) {
-            auto measurement = Utils::getMockMeasurement(enableCorrVecOutputs);
-            this->reportMeasurement(measurement);
-
+            std::string rawMeasurementStr = "";
+            if (ReplayUtils::hasGnssDeviceFile() &&
+                ReplayUtils::isGnssRawMeasurement(
+                        rawMeasurementStr =
+                                DeviceFileReader::Instance().getGnssRawMeasurementData())) {
+                ALOGD("rawMeasurementStr(size: %zu) from device file: %s", rawMeasurementStr.size(),
+                      rawMeasurementStr.c_str());
+                auto measurement =
+                        GnssRawMeasurementParser::getMeasurementFromStrs(rawMeasurementStr);
+                if (measurement != nullptr) {
+                    this->reportMeasurement(*measurement);
+                }
+            } else {
+                auto measurement = Utils::getMockMeasurement(enableCorrVecOutputs);
+                this->reportMeasurement(measurement);
+            }
             std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMillis));
         }
     });
diff --git a/gnss/common/utils/default/Android.bp b/gnss/common/utils/default/Android.bp
index 43db873..bdb1569 100644
--- a/gnss/common/utils/default/Android.bp
+++ b/gnss/common/utils/default/Android.bp
@@ -38,9 +38,14 @@
         "v2_1/GnssDebug.cpp",
         "v2_1/GnssMeasurement.cpp",
         "v2_1/GnssMeasurementCorrections.cpp",
+        "DeviceFileReader.cpp",
+        "FixLocationParser.cpp",
+        "GnssRawMeasurementParser.cpp",
+        "GnssReplayUtils.cpp",
         "MockLocation.cpp",
-        "Utils.cpp",
         "NmeaFixInfo.cpp",
+        "ParseUtils.cpp",
+        "Utils.cpp",
     ],
     export_include_dirs: ["include"],
     shared_libs: [
diff --git a/gnss/common/utils/default/DeviceFileReader.cpp b/gnss/common/utils/default/DeviceFileReader.cpp
new file mode 100644
index 0000000..dfc086a
--- /dev/null
+++ b/gnss/common/utils/default/DeviceFileReader.cpp
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+#include "DeviceFileReader.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+void DeviceFileReader::getDataFromDeviceFile(const std::string& command, int mMinIntervalMs) {
+    char inputBuffer[INPUT_BUFFER_SIZE];
+    std::string deviceFilePath = "";
+    if (command == CMD_GET_LOCATION) {
+        deviceFilePath = ReplayUtils::getFixedLocationPath();
+    } else if (command == CMD_GET_RAWMEASUREMENT) {
+        deviceFilePath = ReplayUtils::getGnssPath();
+    } else {
+        // Invalid command
+        return;
+    }
+
+    int mGnssFd = open(deviceFilePath.c_str(), O_RDWR | O_NONBLOCK);
+
+    if (mGnssFd == -1) {
+        return;
+    }
+
+    int bytes_write = write(mGnssFd, command.c_str(), command.size());
+    if (bytes_write <= 0) {
+        close(mGnssFd);
+        return;
+    }
+
+    struct epoll_event ev, events[1];
+    ev.data.fd = mGnssFd;
+    ev.events = EPOLLIN;
+    int epoll_fd = epoll_create1(0);
+    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, mGnssFd, &ev);
+    int bytes_read = -1;
+    std::string inputStr = "";
+    int epoll_ret = epoll_wait(epoll_fd, events, 1, mMinIntervalMs);
+
+    if (epoll_ret == -1) {
+        close(mGnssFd);
+        return;
+    }
+    while (true) {
+        memset(inputBuffer, 0, INPUT_BUFFER_SIZE);
+        bytes_read = read(mGnssFd, &inputBuffer, INPUT_BUFFER_SIZE);
+        if (bytes_read <= 0) {
+            break;
+        }
+        s_buffer_ += std::string(inputBuffer, bytes_read);
+    }
+    close(mGnssFd);
+
+    // Trim end of file mark(\n\n\n\n).
+    auto pos = s_buffer_.find("\n\n\n\n");
+    if (pos != std::string::npos) {
+        inputStr = s_buffer_.substr(0, pos);
+        s_buffer_ = s_buffer_.substr(pos + 4);
+    } else {
+        return;
+    }
+
+    // Cache the injected data.
+    if (command == CMD_GET_LOCATION) {
+        // TODO validate data
+        data_[CMD_GET_LOCATION] = inputStr;
+    } else if (command == CMD_GET_RAWMEASUREMENT) {
+        if (ReplayUtils::isGnssRawMeasurement(inputStr)) {
+            data_[CMD_GET_RAWMEASUREMENT] = inputStr;
+        }
+    }
+}
+
+std::string DeviceFileReader::getLocationData() {
+    std::unique_lock<std::mutex> lock(mMutex);
+    getDataFromDeviceFile(CMD_GET_LOCATION, 20);
+    return data_[CMD_GET_LOCATION];
+}
+
+std::string DeviceFileReader::getGnssRawMeasurementData() {
+    std::unique_lock<std::mutex> lock(mMutex);
+    getDataFromDeviceFile(CMD_GET_RAWMEASUREMENT, 20);
+    return data_[CMD_GET_RAWMEASUREMENT];
+}
+
+DeviceFileReader::DeviceFileReader() {}
+
+DeviceFileReader::~DeviceFileReader() {}
+
+}  // namespace common
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/common/utils/default/FixLocationParser.cpp b/gnss/common/utils/default/FixLocationParser.cpp
new file mode 100644
index 0000000..f0177b4
--- /dev/null
+++ b/gnss/common/utils/default/FixLocationParser.cpp
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+#include "FixLocationParser.h"
+
+#include <android/hardware/gnss/1.0/IGnss.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+std::unique_ptr<V2_0::GnssLocation> FixLocationParser::getLocationFromInputStr(
+        const std::string& locationStr) {
+    /*
+     * Fix,Provider,LatitudeDegrees,LongitudeDegrees,AltitudeMeters,SpeedMps,
+     * AccuracyMeters,BearingDegrees,UnixTimeMillis,SpeedAccuracyMps,BearingAccuracyDegrees,
+     * elapsedRealtimeNanos
+     */
+    if (locationStr.empty()) {
+        return nullptr;
+    }
+    std::vector<std::string> locationStrRecords;
+    ParseUtils::splitStr(locationStr, LINE_SEPARATOR, locationStrRecords);
+    if (locationStrRecords.empty()) {
+        return nullptr;
+    }
+
+    std::vector<std::string> locationValues;
+    ParseUtils::splitStr(locationStrRecords[0], COMMA_SEPARATOR, locationValues);
+    if (locationValues.size() < 12) {
+        return nullptr;
+    }
+    V2_0::ElapsedRealtime elapsedRealtime = {
+            .flags = V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS |
+                     V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS,
+            .timestampNs = static_cast<uint64_t>(::android::elapsedRealtimeNano()),
+            // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks.
+            // In an actual implementation provide an estimate of the synchronization uncertainty
+            // or don't set the field.
+            .timeUncertaintyNs = 1020400};
+
+    V1_0::GnssLocation locationV1 = {
+            .gnssLocationFlags = 0xFF,
+            .latitudeDegrees = ParseUtils::tryParseDouble(locationValues[2], 0),
+            .longitudeDegrees = ParseUtils::tryParseDouble(locationValues[3], 0),
+            .altitudeMeters = ParseUtils::tryParseDouble(locationValues[4], 0),
+            .speedMetersPerSec = ParseUtils::tryParsefloat(locationValues[5], 0),
+            .bearingDegrees = ParseUtils::tryParsefloat(locationValues[7], 0),
+            .horizontalAccuracyMeters = ParseUtils::tryParsefloat(locationValues[6], 0),
+            .verticalAccuracyMeters = ParseUtils::tryParsefloat(locationValues[6], 0),
+            .speedAccuracyMetersPerSecond = ParseUtils::tryParsefloat(locationValues[9], 0),
+            .bearingAccuracyDegrees = ParseUtils::tryParsefloat(locationValues[10], 0),
+            .timestamp = ParseUtils::tryParseLongLong(locationValues[8], 0)};
+
+    V2_0::GnssLocation locationV2 = {.v1_0 = locationV1, .elapsedRealtime = elapsedRealtime};
+    return std::make_unique<V2_0::GnssLocation>(locationV2);
+}
+
+}  // namespace common
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/common/utils/default/GnssRawMeasurementParser.cpp b/gnss/common/utils/default/GnssRawMeasurementParser.cpp
new file mode 100644
index 0000000..c066229
--- /dev/null
+++ b/gnss/common/utils/default/GnssRawMeasurementParser.cpp
@@ -0,0 +1,305 @@
+/*
+ * 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.
+ */
+
+#include "GnssRawMeasurementParser.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+using aidl::android::hardware::gnss::ElapsedRealtime;
+using aidl::android::hardware::gnss::GnssClock;
+using aidl::android::hardware::gnss::GnssConstellationType;
+using aidl::android::hardware::gnss::GnssData;
+using aidl::android::hardware::gnss::GnssMeasurement;
+using aidl::android::hardware::gnss::GnssMultipathIndicator;
+using aidl::android::hardware::gnss::GnssSignalType;
+
+using ParseUtils = ::android::hardware::gnss::common::ParseUtils;
+
+std::unordered_map<std::string, int> GnssRawMeasurementParser::getColumnIdNameMappingFromHeader(
+        const std::string& header) {
+    std::vector<std::string> columnNames;
+    std::unordered_map<std::string, int> columnNameIdMapping;
+    std::string s = header;
+    // Trim left spaces
+    s.erase(s.begin(),
+            std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); }));
+    // Trim right spaces
+    s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); })
+                    .base(),
+            s.end());
+    // Remove comment symbol, start from `Raw`.
+    s = s.substr(s.find("Raw"));
+
+    ParseUtils::splitStr(s, COMMA_SEPARATOR, columnNames);
+    int columnId = 0;
+    for (auto& name : columnNames) {
+        columnNameIdMapping[name] = columnId++;
+    }
+
+    return columnNameIdMapping;
+}
+
+int GnssRawMeasurementParser::getClockFlags(
+        const std::vector<std::string>& rawMeasurementRecordValues,
+        const std::unordered_map<std::string, int>& columnNameIdMapping) {
+    int clockFlags = 0;
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("LeapSecond")].empty()) {
+        clockFlags |= GnssClock::HAS_LEAP_SECOND;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("FullBiasNanos")].empty()) {
+        clockFlags |= GnssClock::HAS_FULL_BIAS;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("BiasNanos")].empty()) {
+        clockFlags |= GnssClock::HAS_BIAS;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("BiasUncertaintyNanos")].empty()) {
+        clockFlags |= GnssClock::HAS_BIAS_UNCERTAINTY;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("DriftNanosPerSecond")].empty()) {
+        clockFlags |= GnssClock::HAS_DRIFT;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("DriftUncertaintyNanosPerSecond")]
+                 .empty()) {
+        clockFlags |= GnssClock::HAS_DRIFT_UNCERTAINTY;
+    }
+    return clockFlags;
+}
+
+int GnssRawMeasurementParser::getElapsedRealtimeFlags(
+        const std::vector<std::string>& rawMeasurementRecordValues,
+        const std::unordered_map<std::string, int>& columnNameIdMapping) {
+    int elapsedRealtimeFlags = ElapsedRealtime::HAS_TIMESTAMP_NS;
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("TimeUncertaintyNanos")].empty()) {
+        elapsedRealtimeFlags |= ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS;
+    }
+    return elapsedRealtimeFlags;
+}
+
+int GnssRawMeasurementParser::getRawMeasurementFlags(
+        const std::vector<std::string>& rawMeasurementRecordValues,
+        const std::unordered_map<std::string, int>& columnNameIdMapping) {
+    int rawMeasurementFlags = 0;
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("SnrInDb")].empty()) {
+        rawMeasurementFlags |= GnssMeasurement::HAS_SNR;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierFrequencyHz")].empty()) {
+        rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_FREQUENCY;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierCycles")].empty()) {
+        rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_CYCLES;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierPhase")].empty()) {
+        rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_PHASE;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierPhaseUncertainty")].empty()) {
+        rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_PHASE_UNCERTAINTY;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("AgcDb")].empty()) {
+        rawMeasurementFlags |= GnssMeasurement::HAS_AUTOMATIC_GAIN_CONTROL;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("FullInterSignalBiasNanos")].empty()) {
+        rawMeasurementFlags |= GnssMeasurement::HAS_FULL_ISB;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("FullInterSignalBiasUncertaintyNanos")]
+                 .empty()) {
+        rawMeasurementFlags |= GnssMeasurement::HAS_FULL_ISB_UNCERTAINTY;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at("SatelliteInterSignalBiasNanos")]
+                 .empty()) {
+        rawMeasurementFlags |= GnssMeasurement::HAS_SATELLITE_ISB;
+    }
+    if (!rawMeasurementRecordValues[columnNameIdMapping.at(
+                                            "SatelliteInterSignalBiasUncertaintyNanos")]
+                 .empty()) {
+        rawMeasurementFlags |= GnssMeasurement::HAS_SATELLITE_ISB_UNCERTAINTY;
+    }
+    // HAS_SATELLITE_PVT and HAS_CORRELATION_VECTOR fields currently not in rawmeasurement
+    // output, need add them later.
+    return rawMeasurementFlags;
+}
+
+GnssConstellationType GnssRawMeasurementParser::getGnssConstellationType(int constellationType) {
+    GnssConstellationType gnssConstellationType =
+            aidl::android::hardware::gnss::GnssConstellationType::UNKNOWN;
+
+    switch (constellationType) {
+        case 1:
+            gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::GPS;
+            break;
+        case 2:
+            gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::SBAS;
+            break;
+        case 3:
+            gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::GLONASS;
+            break;
+        case 4:
+            gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::QZSS;
+            break;
+        case 5:
+            gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::BEIDOU;
+            break;
+        case 6:
+            gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::GALILEO;
+            break;
+        default:
+            gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::UNKNOWN;
+    }
+
+    return gnssConstellationType;
+}
+
+std::unique_ptr<GnssData> GnssRawMeasurementParser::getMeasurementFromStrs(
+        std::string& rawMeasurementStr) {
+    /*
+     * Raw,utcTimeMillis,TimeNanos,LeapSecond,TimeUncertaintyNanos,FullBiasNanos,BiasNanos,
+     * BiasUncertaintyNanos,DriftNanosPerSecond,DriftUncertaintyNanosPerSecond,
+     * HardwareClockDiscontinuityCount,Svid,TimeOffsetNanos,State,ReceivedSvTimeNanos,
+     * ReceivedSvTimeUncertaintyNanos,Cn0DbHz,PseudorangeRateMetersPerSecond,
+     * PseudorangeRateUncertaintyMetersPerSecond,AccumulatedDeltaRangeState,
+     * AccumulatedDeltaRangeMeters,AccumulatedDeltaRangeUncertaintyMeters,CarrierFrequencyHz,
+     * CarrierCycles,CarrierPhase,CarrierPhaseUncertainty,MultipathIndicator,SnrInDb,
+     * ConstellationType,AgcDb,BasebandCn0DbHz,FullInterSignalBiasNanos,
+     * FullInterSignalBiasUncertaintyNanos,SatelliteInterSignalBiasNanos,
+     * SatelliteInterSignalBiasUncertaintyNanos,CodeType,ChipsetElapsedRealtimeNanos
+     */
+    ALOGD("Parsing %zu bytes rawMeasurementStr.", rawMeasurementStr.size());
+    if (rawMeasurementStr.empty()) {
+        return nullptr;
+    }
+    std::vector<std::string> rawMeasurementStrRecords;
+    ParseUtils::splitStr(rawMeasurementStr, LINE_SEPARATOR, rawMeasurementStrRecords);
+    if (rawMeasurementStrRecords.size() <= 1) {
+        ALOGE("Raw GNSS Measurements parser failed. (No records) ");
+        return nullptr;
+    }
+
+    // Get the column name mapping from the header.
+    std::unordered_map<std::string, int> columnNameIdMapping =
+            getColumnIdNameMappingFromHeader(rawMeasurementStrRecords[0]);
+
+    if (columnNameIdMapping.size() < 37 || !ParseUtils::isValidHeader(columnNameIdMapping)) {
+        ALOGE("Raw GNSS Measurements parser failed. (No header or missing columns.) ");
+        return nullptr;
+    }
+
+    // Set GnssClock from 1st record.
+    std::size_t pointer = 1;
+    std::vector<std::string> firstRecordValues;
+    ParseUtils::splitStr(rawMeasurementStrRecords[pointer], COMMA_SEPARATOR, firstRecordValues);
+    GnssClock clock = {
+            .gnssClockFlags = getClockFlags(firstRecordValues, columnNameIdMapping),
+            .timeNs = ParseUtils::tryParseLongLong(
+                    firstRecordValues[columnNameIdMapping.at("TimeNanos")], 0),
+            .fullBiasNs = ParseUtils::tryParseLongLong(
+                    firstRecordValues[columnNameIdMapping.at("FullBiasNanos")], 0),
+            .biasNs = ParseUtils::tryParseDouble(
+                    firstRecordValues[columnNameIdMapping.at("BiasNanos")], 0),
+            .biasUncertaintyNs = ParseUtils::tryParseDouble(
+                    firstRecordValues[columnNameIdMapping.at("BiasUncertaintyNanos")], 0),
+            .driftNsps = ParseUtils::tryParseDouble(
+                    firstRecordValues[columnNameIdMapping.at("DriftNanosPerSecond")], 0),
+            .driftUncertaintyNsps = ParseUtils::tryParseDouble(
+                    firstRecordValues[columnNameIdMapping.at("DriftNanosPerSecond")], 0),
+            .hwClockDiscontinuityCount = ParseUtils::tryParseInt(
+                    firstRecordValues[columnNameIdMapping.at("HardwareClockDiscontinuityCount")],
+                    0)};
+
+    ElapsedRealtime timestamp = {
+            .flags = getElapsedRealtimeFlags(firstRecordValues, columnNameIdMapping),
+            .timestampNs = ParseUtils::tryParseLongLong(
+                    firstRecordValues[columnNameIdMapping.at("ChipsetElapsedRealtimeNanos")]),
+            .timeUncertaintyNs = ParseUtils::tryParseDouble(
+                    firstRecordValues[columnNameIdMapping.at("TimeUncertaintyNanos")], 0)};
+
+    std::vector<GnssMeasurement> measurementsVec;
+    for (pointer = 1; pointer < rawMeasurementStrRecords.size(); pointer++) {
+        std::vector<std::string> rawMeasurementValues;
+        std::string line = rawMeasurementStrRecords[pointer];
+        ParseUtils::splitStr(line, COMMA_SEPARATOR, rawMeasurementValues);
+        GnssSignalType signalType = {
+                .constellation = getGnssConstellationType(ParseUtils::tryParseInt(
+                        rawMeasurementValues[columnNameIdMapping.at("ConstellationType")], 0)),
+                .carrierFrequencyHz = ParseUtils::tryParseDouble(
+                        rawMeasurementValues[columnNameIdMapping.at("CarrierFrequencyHz")], 0),
+                .codeType = rawMeasurementValues[columnNameIdMapping.at("CodeType")],
+        };
+        GnssMeasurement measurement = {
+                .flags = getRawMeasurementFlags(rawMeasurementValues, columnNameIdMapping),
+                .svid = ParseUtils::tryParseInt(
+                        rawMeasurementValues[columnNameIdMapping.at("Svid")], 0),
+                .signalType = signalType,
+                .receivedSvTimeInNs = ParseUtils::tryParseLongLong(
+                        rawMeasurementValues[columnNameIdMapping.at("ReceivedSvTimeNanos")], 0),
+                .receivedSvTimeUncertaintyInNs =
+                        ParseUtils::tryParseLongLong(rawMeasurementValues[columnNameIdMapping.at(
+                                                             "ReceivedSvTimeUncertaintyNanos")],
+                                                     0),
+                .antennaCN0DbHz = ParseUtils::tryParseDouble(
+                        rawMeasurementValues[columnNameIdMapping.at("Cn0DbHz")], 0),
+                .basebandCN0DbHz = ParseUtils::tryParseDouble(
+                        rawMeasurementValues[columnNameIdMapping.at("BasebandCn0DbHz")], 0),
+                .agcLevelDb = ParseUtils::tryParseDouble(
+                        rawMeasurementValues[columnNameIdMapping.at("AgcDb")], 0),
+                .pseudorangeRateMps =
+                        ParseUtils::tryParseDouble(rawMeasurementValues[columnNameIdMapping.at(
+                                                           "PseudorangeRateMetersPerSecond")],
+                                                   0),
+                .pseudorangeRateUncertaintyMps = ParseUtils::tryParseDouble(
+                        rawMeasurementValues[columnNameIdMapping.at(
+                                "PseudorangeRateUncertaintyMetersPerSecond")],
+                        0),
+                .accumulatedDeltaRangeState = ParseUtils::tryParseInt(
+                        rawMeasurementValues[columnNameIdMapping.at("AccumulatedDeltaRangeState")],
+                        0),
+                .accumulatedDeltaRangeM = ParseUtils::tryParseDouble(
+                        rawMeasurementValues[columnNameIdMapping.at("AccumulatedDeltaRangeMeters")],
+                        0),
+                .accumulatedDeltaRangeUncertaintyM = ParseUtils::tryParseDouble(
+                        rawMeasurementValues[columnNameIdMapping.at(
+                                "AccumulatedDeltaRangeUncertaintyMeters")],
+                        0),
+                .multipathIndicator = GnssMultipathIndicator::UNKNOWN,  // Not in GnssLogger yet.
+                .state = ParseUtils::tryParseInt(
+                        rawMeasurementValues[columnNameIdMapping.at("State")], 0),
+                .fullInterSignalBiasNs = ParseUtils::tryParseDouble(rawMeasurementValues[31], 0),
+                .fullInterSignalBiasUncertaintyNs = ParseUtils::tryParseDouble(
+                        rawMeasurementValues[columnNameIdMapping.at("FullInterSignalBiasNanos")],
+                        0),
+                .satelliteInterSignalBiasNs =
+                        ParseUtils::tryParseDouble(rawMeasurementValues[columnNameIdMapping.at(
+                                                           "SatelliteInterSignalBiasNanos")],
+                                                   0),
+                .satelliteInterSignalBiasUncertaintyNs = ParseUtils::tryParseDouble(
+                        rawMeasurementValues[columnNameIdMapping.at(
+                                "SatelliteInterSignalBiasUncertaintyNanos")],
+                        0),
+                .satellitePvt = {},
+                .correlationVectors = {}};
+        measurementsVec.push_back(measurement);
+    }
+
+    GnssData gnssData = {
+            .measurements = measurementsVec, .clock = clock, .elapsedRealtime = timestamp};
+    return std::make_unique<GnssData>(gnssData);
+}
+
+}  // namespace common
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/common/utils/default/GnssReplayUtils.cpp b/gnss/common/utils/default/GnssReplayUtils.cpp
new file mode 100644
index 0000000..d6769bd
--- /dev/null
+++ b/gnss/common/utils/default/GnssReplayUtils.cpp
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+#include "GnssReplayUtils.h"
+
+#include <array>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+std::string ReplayUtils::getGnssPath() {
+    std::array<char, PROPERTY_VALUE_MAX> devname_value;
+
+    devname_value.fill(0);
+    if (property_get("debug.location.gnss.devname", devname_value.begin(), NULL) > 0) {
+        return devname_value.begin();
+    }
+
+    devname_value.fill(0);
+    if (property_get("vendor.ser.gnss-uart", devname_value.begin(), NULL) > 0) {
+        return devname_value.begin();
+    }
+
+    return GNSS_PATH;
+}
+
+std::string ReplayUtils::getFixedLocationPath() {
+    std::array<char, PROPERTY_VALUE_MAX> devname_value;
+
+    devname_value.fill(0);
+    if (property_get("debug.location.fixedlocation.devname", devname_value.begin(), NULL) > 0) {
+        return devname_value.begin();
+    }
+
+    devname_value.fill(0);
+    if (property_get("vendor.ser.gnss-uart", devname_value.begin(), NULL) > 0) {
+        return devname_value.begin();
+    }
+
+    return FIXED_LOCATION_PATH;
+}
+
+bool ReplayUtils::hasGnssDeviceFile() {
+    struct stat sb;
+    return stat(getGnssPath().c_str(), &sb) != -1;
+}
+
+bool ReplayUtils::hasFixedLocationDeviceFile() {
+    struct stat sb;
+    return stat(getFixedLocationPath().c_str(), &sb) != -1;
+}
+
+bool ReplayUtils::isGnssRawMeasurement(const std::string& inputStr) {
+    // TODO: add more logic check to by pass invalid data.
+    return !inputStr.empty() && (inputStr.find("Raw") != std::string::npos);
+}
+
+bool ReplayUtils::isNMEA(const std::string& inputStr) {
+    return !inputStr.empty() && (inputStr.find("$GPRMC,", 0) != std::string::npos ||
+                                 inputStr.find("$GPRMA,", 0) != std::string::npos);
+}
+
+}  // namespace common
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/common/utils/default/ParseUtils.cpp b/gnss/common/utils/default/ParseUtils.cpp
new file mode 100644
index 0000000..648edf7
--- /dev/null
+++ b/gnss/common/utils/default/ParseUtils.cpp
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+#include <ParseUtils.h>
+#include <sstream>
+#include <stdexcept>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+int ParseUtils::tryParseInt(const std::string& s, int defaultVal) {
+    if (s.empty()) {
+        return defaultVal;
+    } else {
+        return std::stoi(s);
+    }
+}
+
+float ParseUtils::tryParsefloat(const std::string& s, float defaultVal) {
+    if (s.empty()) {
+        return defaultVal;
+    } else {
+        return std::stof(s);
+    }
+}
+
+double ParseUtils::tryParseDouble(const std::string& s, double defaultVal) {
+    if (s.empty()) {
+        return defaultVal;
+    } else {
+        return std::stod(s);
+    }
+}
+
+long ParseUtils::tryParseLong(const std::string& s, long defaultVal) {
+    if (s.empty()) {
+        return defaultVal;
+    } else {
+        return std::stol(s);
+    }
+}
+
+long long ParseUtils::tryParseLongLong(const std::string& s, long long defaultVal) {
+    if (s.empty()) {
+        return defaultVal;
+    } else {
+        return std::stoll(s);
+    }
+}
+
+void ParseUtils::splitStr(const std::string& line, const char& delimiter,
+                          std::vector<std::string>& out) {
+    std::istringstream iss(line);
+    std::string item;
+    while (std::getline(iss, item, delimiter)) {
+        out.push_back(item);
+    }
+}
+
+bool ParseUtils::isValidHeader(const std::unordered_map<std::string, int>& columnNameIdMapping) {
+    std::vector<std::string> requiredHeaderColumns = {"Raw",
+                                                      "utcTimeMillis",
+                                                      "TimeNanos",
+                                                      "LeapSecond",
+                                                      "TimeUncertaintyNanos",
+                                                      "FullBiasNanos",
+                                                      "BiasNanos",
+                                                      "BiasUncertaintyNanos",
+                                                      "DriftNanosPerSecond",
+                                                      "DriftUncertaintyNanosPerSecond",
+                                                      "HardwareClockDiscontinuityCount",
+                                                      "Svid",
+                                                      "TimeOffsetNanos",
+                                                      "State",
+                                                      "ReceivedSvTimeNanos",
+                                                      "ReceivedSvTimeUncertaintyNanos",
+                                                      "Cn0DbHz",
+                                                      "PseudorangeRateMetersPerSecond",
+                                                      "PseudorangeRateUncertaintyMetersPerSecond",
+                                                      "AccumulatedDeltaRangeState",
+                                                      "AccumulatedDeltaRangeMeters",
+                                                      "AccumulatedDeltaRangeUncertaintyMeters",
+                                                      "CarrierFrequencyHz",
+                                                      "CarrierCycles",
+                                                      "CarrierPhase",
+                                                      "CarrierPhaseUncertainty",
+                                                      "MultipathIndicator",
+                                                      "SnrInDb",
+                                                      "ConstellationType",
+                                                      "AgcDb",
+                                                      "BasebandCn0DbHz",
+                                                      "FullInterSignalBiasNanos",
+                                                      "FullInterSignalBiasUncertaintyNanos",
+                                                      "SatelliteInterSignalBiasNanos",
+                                                      "SatelliteInterSignalBiasUncertaintyNanos",
+                                                      "CodeType",
+                                                      "ChipsetElapsedRealtimeNanos"};
+
+    for (const auto& columnName : requiredHeaderColumns) {
+        if (columnNameIdMapping.find(columnName) == columnNameIdMapping.end()) {
+            ALOGE("Missing column %s in header.", columnName.c_str());
+            return false;
+        }
+    }
+
+    return true;
+}
+
+}  // namespace common
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/common/utils/default/include/Constants.h b/gnss/common/utils/default/include/Constants.h
index 22afee1..489413e 100644
--- a/gnss/common/utils/default/include/Constants.h
+++ b/gnss/common/utils/default/include/Constants.h
@@ -34,6 +34,19 @@
 const float kGloG1FreqHz = 1602.0 * 1e6;
 const float kIrnssL5FreqHz = 1176.45 * 1e6;
 
+// Location replay constants
+constexpr char GNSS_PATH[] = "/dev/gnss0";
+constexpr char FIXED_LOCATION_PATH[] = "/dev/gnss1";
+constexpr int INPUT_BUFFER_SIZE = 256;
+constexpr char CMD_GET_LOCATION[] = "CMD_GET_LOCATION";
+constexpr char CMD_GET_RAWMEASUREMENT[] = "CMD_GET_RAWMEASUREMENT";
+constexpr char LINE_SEPARATOR = '\n';
+constexpr char COMMA_SEPARATOR = ',';
+constexpr char GPGA_RECORD_TAG[] = "$GPGGA";
+constexpr char GPRMC_RECORD_TAG[] = "$GPRMC";
+constexpr double TIMESTAMP_EPSILON = 0.001;
+constexpr int MIN_COL_NUM = 13;
+
 }  // namespace common
 }  // namespace gnss
 }  // namespace hardware
diff --git a/gnss/common/utils/default/include/DeviceFileReader.h b/gnss/common/utils/default/include/DeviceFileReader.h
new file mode 100644
index 0000000..c2a5c5f
--- /dev/null
+++ b/gnss/common/utils/default/include/DeviceFileReader.h
@@ -0,0 +1,53 @@
+
+/*
+ * 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.
+ */
+#ifndef android_hardware_gnss_common_default_DeviceFileReader_H_
+#define android_hardware_gnss_common_default_DeviceFileReader_H_
+
+#include <log/log.h>
+#include <mutex>
+#include <string>
+#include <unordered_map>
+#include "Constants.h"
+#include "GnssReplayUtils.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+class DeviceFileReader {
+  public:
+    static DeviceFileReader& Instance() {
+        static DeviceFileReader reader;
+        return reader;
+    }
+    std::string getLocationData();
+    std::string getGnssRawMeasurementData();
+    void getDataFromDeviceFile(const std::string& command, int mMinIntervalMs);
+
+  private:
+    DeviceFileReader();
+    ~DeviceFileReader();
+    std::unordered_map<std::string, std::string> data_;
+    std::string s_buffer_;
+    std::mutex mMutex;
+};
+}  // namespace common
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_common_default_DeviceFileReader_H_
\ No newline at end of file
diff --git a/gnss/common/utils/default/include/FixLocationParser.h b/gnss/common/utils/default/include/FixLocationParser.h
new file mode 100644
index 0000000..19748a9
--- /dev/null
+++ b/gnss/common/utils/default/include/FixLocationParser.h
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_gnss_common_default_FixLocationParser_H_
+#define android_hardware_gnss_common_default_FixLocationParser_H_
+
+#include <android/hardware/gnss/2.0/IGnss.h>
+
+#include <utils/SystemClock.h>
+#include <string>
+#include <vector>
+
+#include <Constants.h>
+#include <Utils.h>
+#include <log/log.h>
+#include "Constants.h"
+#include "ParseUtils.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+struct FixLocationParser {
+  public:
+    static std::unique_ptr<V2_0::GnssLocation> getLocationFromInputStr(const std::string& inputStr);
+};
+
+}  // namespace common
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_common_default_FixLocationParser_H_
diff --git a/gnss/common/utils/default/include/GnssRawMeasurementParser.h b/gnss/common/utils/default/include/GnssRawMeasurementParser.h
new file mode 100644
index 0000000..7d6b4ef
--- /dev/null
+++ b/gnss/common/utils/default/include/GnssRawMeasurementParser.h
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_gnss_common_default_GnssRawMeasurementParser_H_
+#define android_hardware_gnss_common_default_GnssRawMeasurementParser_H_
+
+#include <aidl/android/hardware/gnss/BnGnss.h>
+#include <log/log.h>
+#include <utils/SystemClock.h>
+#include <string>
+#include <unordered_map>
+
+#include "Constants.h"
+#include "ParseUtils.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+struct GnssRawMeasurementParser {
+    static std::unique_ptr<aidl::android::hardware::gnss::GnssData> getMeasurementFromStrs(
+            std::string& rawMeasurementStr);
+    static int getClockFlags(const std::vector<std::string>& rawMeasurementRecordValues,
+                             const std::unordered_map<std::string, int>& columnNameIdMapping);
+    static int getElapsedRealtimeFlags(
+            const std::vector<std::string>& rawMeasurementRecordValues,
+            const std::unordered_map<std::string, int>& columnNameIdMapping);
+    static int getRawMeasurementFlags(
+            const std::vector<std::string>& rawMeasurementRecordValues,
+            const std::unordered_map<std::string, int>& columnNameIdMapping);
+    static std::unordered_map<std::string, int> getColumnIdNameMappingFromHeader(
+            const std::string& header);
+    static aidl::android::hardware::gnss::GnssConstellationType getGnssConstellationType(
+            int constellationType);
+};
+
+}  // namespace common
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_common_default_GnssRawMeasurementParser_H_
\ No newline at end of file
diff --git a/gnss/common/utils/default/include/GnssReplayUtils.h b/gnss/common/utils/default/include/GnssReplayUtils.h
new file mode 100644
index 0000000..d1bbed4
--- /dev/null
+++ b/gnss/common/utils/default/include/GnssReplayUtils.h
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_gnss_common_GnssReplayUtils_H_
+#define android_hardware_gnss_common_GnssReplayUtils_H_
+
+#include <cutils/properties.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <log/log.h>
+#include <sys/epoll.h>
+#include <sys/stat.h>
+#include <chrono>
+#include <string>
+#include <thread>
+
+#include "Constants.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+struct ReplayUtils {
+    static std::string getGnssPath();
+
+    static std::string getFixedLocationPath();
+
+    static std::string getDataFromDeviceFile(const std::string& command, int mMinIntervalMs);
+
+    static bool hasGnssDeviceFile();
+
+    static bool hasFixedLocationDeviceFile();
+
+    static bool isGnssRawMeasurement(const std::string& inputStr);
+
+    static bool isNMEA(const std::string& inputStr);
+};
+
+}  // namespace common
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_common_GnssReplayUtils_H_
diff --git a/gnss/common/utils/default/include/NmeaFixInfo.h b/gnss/common/utils/default/include/NmeaFixInfo.h
index c96eece..5c27045 100644
--- a/gnss/common/utils/default/include/NmeaFixInfo.h
+++ b/gnss/common/utils/default/include/NmeaFixInfo.h
@@ -27,13 +27,6 @@
 namespace gnss {
 namespace common {
 
-constexpr char GPGA_RECORD_TAG[] = "$GPGGA";
-constexpr char GPRMC_RECORD_TAG[] = "$GPRMC";
-constexpr char LINE_SEPARATOR = '\n';
-constexpr char COMMA_SEPARATOR = ',';
-constexpr double TIMESTAMP_EPSILON = 0.001;
-constexpr int MIN_COL_NUM = 13;
-
 /** Helper class to parse and store the GNSS fix details information. */
 class NmeaFixInfo {
   private:
diff --git a/gnss/common/utils/default/include/ParseUtils.h b/gnss/common/utils/default/include/ParseUtils.h
new file mode 100644
index 0000000..3a56313
--- /dev/null
+++ b/gnss/common/utils/default/include/ParseUtils.h
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_gnss_common_default_ParseUtils_H_
+#define android_hardware_gnss_common_default_ParseUtils_H_
+
+#include <log/log.h>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+struct ParseUtils {
+    static int tryParseInt(const std::string& s, int defaultVal = 0);
+    static float tryParsefloat(const std::string& s, float defaultVal = 0.0);
+    static double tryParseDouble(const std::string& s, double defaultVal = 0.0);
+    static long tryParseLong(const std::string& s, long defaultVal = 0);
+    static long long tryParseLongLong(const std::string& s, long long defaultVal = 0);
+    static void splitStr(const std::string& line, const char& delimiter,
+                         std::vector<std::string>& out);
+    static bool isValidHeader(const std::unordered_map<std::string, int>& columnNameIdMapping);
+};
+
+}  // namespace common
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_common_default_ParseUtils_H_
\ No newline at end of file
diff --git a/gnss/common/utils/default/include/v2_1/GnssTemplate.h b/gnss/common/utils/default/include/v2_1/GnssTemplate.h
index 131af24..473e587 100644
--- a/gnss/common/utils/default/include/v2_1/GnssTemplate.h
+++ b/gnss/common/utils/default/include/v2_1/GnssTemplate.h
@@ -30,13 +30,15 @@
 
 #include <cutils/properties.h>
 
+#include "DeviceFileReader.h"
+#include "FixLocationParser.h"
 #include "GnssAntennaInfo.h"
 #include "GnssConfiguration.h"
 #include "GnssDebug.h"
 #include "GnssMeasurement.h"
 #include "GnssMeasurementCorrections.h"
+#include "GnssReplayUtils.h"
 #include "MockLocation.h"
-#include "NmeaFixInfo.h"
 #include "Utils.h"
 
 namespace android::hardware::gnss::common::implementation {
@@ -159,53 +161,13 @@
 
 template <class T_IGnss>
 std::unique_ptr<V2_0::GnssLocation> GnssTemplate<T_IGnss>::getLocationFromHW() {
-    char inputBuffer[INPUT_BUFFER_SIZE];
-    if (!mHardwareModeChecked) {
-        // default using gnss0
-        const char * gnss_dev_path = GNSS_PATH;
-        char devname_value[PROPERTY_VALUE_MAX] = "";
-        if (property_get("debug.location.gnss.devname", devname_value, NULL) > 0) {
-            gnss_dev_path = devname_value;
-            ALOGD("using %s instead of the default %s", gnss_dev_path, GNSS_PATH);
-        }
-
-        mGnssFd = open(gnss_dev_path, O_RDWR | O_NONBLOCK);
-        if (mGnssFd == -1) {
-            ALOGW("Failed to open %s errno: %d", gnss_dev_path, errno);
-        }
-        mHardwareModeChecked = true;
-    }
-
-    if (mGnssFd == -1) {
+    mHardwareModeChecked = true;
+    if (!ReplayUtils::hasFixedLocationDeviceFile()) {
         return nullptr;
     }
-
-    int bytes_write = write(mGnssFd, CMD_GET_LOCATION, strlen(CMD_GET_LOCATION));
-    if (bytes_write <= 0) {
-        return nullptr;
-    }
-
-    struct epoll_event ev, events[1];
-    ev.data.fd = mGnssFd;
-    ev.events = EPOLLIN;
-    int epoll_fd = epoll_create1(0);
-    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, mGnssFd, &ev);
-    int bytes_read = -1;
-    std::string inputStr = "";
-    int epoll_ret = epoll_wait(epoll_fd, events, 1, mMinIntervalMs);
-
-    if (epoll_ret == -1) {
-        return nullptr;
-    }
-    while (true) {
-        memset(inputBuffer, 0, INPUT_BUFFER_SIZE);
-        bytes_read = read(mGnssFd, &inputBuffer, INPUT_BUFFER_SIZE);
-        if (bytes_read <= 0) {
-            break;
-        }
-        inputStr += std::string(inputBuffer, bytes_read);
-    }
-    return NmeaFixInfo::getLocationFromInputStr(inputStr);
+    std::string inputStr =
+            ::android::hardware::gnss::common::DeviceFileReader::Instance().getLocationData();
+    return FixLocationParser::getLocationFromInputStr(inputStr);
 }
 
 template <class T_IGnss>
@@ -223,14 +185,8 @@
             this->reportSvStatus(svStatus);
             auto currentLocation = getLocationFromHW();
             notePowerConsumption();
-            if (mGnssFd != -1) {
-                // Only report location if the return from hardware is valid
-                // note that we can not merge these two "if" together, if didn't
-                // get location from hardware, we shouldn't report location, not
-                // report the "default" one.
-                if (currentLocation != nullptr) {
-                    this->reportLocation(*currentLocation);
-                }
+            if (currentLocation != nullptr) {
+                this->reportLocation(*currentLocation);
             } else {
                 if (sGnssCallback_2_1 != nullptr || sGnssCallback_2_0 != nullptr) {
                     const auto location = Utils::getMockLocationV2_0();
diff --git a/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp b/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp
index 1ead138..ccbc5b1 100644
--- a/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp
+++ b/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp
@@ -30,7 +30,7 @@
 
 std::vector<Display> GraphicsComposerCallback::getDisplays() const {
     std::lock_guard<std::mutex> lock(mMutex);
-    return std::vector<Display>(mDisplays.begin(), mDisplays.end());
+    return mDisplays;
 }
 
 int GraphicsComposerCallback::getInvalidHotplugCount() const {
@@ -51,12 +51,17 @@
 Return<void> GraphicsComposerCallback::onHotplug(Display display, Connection connection) {
     std::lock_guard<std::mutex> lock(mMutex);
 
+    auto it = std::find(mDisplays.begin(), mDisplays.end(), display);
     if (connection == Connection::CONNECTED) {
-        if (!mDisplays.insert(display).second) {
+        if (it == mDisplays.end()) {
+            mDisplays.push_back(display);
+        } else {
             mInvalidHotplugCount++;
         }
     } else if (connection == Connection::DISCONNECTED) {
-        if (!mDisplays.erase(display)) {
+        if (it != mDisplays.end()) {
+            mDisplays.erase(it);
+        } else {
             mInvalidHotplugCount++;
         }
     }
@@ -67,7 +72,8 @@
 Return<void> GraphicsComposerCallback::onRefresh(Display display) {
     std::lock_guard<std::mutex> lock(mMutex);
 
-    if (mDisplays.count(display) == 0) {
+    auto it = std::find(mDisplays.begin(), mDisplays.end(), display);
+    if (it == mDisplays.end()) {
         mInvalidRefreshCount++;
     }
 
@@ -77,7 +83,8 @@
 Return<void> GraphicsComposerCallback::onVsync(Display display, int64_t) {
     std::lock_guard<std::mutex> lock(mMutex);
 
-    if (!mVsyncAllowed || mDisplays.count(display) == 0) {
+    auto it = std::find(mDisplays.begin(), mDisplays.end(), display);
+    if (!mVsyncAllowed || it == mDisplays.end()) {
         mInvalidVsyncCount++;
     }
 
diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h
index e3c348f..da64052 100644
--- a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h
@@ -19,7 +19,7 @@
 #include <android/hardware/graphics/composer/2.1/IComposerCallback.h>
 
 #include <mutex>
-#include <unordered_set>
+#include <vector>
 
 namespace android {
 namespace hardware {
@@ -48,7 +48,7 @@
 
     mutable std::mutex mMutex;
     // the set of all currently connected displays
-    std::unordered_set<Display> mDisplays;
+    std::vector<Display> mDisplays;
     // true only when vsync is enabled
     bool mVsyncAllowed = true;
 
diff --git a/graphics/composer/2.4/utils/vts/GraphicsComposerCallback.cpp b/graphics/composer/2.4/utils/vts/GraphicsComposerCallback.cpp
index c9366a8..51e1ab7 100644
--- a/graphics/composer/2.4/utils/vts/GraphicsComposerCallback.cpp
+++ b/graphics/composer/2.4/utils/vts/GraphicsComposerCallback.cpp
@@ -25,7 +25,7 @@
 
 std::vector<Display> GraphicsComposerCallback::getDisplays() const {
     std::lock_guard<std::mutex> lock(mMutex);
-    return std::vector<Display>(mDisplays.begin(), mDisplays.end());
+    return mDisplays;
 }
 
 int32_t GraphicsComposerCallback::getInvalidHotplugCount() const {
@@ -71,12 +71,17 @@
 Return<void> GraphicsComposerCallback::onHotplug(Display display, Connection connection) {
     std::lock_guard<std::mutex> lock(mMutex);
 
+    auto it = std::find(mDisplays.begin(), mDisplays.end(), display);
     if (connection == Connection::CONNECTED) {
-        if (!mDisplays.insert(display).second) {
+        if (it == mDisplays.end()) {
+            mDisplays.push_back(display);
+        } else {
             mInvalidHotplugCount++;
         }
     } else if (connection == Connection::DISCONNECTED) {
-        if (!mDisplays.erase(display)) {
+        if (it != mDisplays.end()) {
+            mDisplays.erase(it);
+        } else {
             mInvalidHotplugCount++;
         }
     }
@@ -87,7 +92,8 @@
 Return<void> GraphicsComposerCallback::onRefresh(Display display) {
     std::lock_guard<std::mutex> lock(mMutex);
 
-    if (mDisplays.count(display) == 0) {
+    auto it = std::find(mDisplays.begin(), mDisplays.end(), display);
+    if (it == mDisplays.end()) {
         mInvalidRefreshCount++;
     }
 
@@ -106,7 +112,8 @@
 Return<void> GraphicsComposerCallback::onVsync_2_4(Display display, int64_t, VsyncPeriodNanos) {
     std::lock_guard<std::mutex> lock(mMutex);
 
-    if (!mVsyncAllowed || mDisplays.count(display) == 0) {
+    auto it = std::find(mDisplays.begin(), mDisplays.end(), display);
+    if (!mVsyncAllowed || it == mDisplays.end()) {
         mInvalidVsync_2_4Count++;
     }
 
@@ -117,7 +124,8 @@
         Display display, const VsyncPeriodChangeTimeline& updatedTimeline) {
     std::lock_guard<std::mutex> lock(mMutex);
 
-    if (mDisplays.count(display) == 0) {
+    auto it = std::find(mDisplays.begin(), mDisplays.end(), display);
+    if (it == mDisplays.end()) {
         mInvalidVsyncPeriodChangeCount++;
     }
 
@@ -134,4 +142,4 @@
     return Void();
 }
 
-}  // namespace android::hardware::graphics::composer::V2_4::vts
\ No newline at end of file
+}  // namespace android::hardware::graphics::composer::V2_4::vts
diff --git a/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/GraphicsComposerCallback.h b/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/GraphicsComposerCallback.h
index f4e23ae..c03070b 100644
--- a/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/GraphicsComposerCallback.h
+++ b/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/GraphicsComposerCallback.h
@@ -18,7 +18,7 @@
 #include <android/hardware/graphics/composer/2.4/IComposerCallback.h>
 
 #include <mutex>
-#include <unordered_set>
+#include <vector>
 
 namespace android::hardware::graphics::composer::V2_4::vts {
 
@@ -56,7 +56,7 @@
 
     mutable std::mutex mMutex;
     // the set of all currently connected displays
-    std::unordered_set<Display> mDisplays;
+    std::vector<Display> mDisplays;
     // true only when vsync is enabled
     bool mVsyncAllowed = true;
 
diff --git a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
index 5aceda7..b071f71 100644
--- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
+++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
@@ -19,8 +19,6 @@
 #include <algorithm>
 #include <regex>
 #include <thread>
-#include <unordered_map>
-#include <utility>
 
 #include <android-base/logging.h>
 #include <android-base/properties.h>
@@ -317,59 +315,6 @@
     }
 }
 
-TEST_P(GraphicsComposerHidlTest, GetDisplayAttribute_2_4_ConfigsInAGroupDifferOnlyByVsyncPeriod) {
-    struct Resolution {
-        int32_t width, height;
-    };
-    struct Dpi {
-        int32_t x, y;
-    };
-    for (const auto& display : mDisplays) {
-        std::vector<Config> configs = mComposerClient->getDisplayConfigs(display.get());
-        std::unordered_map<int32_t, Resolution> configGroupToResolutionMap;
-        std::unordered_map<int32_t, Dpi> configGroupToDpiMap;
-        for (auto config : configs) {
-            const auto configGroup = mComposerClient->getDisplayAttribute_2_4(
-                    display.get(), config, IComposerClient::Attribute::CONFIG_GROUP);
-            const auto width = mComposerClient->getDisplayAttribute_2_4(
-                    display.get(), config, IComposerClient::Attribute::WIDTH);
-            const auto height = mComposerClient->getDisplayAttribute_2_4(
-                    display.get(), config, IComposerClient::Attribute::HEIGHT);
-            if (configGroupToResolutionMap.find(configGroup) == configGroupToResolutionMap.end()) {
-                configGroupToResolutionMap[configGroup] = {width, height};
-            }
-            EXPECT_EQ(configGroupToResolutionMap[configGroup].width, width);
-            EXPECT_EQ(configGroupToResolutionMap[configGroup].height, height);
-
-            int32_t dpiX = -1;
-            mComposerClient->getRaw()->getDisplayAttribute_2_4(
-                    display.get(), config, IComposerClient::Attribute::DPI_X,
-                    [&](const auto& tmpError, const auto& value) {
-                        if (tmpError == Error::NONE) {
-                            dpiX = value;
-                        }
-                    });
-            int32_t dpiY = -1;
-            mComposerClient->getRaw()->getDisplayAttribute_2_4(
-                    display.get(), config, IComposerClient::Attribute::DPI_Y,
-                    [&](const auto& tmpError, const auto& value) {
-                        if (tmpError == Error::NONE) {
-                            dpiY = value;
-                        }
-                    });
-            if (dpiX == -1 && dpiY == -1) {
-                continue;
-            }
-
-            if (configGroupToDpiMap.find(configGroup) == configGroupToDpiMap.end()) {
-                configGroupToDpiMap[configGroup] = {dpiX, dpiY};
-            }
-            EXPECT_EQ(configGroupToDpiMap[configGroup].x, dpiX);
-            EXPECT_EQ(configGroupToDpiMap[configGroup].y, dpiY);
-        }
-    }
-}
-
 TEST_P(GraphicsComposerHidlTest, getDisplayVsyncPeriod_BadDisplay) {
     VsyncPeriodNanos vsyncPeriodNanos;
     EXPECT_EQ(Error::BAD_DISPLAY,
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
index f8f5cff..4549f51 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
@@ -32,23 +32,17 @@
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
     EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
-
-    if (getRadioHalCapabilities()) {
-        ASSERT_TRUE(CheckAnyOfErrors(
-                radioRsp_v1_6->rspInfo.error,
-                {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
-    } else {
-        ASSERT_TRUE(CheckAnyOfErrors(
-                radioRsp_v1_6->rspInfo.error,
-                {::android::hardware::radio::V1_6::RadioError::NONE,
-                 ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
-                 ::android::hardware::radio::V1_6::RadioError::OPERATION_NOT_ALLOWED,
-                 ::android::hardware::radio::V1_6::RadioError::MODE_NOT_SUPPORTED,
-                 ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
-                 ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
-                 ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
-                 ::android::hardware::radio::V1_6::RadioError::NO_RESOURCES}));
-    }
+    ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
+                             {::android::hardware::radio::V1_6::RadioError::NONE,
+                              ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+                              ::android::hardware::radio::V1_6::RadioError::OPERATION_NOT_ALLOWED,
+                              ::android::hardware::radio::V1_6::RadioError::MODE_NOT_SUPPORTED,
+                              ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
+                              ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+                              ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+                              ::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED,
+                              ::android::hardware::radio::V1_6::RadioError::NO_RESOURCES}));
 }
 
 /*
@@ -74,23 +68,17 @@
         EXPECT_EQ(std::cv_status::no_timeout, wait());
         EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
         EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
-
-        if (getRadioHalCapabilities()) {
-            ASSERT_TRUE(CheckAnyOfErrors(
-                    radioRsp_v1_6->rspInfo.error,
-                    {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
-        } else {
-            ASSERT_TRUE(CheckAnyOfErrors(
-                    radioRsp_v1_6->rspInfo.error,
-                    {::android::hardware::radio::V1_6::RadioError::NONE,
-                     ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
-                     ::android::hardware::radio::V1_6::RadioError::OPERATION_NOT_ALLOWED,
-                     ::android::hardware::radio::V1_6::RadioError::MODE_NOT_SUPPORTED,
-                     ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
-                     ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
-                     ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
-                     ::android::hardware::radio::V1_6::RadioError::NO_RESOURCES}));
-        }
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_v1_6->rspInfo.error,
+                {::android::hardware::radio::V1_6::RadioError::NONE,
+                 ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+                 ::android::hardware::radio::V1_6::RadioError::OPERATION_NOT_ALLOWED,
+                 ::android::hardware::radio::V1_6::RadioError::MODE_NOT_SUPPORTED,
+                 ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
+                 ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+                 ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+                 ::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED,
+                 ::android::hardware::radio::V1_6::RadioError::NO_RESOURCES}));
     }
 }
 
@@ -515,7 +503,8 @@
     if (getRadioHalCapabilities()) {
         ASSERT_TRUE(CheckAnyOfErrors(
                 radioRsp_v1_6->rspInfo.error,
-                {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
+                {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED,
+                 ::android::hardware::radio::V1_6::RadioError::NONE}));
     } else {
         ASSERT_TRUE(CheckAnyOfErrors(
                 radioRsp_v1_6->rspInfo.error,
@@ -537,7 +526,8 @@
     if (getRadioHalCapabilities()) {
         ASSERT_TRUE(CheckAnyOfErrors(
                 radioRsp_v1_6->rspInfo.error,
-                {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
+                {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED,
+                 ::android::hardware::radio::V1_6::RadioError::NONE}));
     } else {
         ASSERT_TRUE(CheckAnyOfErrors(
                 radioRsp_v1_6->rspInfo.error,
@@ -559,7 +549,8 @@
     if (getRadioHalCapabilities()) {
         ASSERT_TRUE(CheckAnyOfErrors(
                 radioRsp_v1_6->rspInfo.error,
-                {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
+                {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED,
+                 ::android::hardware::radio::V1_6::RadioError::NONE}));
     } else {
         ASSERT_TRUE(CheckAnyOfErrors(
                 radioRsp_v1_6->rspInfo.error,
@@ -580,7 +571,8 @@
     if (getRadioHalCapabilities()) {
         ASSERT_TRUE(CheckAnyOfErrors(
                 radioRsp_v1_6->rspInfo.error,
-                {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
+                {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED,
+                 ::android::hardware::radio::V1_6::RadioError::NONE}));
     } else {
         ASSERT_TRUE(CheckAnyOfErrors(
                 radioRsp_v1_6->rspInfo.error,
@@ -609,12 +601,16 @@
                               ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
                               ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE}));
 
+    // Give some time for modem to fully power up the SIM card
+    sleep(MODEM_SET_SIM_POWER_DELAY_IN_SECONDS);
+
     // setSimCardPower_1_6 does not return  until the request is handled, and should not trigger
     // CardState::ABSENT when turning off power
     if (radioRsp_v1_6->rspInfo.error == ::android::hardware::radio::V1_6::RadioError::NONE) {
         /* Wait some time for setting sim power down and then verify it */
         updateSimCardStatus();
-        EXPECT_EQ(CardState::PRESENT, cardStatus.base.base.base.cardState);
+        // We cannot assert the consistency of CardState here due to b/203031664
+        // EXPECT_EQ(CardState::PRESENT, cardStatus.base.base.base.cardState);
         // applications should be an empty vector of AppStatus
         EXPECT_EQ(0, cardStatus.applications.size());
     }
@@ -631,6 +627,9 @@
                               ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
                               ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE}));
 
+    // Give some time for modem to fully power up the SIM card
+    sleep(MODEM_SET_SIM_POWER_DELAY_IN_SECONDS);
+
     // setSimCardPower_1_6 does not return  until the request is handled. Just verify that we still
     // have CardState::PRESENT after turning the power back on
     if (radioRsp_v1_6->rspInfo.error == ::android::hardware::radio::V1_6::RadioError::NONE) {
@@ -646,6 +645,10 @@
     if (!deviceSupportsFeature(FEATURE_VOICE_CALL)) {
         ALOGI("Skipping emergencyDial because voice call is not supported in device");
         return;
+    } else if (!deviceSupportsFeature(FEATURE_TELEPHONY_GSM) &&
+               !deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
+        ALOGI("Skipping emergencyDial because gsm/cdma radio is not supported in device");
+        return;
     } else {
         ALOGI("Running emergencyDial because voice call is supported in device");
     }
@@ -700,6 +703,10 @@
     if (!deviceSupportsFeature(FEATURE_VOICE_CALL)) {
         ALOGI("Skipping emergencyDial because voice call is not supported in device");
         return;
+    } else if (!deviceSupportsFeature(FEATURE_TELEPHONY_GSM) &&
+               !deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
+        ALOGI("Skipping emergencyDial because gsm/cdma radio is not supported in device");
+        return;
     } else {
         ALOGI("Running emergencyDial because voice call is supported in device");
     }
@@ -753,6 +760,10 @@
     if (!deviceSupportsFeature(FEATURE_VOICE_CALL)) {
         ALOGI("Skipping emergencyDial because voice call is not supported in device");
         return;
+    } else if (!deviceSupportsFeature(FEATURE_TELEPHONY_GSM) &&
+               !deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
+        ALOGI("Skipping emergencyDial because gsm/cdma radio is not supported in device");
+        return;
     } else {
         ALOGI("Running emergencyDial because voice call is supported in device");
     }
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h b/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h
index 54c2977..f041865 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h
+++ b/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h
@@ -47,6 +47,7 @@
 
 #define MODEM_EMERGENCY_CALL_ESTABLISH_TIME 3
 #define MODEM_EMERGENCY_CALL_DISCONNECT_TIME 3
+#define MODEM_SET_SIM_POWER_DELAY_IN_SECONDS 2
 
 #define RADIO_SERVICE_SLOT1_NAME "slot1"  // HAL instance name for SIM slot 1 or single SIM device
 #define RADIO_SERVICE_SLOT2_NAME "slot2"  // HAL instance name for SIM slot 2 on dual SIM device
diff --git a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
index 26ed344..64550ef 100644
--- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
@@ -50,7 +50,7 @@
         vector<KeyCharacteristics> attest_key_characteristics;
         vector<Certificate> attest_key_cert_chain;
         ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                                     .RsaSigningKey(size, 65537)
+                                                     .RsaKey(size, 65537)
                                                      .AttestKey()
                                                      .SetDefaultValidity(),
                                              {} /* attestation signing key */, &attest_key.keyBlob,
@@ -200,7 +200,7 @@
     vector<Certificate> attest_key_cert_chain;
     ASSERT_EQ(ErrorCode::OK,
               GenerateKey(AuthorizationSetBuilder()
-                                  .RsaSigningKey(2048, 65537)
+                                  .RsaKey(2048, 65537)
                                   .AttestKey()
                                   .AttestationChallenge(challenge)
                                   .AttestationApplicationId(app_id)
@@ -299,7 +299,7 @@
 
         EXPECT_EQ(ErrorCode::OK,
                   GenerateKey(AuthorizationSetBuilder()
-                                      .RsaSigningKey(2048, 65537)
+                                      .RsaKey(2048, 65537)
                                       .AttestKey()
                                       .AttestationChallenge("foo")
                                       .AttestationApplicationId("bar")
@@ -371,7 +371,7 @@
 
         EXPECT_EQ(ErrorCode::OK,
                   GenerateKey(AuthorizationSetBuilder()
-                                      .EcdsaSigningKey(EcCurve::P_256)
+                                      .EcdsaKey(EcCurve::P_256)
                                       .AttestKey()
                                       .AttestationChallenge("foo")
                                       .AttestationApplicationId("bar")
@@ -446,7 +446,7 @@
         if ((i & 0x1) == 1) {
             EXPECT_EQ(ErrorCode::OK,
                       GenerateKey(AuthorizationSetBuilder()
-                                          .EcdsaSigningKey(EcCurve::P_256)
+                                          .EcdsaKey(EcCurve::P_256)
                                           .AttestKey()
                                           .AttestationChallenge("foo")
                                           .AttestationApplicationId("bar")
@@ -459,7 +459,7 @@
         } else {
             EXPECT_EQ(ErrorCode::OK,
                       GenerateKey(AuthorizationSetBuilder()
-                                          .RsaSigningKey(2048, 65537)
+                                          .RsaKey(2048, 65537)
                                           .AttestKey()
                                           .AttestationChallenge("foo")
                                           .AttestationApplicationId("bar")
@@ -509,7 +509,7 @@
         vector<KeyCharacteristics> attest_key_characteristics;
         vector<Certificate> attest_key_cert_chain;
         ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                                     .RsaSigningKey(size, 65537)
+                                                     .RsaKey(size, 65537)
                                                      .AttestKey()
                                                      .SetDefaultValidity(),
                                              {} /* attestation signing key */, &attest_key.keyBlob,
@@ -555,12 +555,12 @@
         AttestationKey attest_key;
         vector<KeyCharacteristics> attest_key_characteristics;
         vector<Certificate> attest_key_cert_chain;
-        ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                                     .EcdsaSigningKey(curve)
-                                                     .AttestKey()
-                                                     .SetDefaultValidity(),
-                                             {} /* attestation signing key */, &attest_key.keyBlob,
-                                             &attest_key_characteristics, &attest_key_cert_chain));
+        ASSERT_EQ(
+                ErrorCode::OK,
+                GenerateKey(
+                        AuthorizationSetBuilder().EcdsaKey(curve).AttestKey().SetDefaultValidity(),
+                        {} /* attestation signing key */, &attest_key.keyBlob,
+                        &attest_key_characteristics, &attest_key_cert_chain));
 
         ASSERT_GT(attest_key_cert_chain.size(), 0);
         EXPECT_EQ(attest_key_cert_chain.size(), 1);
@@ -671,7 +671,7 @@
     vector<KeyCharacteristics> attest_key_characteristics;
     vector<Certificate> attest_key_cert_chain;
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                                 .EcdsaSigningKey(EcCurve::P_256)
+                                                 .EcdsaKey(EcCurve::P_256)
                                                  .AttestKey()
                                                  .SetDefaultValidity(),
                                          {} /* attestation signing key */, &attest_key.keyBlob,
@@ -735,7 +735,7 @@
     vector<KeyCharacteristics> attest_key_characteristics;
     vector<Certificate> attest_key_cert_chain;
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                                 .EcdsaSigningKey(EcCurve::P_256)
+                                                 .EcdsaKey(EcCurve::P_256)
                                                  .AttestKey()
                                                  .SetDefaultValidity(),
                                          {} /* attestation signing key */, &attest_key.keyBlob,
diff --git a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
index d7abf07..79716b1 100644
--- a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
+++ b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
@@ -76,6 +76,7 @@
                                       .Digest(Digest::SHA_2_256)
                                       .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
                                       .Authorization(TAG_INCLUDE_UNIQUE_ID)
+                                      .Authorization(TAG_CREATION_DATETIME, 1619621648000)
                                       .AttestationChallenge("challenge")
                                       .AttestationApplicationId("foo")
                                       .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
@@ -102,6 +103,7 @@
                                       .EcdsaSigningKey(EcCurve::P_256)
                                       .Digest(Digest::SHA_2_256)
                                       .Authorization(TAG_INCLUDE_UNIQUE_ID)
+                                      .Authorization(TAG_CREATION_DATETIME, 1619621648000)
                                       .AttestationChallenge("challenge")
                                       .AttestationApplicationId("foo")
                                       .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
@@ -129,6 +131,7 @@
                                       .Digest(Digest::SHA_2_256)
                                       .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
                                       .Authorization(TAG_INCLUDE_UNIQUE_ID)
+                                      .Authorization(TAG_CREATION_DATETIME, 1619621648000)
                                       .AttestationChallenge("challenge")
                                       .AttestationApplicationId("foo")
                                       .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
@@ -184,6 +187,7 @@
                                       .EcdsaSigningKey(EcCurve::P_256)
                                       .Digest(Digest::SHA_2_256)
                                       .Authorization(TAG_INCLUDE_UNIQUE_ID)
+                                      .Authorization(TAG_CREATION_DATETIME, 1619621648000)
                                       .AttestationChallenge("challenge")
                                       .AttestationApplicationId("foo")
                                       .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
@@ -242,14 +246,16 @@
 
     for (const KeyParameter& tag : attestation_id_tags) {
         SCOPED_TRACE(testing::Message() << "+tag-" << tag);
-        AuthorizationSetBuilder builder = AuthorizationSetBuilder()
-                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
-                                                  .EcdsaSigningKey(EcCurve::P_256)
-                                                  .Digest(Digest::SHA_2_256)
-                                                  .Authorization(TAG_INCLUDE_UNIQUE_ID)
-                                                  .AttestationChallenge("challenge")
-                                                  .AttestationApplicationId("foo")
-                                                  .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION);
+        AuthorizationSetBuilder builder =
+                AuthorizationSetBuilder()
+                        .Authorization(TAG_NO_AUTH_REQUIRED)
+                        .EcdsaSigningKey(EcCurve::P_256)
+                        .Digest(Digest::SHA_2_256)
+                        .Authorization(TAG_INCLUDE_UNIQUE_ID)
+                        .Authorization(TAG_CREATION_DATETIME, 1619621648000)
+                        .AttestationChallenge("challenge")
+                        .AttestationApplicationId("foo")
+                        .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION);
         builder.push_back(tag);
         auto result = GenerateKey(builder, &key_blob, &key_characteristics);
 
@@ -310,14 +316,16 @@
 
     for (const KeyParameter& invalid_tag : attestation_id_tags) {
         SCOPED_TRACE(testing::Message() << "+tag-" << invalid_tag);
-        AuthorizationSetBuilder builder = AuthorizationSetBuilder()
-                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
-                                                  .EcdsaSigningKey(EcCurve::P_256)
-                                                  .Digest(Digest::SHA_2_256)
-                                                  .Authorization(TAG_INCLUDE_UNIQUE_ID)
-                                                  .AttestationChallenge("challenge")
-                                                  .AttestationApplicationId("foo")
-                                                  .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION);
+        AuthorizationSetBuilder builder =
+                AuthorizationSetBuilder()
+                        .Authorization(TAG_NO_AUTH_REQUIRED)
+                        .EcdsaSigningKey(EcCurve::P_256)
+                        .Digest(Digest::SHA_2_256)
+                        .Authorization(TAG_INCLUDE_UNIQUE_ID)
+                        .Authorization(TAG_CREATION_DATETIME, 1619621648000)
+                        .AttestationChallenge("challenge")
+                        .AttestationApplicationId("foo")
+                        .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION);
         // Add the tag that doesn't match the local device's real ID.
         builder.push_back(invalid_tag);
         auto result = GenerateKey(builder, &key_blob, &key_characteristics);
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 2032411..8e35c91 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -1298,7 +1298,8 @@
                                AuthorizationSet expected_sw_enforced,  //
                                AuthorizationSet expected_hw_enforced,  //
                                SecurityLevel security_level,
-                               const vector<uint8_t>& attestation_cert) {
+                               const vector<uint8_t>& attestation_cert,
+                               vector<uint8_t>* unique_id) {
     X509_Ptr cert(parse_cert_blob(attestation_cert));
     EXPECT_TRUE(!!cert.get());
     if (!cert.get()) return false;
@@ -1458,6 +1459,10 @@
     expected_hw_enforced.Sort();
     EXPECT_EQ(filtered_tags(expected_hw_enforced), filtered_tags(att_hw_enforced));
 
+    if (unique_id != nullptr) {
+        *unique_id = att_unique_id;
+    }
+
     return true;
 }
 
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index ec3fcf6..7b3b9d4 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -338,7 +338,8 @@
                                AuthorizationSet expected_sw_enforced,  //
                                AuthorizationSet expected_hw_enforced,  //
                                SecurityLevel security_level,
-                               const vector<uint8_t>& attestation_cert);
+                               const vector<uint8_t>& attestation_cert,
+                               vector<uint8_t>* unique_id = nullptr);
 
 string bin2hex(const vector<uint8_t>& data);
 X509_Ptr parse_cert_blob(const vector<uint8_t>& blob);
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 2a0ee7f..4d7f1b8 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -1550,6 +1550,102 @@
 }
 
 /*
+ * NewKeyGenerationTest.EcdsaAttestationUniqueId
+ *
+ * Verifies that creation of an attested ECDSA key with a UNIQUE_ID included.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaAttestationUniqueId) {
+    auto get_unique_id = [this](const std::string& app_id, uint64_t datetime,
+                                vector<uint8_t>* unique_id, bool reset = false) {
+        auto challenge = "hello";
+        auto subject = "cert subj 2";
+        vector<uint8_t> subject_der(make_name_from_str(subject));
+        uint64_t serial_int = 0x1010;
+        vector<uint8_t> serial_blob(build_serial_blob(serial_int));
+        AuthorizationSetBuilder builder =
+                AuthorizationSetBuilder()
+                        .Authorization(TAG_NO_AUTH_REQUIRED)
+                        .Authorization(TAG_INCLUDE_UNIQUE_ID)
+                        .EcdsaSigningKey(EcCurve::P_256)
+                        .Digest(Digest::NONE)
+                        .AttestationChallenge(challenge)
+                        .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                        .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                        .AttestationApplicationId(app_id)
+                        .Authorization(TAG_CREATION_DATETIME, datetime)
+                        .SetDefaultValidity();
+        if (reset) {
+            builder.Authorization(TAG_RESET_SINCE_ID_ROTATION);
+        }
+
+        ASSERT_EQ(ErrorCode::OK, GenerateKey(builder));
+        ASSERT_GT(key_blob_.size(), 0U);
+
+        EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
+        ASSERT_GT(cert_chain_.size(), 0);
+        verify_subject_and_serial(cert_chain_[0], serial_int, subject, /* self_signed = */ false);
+
+        AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics_);
+        AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics_);
+
+        // Check that the unique ID field in the extension is non-empty.
+        EXPECT_TRUE(verify_attestation_record(challenge, app_id, sw_enforced, hw_enforced,
+                                              SecLevel(), cert_chain_[0].encodedCertificate,
+                                              unique_id));
+        EXPECT_GT(unique_id->size(), 0);
+        CheckedDeleteKey();
+    };
+
+    // Generate unique ID
+    auto app_id = "foo";
+    uint64_t cert_date = 1619621648000;  // Wed Apr 28 14:54:08 2021 in ms since epoch
+    vector<uint8_t> unique_id;
+    get_unique_id(app_id, cert_date, &unique_id);
+
+    // Generating a new key with the same parameters should give the same unique ID.
+    vector<uint8_t> unique_id2;
+    get_unique_id(app_id, cert_date, &unique_id2);
+    EXPECT_EQ(unique_id, unique_id2);
+
+    // Generating a new key with a slightly different date should give the same unique ID.
+    uint64_t rounded_date = cert_date / 2592000000LLU;
+    uint64_t min_date = rounded_date * 2592000000LLU;
+    uint64_t max_date = ((rounded_date + 1) * 2592000000LLU) - 1;
+
+    vector<uint8_t> unique_id3;
+    get_unique_id(app_id, min_date, &unique_id3);
+    EXPECT_EQ(unique_id, unique_id3);
+
+    vector<uint8_t> unique_id4;
+    get_unique_id(app_id, max_date, &unique_id4);
+    EXPECT_EQ(unique_id, unique_id4);
+
+    // A different attestation application ID should yield a different unique ID.
+    auto app_id2 = "different_foo";
+    vector<uint8_t> unique_id5;
+    get_unique_id(app_id2, cert_date, &unique_id5);
+    EXPECT_NE(unique_id, unique_id5);
+
+    // A radically different date should yield a different unique ID.
+    vector<uint8_t> unique_id6;
+    get_unique_id(app_id, 1611621648000, &unique_id6);
+    EXPECT_NE(unique_id, unique_id6);
+
+    vector<uint8_t> unique_id7;
+    get_unique_id(app_id, max_date + 1, &unique_id7);
+    EXPECT_NE(unique_id, unique_id7);
+
+    vector<uint8_t> unique_id8;
+    get_unique_id(app_id, min_date - 1, &unique_id8);
+    EXPECT_NE(unique_id, unique_id8);
+
+    // Marking RESET_SINCE_ID_ROTATION should give a different unique ID.
+    vector<uint8_t> unique_id9;
+    get_unique_id(app_id, cert_date, &unique_id9, /* reset_id = */ true);
+    EXPECT_NE(unique_id, unique_id9);
+}
+
+/*
  * NewKeyGenerationTest.EcdsaAttestationTagNoApplicationId
  *
  * Verifies that creation of an attested ECDSA key does not include APPLICATION_ID.
diff --git a/wifi/1.0/vts/functional/Android.bp b/wifi/1.0/vts/functional/Android.bp
index e4948b4..6c0ebf7 100644
--- a/wifi/1.0/vts/functional/Android.bp
+++ b/wifi/1.0/vts/functional/Android.bp
@@ -107,8 +107,10 @@
     static_libs: [
         "VtsHalWifiV1_0TargetTestUtil",
         "android.hardware.wifi@1.0",
+        "android.hardware.wifi.hostapd@1.0",
         "libwifi-system-iface",
     ],
+    disable_framework: true,
     test_suites: [
         "general-tests",
         "vts",
diff --git a/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
index 96b4501..28b1616 100644
--- a/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
@@ -15,9 +15,9 @@
  */
 
 #include <android-base/logging.h>
-
 #include <android/hardware/wifi/1.0/IWifi.h>
 #include <android/hardware/wifi/1.0/IWifiApIface.h>
+#include <android/hardware/wifi/hostapd/1.0/IHostapd.h>
 #include <gtest/gtest.h>
 #include <hidl/GtestPrinter.h>
 #include <hidl/ServiceManagement.h>
@@ -26,6 +26,7 @@
 #include "wifi_hidl_test_utils.h"
 
 using ::android::sp;
+using ::android::hardware::wifi::hostapd::V1_0::IHostapd;
 using ::android::hardware::wifi::V1_0::IfaceType;
 using ::android::hardware::wifi::V1_0::IWifi;
 using ::android::hardware::wifi::V1_0::IWifiApIface;
@@ -38,6 +39,10 @@
 class WifiApIfaceHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
+        if (android::hardware::getAllHalInstanceNames(IHostapd::descriptor)
+                .empty()) {
+            GTEST_SKIP() << "Device does not support AP";
+        }
         // Make sure test starts with a clean state
         stopWifi(GetInstanceName());
 
diff --git a/wifi/1.0/vts/functional/wifi_chip_hidl_ap_test.cpp b/wifi/1.0/vts/functional/wifi_chip_hidl_ap_test.cpp
index 2e6ad32..66e1a80 100644
--- a/wifi/1.0/vts/functional/wifi_chip_hidl_ap_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_chip_hidl_ap_test.cpp
@@ -15,9 +15,9 @@
  */
 
 #include <android-base/logging.h>
-
 #include <android/hardware/wifi/1.0/IWifi.h>
 #include <android/hardware/wifi/1.0/IWifiChip.h>
+#include <android/hardware/wifi/hostapd/1.0/IHostapd.h>
 #include <gtest/gtest.h>
 #include <hidl/GtestPrinter.h>
 #include <hidl/ServiceManagement.h>
@@ -26,6 +26,7 @@
 #include "wifi_hidl_test_utils.h"
 
 using ::android::sp;
+using ::android::hardware::wifi::hostapd::V1_0::IHostapd;
 using ::android::hardware::wifi::V1_0::ChipModeId;
 using ::android::hardware::wifi::V1_0::IfaceType;
 using ::android::hardware::wifi::V1_0::IWifi;
@@ -41,6 +42,10 @@
 class WifiChipHidlApTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
+        if (android::hardware::getAllHalInstanceNames(IHostapd::descriptor)
+                .empty()) {
+            GTEST_SKIP() << "Device does not support AP";
+        }
         // Make sure test starts with a clean state
         stopWifi(GetInstanceName());
 
diff --git a/wifi/1.1/vts/functional/Android.bp b/wifi/1.1/vts/functional/Android.bp
index 8048642..a8f3470 100644
--- a/wifi/1.1/vts/functional/Android.bp
+++ b/wifi/1.1/vts/functional/Android.bp
@@ -39,6 +39,7 @@
         "android.hardware.wifi@1.5",
         "libwifi-system-iface",
     ],
+    disable_framework: true,
     test_suites: [
         "general-tests",
         "vts",
diff --git a/wifi/1.4/vts/functional/Android.bp b/wifi/1.4/vts/functional/Android.bp
index 14ebbe3..f86869b 100644
--- a/wifi/1.4/vts/functional/Android.bp
+++ b/wifi/1.4/vts/functional/Android.bp
@@ -14,7 +14,6 @@
 // limitations under the License.
 //
 
-// SoftAP-specific tests, similar to VtsHalWifiApV1_0TargetTest.
 package {
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
@@ -25,10 +24,9 @@
 }
 
 cc_test {
-    name: "VtsHalWifiApV1_4TargetTest",
+    name: "VtsHalWifiV1_4TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
-        "wifi_ap_iface_hidl_test.cpp",
         "wifi_chip_hidl_test.cpp",
     ],
     static_libs: [
@@ -46,6 +44,30 @@
     ],
 }
 
+// SoftAP-specific tests, similar to VtsHalWifiApV1_0TargetTest.
+cc_test {
+    name: "VtsHalWifiApV1_4TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "wifi_ap_iface_hidl_test.cpp",
+    ],
+    static_libs: [
+        "VtsHalWifiV1_0TargetTestUtil",
+        "android.hardware.wifi@1.0",
+        "android.hardware.wifi@1.1",
+        "android.hardware.wifi@1.2",
+        "android.hardware.wifi@1.3",
+        "android.hardware.wifi@1.4",
+        "android.hardware.wifi.hostapd@1.0",
+        "libwifi-system-iface",
+    ],
+    disable_framework: true,
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
+
 // These tests are split out so that they can be conditioned on presence of the
 // "android.hardware.wifi.aware" feature.
 cc_test {
diff --git a/wifi/1.4/vts/functional/wifi_ap_iface_hidl_test.cpp b/wifi/1.4/vts/functional/wifi_ap_iface_hidl_test.cpp
index 5b0f173..756afa5 100644
--- a/wifi/1.4/vts/functional/wifi_ap_iface_hidl_test.cpp
+++ b/wifi/1.4/vts/functional/wifi_ap_iface_hidl_test.cpp
@@ -16,6 +16,7 @@
 
 #include <android/hardware/wifi/1.4/IWifi.h>
 #include <android/hardware/wifi/1.4/IWifiApIface.h>
+#include <android/hardware/wifi/hostapd/1.0/IHostapd.h>
 #include <gtest/gtest.h>
 #include <hidl/GtestPrinter.h>
 #include <hidl/ServiceManagement.h>
@@ -25,6 +26,7 @@
 
 using ::android::sp;
 using ::android::hardware::hidl_array;
+using ::android::hardware::wifi::hostapd::V1_0::IHostapd;
 using ::android::hardware::wifi::V1_0::WifiStatus;
 using ::android::hardware::wifi::V1_0::WifiStatusCode;
 using ::android::hardware::wifi::V1_4::IWifi;
@@ -36,6 +38,10 @@
 class WifiApIfaceHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
+        if (android::hardware::getAllHalInstanceNames(IHostapd::descriptor)
+                .empty()) {
+            GTEST_SKIP() << "Device does not support AP";
+        }
         // Make sure to start with a clean state
         stopWifi(GetInstanceName());
 
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
index 8cb7e22..114fe4f 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
@@ -317,7 +317,7 @@
 }
 
 bool waitForFrameworkReady() {
-    int waitCount = 10;
+    int waitCount = 15;
     do {
         // Check whether package service is ready or not.
         if (!testing::checkSubstringInCommandOutput(
diff --git a/wifi/supplicant/1.4/vts/functional/Android.bp b/wifi/supplicant/1.4/vts/functional/Android.bp
index 8cbe04f..57ee830 100644
--- a/wifi/supplicant/1.4/vts/functional/Android.bp
+++ b/wifi/supplicant/1.4/vts/functional/Android.bp
@@ -77,7 +77,6 @@
         "general-tests",
         "vts",
     ],
-    disable_framework: true,
 }
 
 cc_test {
@@ -108,5 +107,4 @@
         "general-tests",
         "vts",
     ],
-    disable_framework: true,
 }