Merge "Update HAL 1.6 for 5G Slicing" into sc-dev
diff --git a/audio/7.0/config/api/current.txt b/audio/7.0/config/api/current.txt
index f585d8e..78f2f29 100644
--- a/audio/7.0/config/api/current.txt
+++ b/audio/7.0/config/api/current.txt
@@ -251,7 +251,6 @@
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_HW_AV_SYNC;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_HW_HOTWORD;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_MMAP_NOIRQ;
-    enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_NONE;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_RAW;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_SYNC;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_VOIP_TX;
@@ -265,7 +264,6 @@
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
-    enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_NONE;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_NON_BLOCKING;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_PRIMARY;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_RAW;
diff --git a/audio/7.0/config/audio_policy_configuration.xsd b/audio/7.0/config/audio_policy_configuration.xsd
index 87e5774..50c1793 100644
--- a/audio/7.0/config/audio_policy_configuration.xsd
+++ b/audio/7.0/config/audio_policy_configuration.xsd
@@ -159,13 +159,9 @@
         <xs:annotation>
             <xs:documentation xml:lang="en">
               The flags indicate suggested stream attributes supported by the profile.
-              Use of AUDIO_{INPUT|OUTPUT}_FLAG_NONE in the XML file isn't required
-              as empty flag lists are allowed. However these constants are useful for
-              representing an empty enum value.
             </xs:documentation>
         </xs:annotation>
         <xs:restriction base="xs:string">
-            <xs:enumeration value="AUDIO_OUTPUT_FLAG_NONE" />
             <xs:enumeration value="AUDIO_OUTPUT_FLAG_DIRECT" />
             <xs:enumeration value="AUDIO_OUTPUT_FLAG_PRIMARY" />
             <xs:enumeration value="AUDIO_OUTPUT_FLAG_FAST" />
@@ -182,7 +178,6 @@
             <xs:enumeration value="AUDIO_OUTPUT_FLAG_VOIP_RX" />
             <xs:enumeration value="AUDIO_OUTPUT_FLAG_INCALL_MUSIC" />
             <xs:enumeration value="AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD" />
-            <xs:enumeration value="AUDIO_INPUT_FLAG_NONE" />
             <xs:enumeration value="AUDIO_INPUT_FLAG_FAST" />
             <xs:enumeration value="AUDIO_INPUT_FLAG_HW_HOTWORD" />
             <xs:enumeration value="AUDIO_INPUT_FLAG_RAW" />
diff --git a/audio/README.md b/audio/README.md
index b77b9ba..1938ad4 100644
--- a/audio/README.md
+++ b/audio/README.md
@@ -7,47 +7,49 @@
 
 ## Directory Structure
 
-* `2.0` -- version 2.0 of the core HIDL API. Note that `.hal` files
+* `2.0` — version 2.0 of the core HIDL API. Note that `.hal` files
   can not be moved into the `core` directory because that would change
   its namespace and include path.
-   - `config` -- the XSD schema for the Audio Policy Manager
+   - `config` — the XSD schema for the Audio Policy Manager
      configuration file.
-* `4.0` -- version 4.0 of the core HIDL API.
+* `4.0` — version 4.0 of the core HIDL API.
 * ...
-* `common` -- common types for audio core and effect HIDL API.
-   - `2.0` -- version 2.0 of the common types HIDL API.
-   - `4.0` -- version 4.0.
+* `common` — common types for audio core and effect HIDL API.
+   - `2.0` — version 2.0 of the common types HIDL API.
+   - `4.0` — version 4.0.
    - ...
-   - `7.0` -- version 7.0.
-      - `example` -- example implementation of the core and effect
+   - `7.0` — version 7.0.
+      - `example` — example implementation of the core and effect
         V7.0 API. It represents a "fake" audio HAL that doesn't
         actually communicate with hardware.
-   - `all-versions` -- code common to all version of both core and effect API.
-      - `default` -- shared code of the default implementation.
-         - `service` -- vendor HAL service for hosting the default
+   - `all-versions` — code common to all version of both core and effect API.
+      - `default` — shared code of the default implementation.
+         - `service` — vendor HAL service for hosting the default
            implementation.
-      - `test` -- utilities used by tests.
-      - `util` -- utilities used by both implementation and tests.
-* `core` -- VTS tests and the default implementation of the core API
+      - `test` — utilities used by tests.
+      - `util` — utilities used by both implementation and tests.
+* `core` — VTS tests and the default implementation of the core API
   (not HIDL API, it's in `audio/N.M`).
-   - `7.0` -- code specific to version V7.0 of the core HIDL API
-   - `all-versions` -- the code is common between all versions,
+   - `7.0` — code specific to version V7.0 of the core HIDL API
+   - `all-versions` — the code is common between all versions,
      version-specific parts are enclosed into conditional directives
      of preprocessor or reside in dedicated files.
-       - `default` -- code that wraps the legacy API (from
+       - `default` — code that wraps the legacy API (from
          `hardware/libhardware`).
+         - `util` — utilities for the default implementation.
        - `vts` VTS tests for the core HIDL API.
-* `effect` -- same for the effect HIDL API.
+* `effect` — same for the effect HIDL API.
    - `2.0`
-      - `config` -- the XSD schema for the Audio Effects configuration
-        file.
+      - `config` — the XSD schema for the Audio Effects configuration file.
    - `4.0`
    - ...
    - `all-versions`
-      - `default`
-      - `vts`
-* `policy` -- Configurable Audio Policy schemes.
-   - `1.0` -- note that versions of CAP are not linked to the versions
+       - `default` — code that wraps the legacy API (from
+         `hardware/libhardware`).
+         - `util` — utilities for the default implementation.
+       - `vts` VTS tests for the effect HIDL API.
+* `policy` — Configurable Audio Policy schemes.
+   - `1.0` — note that versions of CAP are not linked to the versions
      of audio HAL.
-      - `vts` -- VTS tests for validating actual configuration files.
-      - `xml` -- XSD schemas for CAP configuration files.
+      - `vts` — VTS tests for validating actual configuration files.
+      - `xml` — XSD schemas for CAP configuration files.
diff --git a/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h b/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h
index c0042db..b427f3a 100644
--- a/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h
+++ b/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h
@@ -212,10 +212,16 @@
     return isOutputDevice(stringToAudioDevice(device));
 }
 
+static inline bool maybeVendorExtension(const std::string& s) {
+    // Only checks whether the string starts with the "vendor prefix".
+    static const std::string vendorPrefix = "VX_";
+    return s.size() > vendorPrefix.size() && s.substr(0, vendorPrefix.size()) == vendorPrefix;
+}
+
 static inline bool isVendorExtension(const std::string& s) {
     // Must match the "vendorExtension" rule from the XSD file.
     static const std::string vendorPrefix = "VX_";
-    return s.size() > vendorPrefix.size() && s.substr(0, vendorPrefix.size()) == vendorPrefix &&
+    return maybeVendorExtension(s) &&
            std::all_of(s.begin() + vendorPrefix.size(), s.end(),
                        [](unsigned char c) { return c == '_' || std::isalnum(c); });
 }
diff --git a/audio/common/7.0/types.hal b/audio/common/7.0/types.hal
index 3903a0b..99c2e5a 100644
--- a/audio/common/7.0/types.hal
+++ b/audio/common/7.0/types.hal
@@ -309,15 +309,15 @@
 struct PlaybackTrackMetadata {
     AudioUsage usage;
     AudioContentType contentType;
-    /** Tags from AudioTrack audio atttributes */
-    vec<AudioTag> tags;
-    AudioChannelMask channelMask;
     /**
      * Positive linear gain applied to the track samples. 0 being muted and 1 is no attenuation,
      * 2 means double amplification...
      * Must not be negative.
      */
     float gain;
+    AudioChannelMask channelMask;
+    /** Tags from AudioTrack audio atttributes */
+    vec<AudioTag> tags;
 };
 
 /** Metadatas of the source of a StreamOut. */
@@ -328,9 +328,6 @@
 /** Metadata of a record track for a StreamIn. */
 struct RecordTrackMetadata {
     AudioSource source;
-    /** Tags from AudioTrack audio atttributes */
-    vec<AudioTag> tags;
-    AudioChannelMask channelMask;
     /**
      * Positive linear gain applied to the track samples. 0 being muted and 1 is no attenuation,
      * 2 means double amplification...
@@ -344,6 +341,9 @@
         Monostate unspecified;
         DeviceAddress device;
     } destination;
+    AudioChannelMask channelMask;
+    /** Tags from AudioTrack audio atttributes */
+    vec<AudioTag> tags;
 };
 
 /** Metadatas of the sink of a StreamIn. */
diff --git a/audio/common/all-versions/default/7.0/HidlUtils.cpp b/audio/common/all-versions/default/7.0/HidlUtils.cpp
index f09db5e..bb3a596 100644
--- a/audio/common/all-versions/default/7.0/HidlUtils.cpp
+++ b/audio/common/all-versions/default/7.0/HidlUtils.cpp
@@ -16,6 +16,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <algorithm>
 
 #define LOG_TAG "HidlUtils"
 #include <log/log.h>
@@ -281,7 +282,7 @@
                                              hidl_vec<AudioGainMode>* gainModeMask) {
     status_t status = NO_ERROR;
     std::vector<AudioGainMode> result;
-    for (uint32_t bit = 0; bit < sizeof(audio_gain_mode_t) * 8; ++bit) {
+    for (uint32_t bit = 0; halGainModeMask != 0 && bit < sizeof(audio_gain_mode_t) * 8; ++bit) {
         audio_gain_mode_t flag = static_cast<audio_gain_mode_t>(1u << bit);
         if ((flag & halGainModeMask) == flag) {
             AudioGainMode flagStr = audio_gain_mode_to_string(flag);
@@ -291,6 +292,7 @@
                 ALOGE("Unknown audio gain mode value 0x%X", flag);
                 status = BAD_VALUE;
             }
+            halGainModeMask = static_cast<audio_gain_mode_t>(halGainModeMask & ~flag);
         }
     }
     *gainModeMask = result;
@@ -858,15 +860,17 @@
     return result;
 }
 
-status_t HidlUtils::audioTagsFromHal(const char* halTags, hidl_vec<AudioTag>* tags) {
-    std::vector<std::string> strTags = utils::splitString(halTags, sAudioTagSeparator);
+status_t HidlUtils::audioTagsFromHal(const std::vector<std::string>& strTags,
+                                     hidl_vec<AudioTag>* tags) {
     status_t result = NO_ERROR;
     tags->resize(strTags.size());
     size_t to = 0;
     for (size_t from = 0; from < strTags.size(); ++from) {
-        if (xsd::isVendorExtension(strTags[from])) {
-            (*tags)[to++] = strTags[from];
+        const auto& tag = strTags[from];
+        if (xsd::isVendorExtension(tag)) {
+            (*tags)[to++] = tag;
         } else {
+            ALOGE("Vendor extension tag is ill-formed: \"%s\"", tag.c_str());
             result = BAD_VALUE;
         }
     }
@@ -889,6 +893,7 @@
             halTagsBuffer << tag;
             hasValue = true;
         } else {
+            ALOGE("Vendor extension tag is ill-formed: \"%s\"", tag.c_str());
             result = BAD_VALUE;
         }
     }
@@ -899,6 +904,31 @@
     return result;
 }
 
+hidl_vec<AudioTag> HidlUtils::filterOutNonVendorTags(const hidl_vec<AudioTag>& tags) {
+    hidl_vec<AudioTag> result;
+    result.resize(tags.size());
+    size_t resultIdx = 0;
+    for (const auto& tag : tags) {
+        if (xsd::maybeVendorExtension(tag)) {
+            result[resultIdx++] = tag;
+        }
+    }
+    if (resultIdx != result.size()) {
+        result.resize(resultIdx);
+    }
+    return result;
+}
+
+std::vector<std::string> HidlUtils::filterOutNonVendorTags(const std::vector<std::string>& tags) {
+    std::vector<std::string> result;
+    std::copy_if(tags.begin(), tags.end(), std::back_inserter(result), xsd::maybeVendorExtension);
+    return result;
+}
+
+std::vector<std::string> HidlUtils::splitAudioTags(const char* halTags) {
+    return utils::splitString(halTags, sAudioTagSeparator);
+}
+
 status_t HidlUtils::deviceAddressFromHal(audio_devices_t halDeviceType,
                                          const char* halDeviceAddress, DeviceAddress* device) {
     status_t result = NO_ERROR;
diff --git a/audio/common/all-versions/default/HidlUtils.h b/audio/common/all-versions/default/HidlUtils.h
index cc4fbf2..22b7152 100644
--- a/audio/common/all-versions/default/HidlUtils.h
+++ b/audio/common/all-versions/default/HidlUtils.h
@@ -20,6 +20,8 @@
 #include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
 
 #include <memory>
+#include <string>
+#include <vector>
 
 #include <system/audio.h>
 
@@ -118,8 +120,12 @@
                                            AudioStreamType* streamType);
     static status_t audioStreamTypeToHal(const AudioStreamType& streamType,
                                          audio_stream_type_t* halStreamType);
-    static status_t audioTagsFromHal(const char* halTags, hidl_vec<AudioTag>* tags);
+    static status_t audioTagsFromHal(const std::vector<std::string>& strTags,
+                                     hidl_vec<AudioTag>* tags);
     static status_t audioTagsToHal(const hidl_vec<AudioTag>& tags, char* halTags);
+    static hidl_vec<AudioTag> filterOutNonVendorTags(const hidl_vec<AudioTag>& tags);
+    static std::vector<std::string> filterOutNonVendorTags(const std::vector<std::string>& tags);
+    static std::vector<std::string> splitAudioTags(const char* halTags);
 
   private:
     static status_t audioIndexChannelMaskFromHal(audio_channel_mask_t halChannelMask,
diff --git a/audio/common/all-versions/default/UuidUtils.cpp b/audio/common/all-versions/default/UuidUtils.cpp
index 85edc7b..6c4c94d 100644
--- a/audio/common/all-versions/default/UuidUtils.cpp
+++ b/audio/common/all-versions/default/UuidUtils.cpp
@@ -42,6 +42,14 @@
     memcpy(halUuid->node, uuid.node.data(), uuid.node.size());
 }
 
+std::string UuidUtils::uuidToString(const audio_uuid_t& halUuid) {
+    char str[64];
+    snprintf(str, sizeof(str), "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", halUuid.timeLow,
+             halUuid.timeMid, halUuid.timeHiAndVersion, halUuid.clockSeq, halUuid.node[0],
+             halUuid.node[1], halUuid.node[2], halUuid.node[3], halUuid.node[4], halUuid.node[5]);
+    return str;
+}
+
 }  // namespace implementation
 }  // namespace CPP_VERSION
 }  // namespace common
diff --git a/audio/common/all-versions/default/UuidUtils.h b/audio/common/all-versions/default/UuidUtils.h
index 38db48a..cd04fb0 100644
--- a/audio/common/all-versions/default/UuidUtils.h
+++ b/audio/common/all-versions/default/UuidUtils.h
@@ -17,14 +17,14 @@
 #ifndef android_hardware_audio_Uuid_Utils_H_
 #define android_hardware_audio_Uuid_Utils_H_
 
+#include <string>
+
 // clang-format off
 #include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
 // clang-format on
 
 #include <system/audio.h>
 
-using ::android::hardware::hidl_vec;
-
 namespace android {
 namespace hardware {
 namespace audio {
@@ -38,6 +38,7 @@
   public:
     static void uuidFromHal(const audio_uuid_t& halUuid, Uuid* uuid);
     static void uuidToHal(const Uuid& uuid, audio_uuid_t* halUuid);
+    static std::string uuidToString(const audio_uuid_t& halUuid);
 };
 
 }  // namespace implementation
diff --git a/audio/common/all-versions/default/tests/hidlutils_tests.cpp b/audio/common/all-versions/default/tests/hidlutils_tests.cpp
index 642ece3..40fc5c8 100644
--- a/audio/common/all-versions/default/tests/hidlutils_tests.cpp
+++ b/audio/common/all-versions/default/tests/hidlutils_tests.cpp
@@ -762,9 +762,7 @@
 
 TEST(HidlUtils, ConvertOffloadInfo) {
     AudioOffloadInfo offloadInfo = {};
-    offloadInfo.base.sampleRateHz = 44100;
-    offloadInfo.base.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
-    offloadInfo.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
+    offloadInfo.base = generateValidConfigBase(false /*isInput*/);
     offloadInfo.streamType = toString(xsd::AudioStreamType::AUDIO_STREAM_MUSIC);
     offloadInfo.bitRatePerSecond = 320;
     offloadInfo.durationMicroseconds = -1;
@@ -783,33 +781,76 @@
 
 TEST(HidlUtils, ConvertInvalidConfig) {
     AudioConfig invalid;
-    audio_config_t halInvalid = AUDIO_CONFIG_INITIALIZER;
-    halInvalid.channel_mask = kInvalidHalChannelMask;
-    halInvalid.format = kInvalidHalFormat;
-    EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigFromHal(halInvalid, false /*isInput*/, &invalid));
-    EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigFromHal(halInvalid, true /*isInput*/, &invalid));
-    invalid.base.channelMask = "random string";
-    invalid.base.format = "random string";
-    EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigToHal(invalid, &halInvalid));
+    audio_config_t halInvalidChannelMask = AUDIO_CONFIG_INITIALIZER;
+    halInvalidChannelMask.channel_mask = kInvalidHalChannelMask;
+    EXPECT_EQ(BAD_VALUE,
+              HidlUtils::audioConfigFromHal(halInvalidChannelMask, false /*isInput*/, &invalid));
+    EXPECT_EQ(BAD_VALUE,
+              HidlUtils::audioConfigFromHal(halInvalidChannelMask, true /*isInput*/, &invalid));
+    audio_config_t halInvalidFormat = AUDIO_CONFIG_INITIALIZER;
+    halInvalidFormat.format = kInvalidHalFormat;
+    EXPECT_EQ(BAD_VALUE,
+              HidlUtils::audioConfigFromHal(halInvalidFormat, false /*isInput*/, &invalid));
+    EXPECT_EQ(BAD_VALUE,
+              HidlUtils::audioConfigFromHal(halInvalidFormat, true /*isInput*/, &invalid));
+
+    AudioConfig invalidChannelMask;
+    audio_config_t halInvalid;
+    invalidChannelMask.base.channelMask = "random string";
+    invalidChannelMask.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_DEFAULT);
+    EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigToHal(invalidChannelMask, &halInvalid));
+    AudioConfig invalidFormat;
+    invalidFormat.base.format = "random string";
+    invalidFormat.base.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
+    EXPECT_EQ(BAD_VALUE, HidlUtils::audioConfigToHal(invalidFormat, &halInvalid));
+}
+
+TEST(HidlUtils, ConvertConfigDefault) {
+    audio_config_t halDefault = AUDIO_CONFIG_INITIALIZER;
+    AudioConfig defaultOut, defaultIn;
+    EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigFromHal(halDefault, false /*isInput*/, &defaultOut));
+    EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigFromHal(halDefault, true /*isInput*/, &defaultIn));
+    EXPECT_EQ(defaultOut, defaultIn);
+    EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigToHal(defaultOut, &halDefault));
+
+    // Note: empty channel mask and config are not valid values.
+    AudioConfig defaultCfg{};
+    defaultCfg.base.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
+    defaultCfg.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_DEFAULT);
+    audio_config_t halDefaultCfg;
+    EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigToHal(defaultCfg, &halDefaultCfg));
+    AudioConfig defaultCfgBackOut, defaultCfgBackIn;
+    EXPECT_EQ(NO_ERROR,
+              HidlUtils::audioConfigFromHal(halDefaultCfg, false /*isInput*/, &defaultCfgBackOut));
+    EXPECT_EQ(NO_ERROR,
+              HidlUtils::audioConfigFromHal(halDefaultCfg, true /*isInput*/, &defaultCfgBackIn));
+    EXPECT_EQ(defaultCfgBackOut, defaultCfgBackIn);
+    EXPECT_EQ(defaultCfg, defaultCfgBackOut);
 }
 
 TEST(HidlUtils, ConvertConfig) {
-    AudioConfig config = {};
-    config.base.sampleRateHz = 44100;
-    config.base.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
-    config.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
-    audio_config_t halConfig;
-    EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigToHal(config, &halConfig));
-    AudioConfig configBack;
-    EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigFromHal(halConfig, false /*isInput*/, &configBack));
-    EXPECT_EQ(config, configBack);
+    AudioConfig configOut{};
+    configOut.base = generateValidConfigBase(false /*isInput*/);
+    audio_config_t halConfigOut;
+    EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigToHal(configOut, &halConfigOut));
+    AudioConfig configOutBack;
+    EXPECT_EQ(NO_ERROR,
+              HidlUtils::audioConfigFromHal(halConfigOut, false /*isInput*/, &configOutBack));
+    EXPECT_EQ(configOut, configOutBack);
+
+    AudioConfig configIn{};
+    configIn.base = generateValidConfigBase(true /*isInput*/);
+    audio_config_t halConfigIn;
+    EXPECT_EQ(NO_ERROR, HidlUtils::audioConfigToHal(configIn, &halConfigIn));
+    AudioConfig configInBack;
+    EXPECT_EQ(NO_ERROR,
+              HidlUtils::audioConfigFromHal(halConfigIn, true /*isInput*/, &configInBack));
+    EXPECT_EQ(configIn, configInBack);
 }
 
 TEST(HidlUtils, ConvertConfigWithOffloadInfo) {
     AudioConfig config = {};
-    config.base.sampleRateHz = 44100;
-    config.base.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
-    config.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
+    config.base = generateValidConfigBase(false /*isInput*/);
     config.offloadInfo.info(
             AudioOffloadInfo{.base = config.base,
                              .streamType = toString(xsd::AudioStreamType::AUDIO_STREAM_MUSIC),
@@ -952,20 +993,51 @@
     char halEmptyTags[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE] = {};
     EXPECT_EQ(NO_ERROR, HidlUtils::audioTagsToHal(emptyTags, halEmptyTags));
     hidl_vec<AudioTag> emptyTagsBack;
-    EXPECT_EQ(NO_ERROR, HidlUtils::audioTagsFromHal(halEmptyTags, &emptyTagsBack));
+    EXPECT_EQ(NO_ERROR,
+              HidlUtils::audioTagsFromHal(HidlUtils::splitAudioTags(halEmptyTags), &emptyTagsBack));
     EXPECT_EQ(emptyTags, emptyTagsBack);
 
     hidl_vec<AudioTag> oneTag = {{"VX_GOOGLE_VR"}};
     char halOneTag[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE] = {};
     EXPECT_EQ(NO_ERROR, HidlUtils::audioTagsToHal(oneTag, halOneTag));
     hidl_vec<AudioTag> oneTagBack;
-    EXPECT_EQ(NO_ERROR, HidlUtils::audioTagsFromHal(halOneTag, &oneTagBack));
+    EXPECT_EQ(NO_ERROR,
+              HidlUtils::audioTagsFromHal(HidlUtils::splitAudioTags(halOneTag), &oneTagBack));
     EXPECT_EQ(oneTag, oneTagBack);
 
     hidl_vec<AudioTag> twoTags = {{"VX_GOOGLE_VR_42", "VX_GOOGLE_1E100"}};
     char halTwoTags[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE] = {};
     EXPECT_EQ(NO_ERROR, HidlUtils::audioTagsToHal(twoTags, halTwoTags));
     hidl_vec<AudioTag> twoTagsBack;
-    EXPECT_EQ(NO_ERROR, HidlUtils::audioTagsFromHal(halTwoTags, &twoTagsBack));
+    EXPECT_EQ(NO_ERROR,
+              HidlUtils::audioTagsFromHal(HidlUtils::splitAudioTags(halTwoTags), &twoTagsBack));
     EXPECT_EQ(twoTags, twoTagsBack);
 }
+
+template <typename T>
+class FilterTest : public ::testing::Test {};
+using FilterTestTypeParams = ::testing::Types<hidl_vec<AudioTag>, std::vector<std::string>>;
+TYPED_TEST_SUITE(FilterTest, FilterTestTypeParams);
+
+TYPED_TEST(FilterTest, FilterOutNonVendorTags) {
+    TypeParam emptyTags;
+    EXPECT_EQ(emptyTags, HidlUtils::filterOutNonVendorTags(emptyTags));
+
+    TypeParam allVendorTags = {{"VX_GOOGLE_VR_42", "VX_GOOGLE_1E100"}};
+    EXPECT_EQ(allVendorTags, HidlUtils::filterOutNonVendorTags(allVendorTags));
+
+    TypeParam oneVendorTag = {{"", "VX_GOOGLE_VR", "random_string"}};
+    TypeParam oneVendorTagOnly = HidlUtils::filterOutNonVendorTags(oneVendorTag);
+    EXPECT_EQ(1, oneVendorTagOnly.size());
+    EXPECT_EQ(oneVendorTag[1], oneVendorTagOnly[0]);
+
+    // The vendor extension isn't valid, however it must not be filtered out
+    // so the converter can detect the issue.
+    TypeParam oneMaybeVendorTag = {{"", "random string", "VX_GOOGLE_$$"}};
+    TypeParam oneMaybeVendorTagOnly = HidlUtils::filterOutNonVendorTags(oneMaybeVendorTag);
+    EXPECT_EQ(1, oneMaybeVendorTagOnly.size());
+    EXPECT_EQ(oneMaybeVendorTag[2], oneMaybeVendorTagOnly[0]);
+
+    TypeParam noVendorTags = {{"", "random string", "V_"}};
+    EXPECT_EQ(emptyTags, HidlUtils::filterOutNonVendorTags(noVendorTags));
+}
diff --git a/audio/core/all-versions/default/Android.bp b/audio/core/all-versions/default/Android.bp
index c75c779..e0f0894 100644
--- a/audio/core/all-versions/default/Android.bp
+++ b/audio/core/all-versions/default/Android.bp
@@ -1,7 +1,6 @@
 filegroup {
     name: "android.hardware.audio-impl_srcs",
     srcs: [
-        "Conversions.cpp",
         "Device.cpp",
         "DevicesFactory.cpp",
         "ParametersUtil.cpp",
@@ -64,6 +63,7 @@
     defaults: ["android.hardware.audio-impl_default"],
     shared_libs: [
         "android.hardware.audio@2.0",
+        "android.hardware.audio@2.0-util",
         "android.hardware.audio.common@2.0",
         "android.hardware.audio.common@2.0-util",
     ],
@@ -80,6 +80,7 @@
 
     shared_libs: [
         "android.hardware.audio@4.0",
+        "android.hardware.audio@4.0-util",
         "android.hardware.audio.common@4.0",
         "android.hardware.audio.common@4.0-util",
     ],
@@ -95,6 +96,7 @@
     defaults: ["android.hardware.audio-impl_default"],
     shared_libs: [
         "android.hardware.audio@5.0",
+        "android.hardware.audio@5.0-util",
         "android.hardware.audio.common@5.0",
         "android.hardware.audio.common@5.0-util",
     ],
@@ -110,6 +112,7 @@
     defaults: ["android.hardware.audio-impl_default"],
     shared_libs: [
         "android.hardware.audio@6.0",
+        "android.hardware.audio@6.0-util",
         "android.hardware.audio.common@6.0",
         "android.hardware.audio.common@6.0-util",
     ],
@@ -130,6 +133,7 @@
     defaults: ["android.hardware.audio-impl_default"],
     shared_libs: [
         "android.hardware.audio@7.0",
+        "android.hardware.audio@7.0-util",
         "android.hardware.audio.common@7.0",
         "android.hardware.audio.common@7.0-enums",
         "android.hardware.audio.common@7.0-util",
diff --git a/audio/core/all-versions/default/Conversions.cpp b/audio/core/all-versions/default/Conversions.cpp
deleted file mode 100644
index f1752cc..0000000
--- a/audio/core/all-versions/default/Conversions.cpp
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (C) 2018 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 "core/default/Conversions.h"
-
-#include <stdio.h>
-
-#if MAJOR_VERSION >= 7
-#include <android_audio_policy_configuration_V7_0-enums.h>
-#endif
-#include <HidlUtils.h>
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace audio {
-namespace CPP_VERSION {
-namespace implementation {
-
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
-
-#define CONVERT_CHECKED(expr, result)                   \
-    if (status_t status = (expr); status != NO_ERROR) { \
-        result = status;                                \
-    }
-
-status_t deviceAddressToHal(const DeviceAddress& device, audio_devices_t* halDeviceType,
-                            char* halDeviceAddress) {
-#if MAJOR_VERSION >= 5
-    return HidlUtils::deviceAddressToHal(device, halDeviceType, halDeviceAddress);
-#else
-    return HidlUtils::deviceAddressToHalImpl(device, halDeviceType, halDeviceAddress);
-#endif
-}
-
-status_t deviceAddressFromHal(audio_devices_t halDeviceType, const char* halDeviceAddress,
-                              DeviceAddress* device) {
-#if MAJOR_VERSION >= 5
-    return HidlUtils::deviceAddressFromHal(halDeviceType, halDeviceAddress, device);
-#else
-    return HidlUtils::deviceAddressFromHalImpl(halDeviceType, halDeviceAddress, device);
-#endif
-}
-
-#if MAJOR_VERSION >= 4
-bool halToMicrophoneCharacteristics(MicrophoneInfo* pDst,
-                                    const struct audio_microphone_characteristic_t& src) {
-    bool status = false;
-    if (pDst != NULL) {
-        pDst->deviceId = src.device_id;
-
-        if (deviceAddressFromHal(src.device, src.address, &pDst->deviceAddress) != OK) {
-            return false;
-        }
-        pDst->channelMapping.resize(AUDIO_CHANNEL_COUNT_MAX);
-        for (size_t ch = 0; ch < pDst->channelMapping.size(); ch++) {
-            pDst->channelMapping[ch] = AudioMicrophoneChannelMapping(src.channel_mapping[ch]);
-        }
-        pDst->location = AudioMicrophoneLocation(src.location);
-        pDst->group = (AudioMicrophoneGroup)src.group;
-        pDst->indexInTheGroup = (uint32_t)src.index_in_the_group;
-        pDst->sensitivity = src.sensitivity;
-        pDst->maxSpl = src.max_spl;
-        pDst->minSpl = src.min_spl;
-        pDst->directionality = AudioMicrophoneDirectionality(src.directionality);
-        pDst->frequencyResponse.resize(src.num_frequency_responses);
-        for (size_t k = 0; k < src.num_frequency_responses; k++) {
-            pDst->frequencyResponse[k].frequency = src.frequency_responses[0][k];
-            pDst->frequencyResponse[k].level = src.frequency_responses[1][k];
-        }
-        pDst->position.x = src.geometric_location.x;
-        pDst->position.y = src.geometric_location.y;
-        pDst->position.z = src.geometric_location.z;
-
-        pDst->orientation.x = src.orientation.x;
-        pDst->orientation.y = src.orientation.y;
-        pDst->orientation.z = src.orientation.z;
-
-        status = true;
-    }
-    return status;
-}
-
-status_t sinkMetadataToHal(const SinkMetadata& sinkMetadata,
-                           std::vector<record_track_metadata>* halTracks) {
-    status_t result = NO_ERROR;
-    if (halTracks != nullptr) {
-        halTracks->reserve(sinkMetadata.tracks.size());
-    }
-    for (auto& metadata : sinkMetadata.tracks) {
-        record_track_metadata halTrackMetadata{.gain = metadata.gain};
-        CONVERT_CHECKED(HidlUtils::audioSourceToHal(metadata.source, &halTrackMetadata.source),
-                        result);
-#if MAJOR_VERSION >= 5
-        if (metadata.destination.getDiscriminator() ==
-            RecordTrackMetadata::Destination::hidl_discriminator::device) {
-            CONVERT_CHECKED(
-                    deviceAddressToHal(metadata.destination.device(), &halTrackMetadata.dest_device,
-                                       halTrackMetadata.dest_device_address),
-                    result);
-        }
-#endif
-        if (halTracks != nullptr) {
-            halTracks->push_back(std::move(halTrackMetadata));
-        }
-    }
-    return result;
-}
-
-status_t sourceMetadataToHal(const SourceMetadata& sourceMetadata,
-                             std::vector<playback_track_metadata_t>* halTracks) {
-    status_t result = NO_ERROR;
-    if (halTracks != nullptr) {
-        halTracks->reserve(sourceMetadata.tracks.size());
-    }
-    for (auto& metadata : sourceMetadata.tracks) {
-        playback_track_metadata_t halTrackMetadata{.gain = metadata.gain};
-        CONVERT_CHECKED(HidlUtils::audioUsageToHal(metadata.usage, &halTrackMetadata.usage),
-                        result);
-        CONVERT_CHECKED(HidlUtils::audioContentTypeToHal(metadata.contentType,
-                                                         &halTrackMetadata.content_type),
-                        result);
-        if (halTracks != nullptr) {
-            halTracks->push_back(std::move(halTrackMetadata));
-        }
-    }
-    return result;
-}
-#endif  // MAJOR_VERSION >= 4
-
-#if MAJOR_VERSION >= 7
-namespace xsd {
-using namespace ::android::audio::policy::configuration::V7_0;
-}
-
-bool audioInputFlagsToHal(const hidl_vec<AudioInOutFlag>& flags, audio_input_flags_t* halFlags) {
-    bool success = true;
-    *halFlags = {};
-    for (const auto& flag : flags) {
-        audio_input_flags_t halFlag;
-        if (!xsd::isUnknownAudioInOutFlag(flag) &&
-            audio_input_flag_from_string(flag.c_str(), &halFlag)) {
-            *halFlags = static_cast<audio_input_flags_t>(*halFlags | halFlag);
-        } else {
-            ALOGE("Unknown audio input flag \"%s\"", flag.c_str());
-            success = false;
-        }
-    }
-    return success;
-}
-
-bool audioOutputFlagsToHal(const hidl_vec<AudioInOutFlag>& flags, audio_output_flags_t* halFlags) {
-    bool success = true;
-    *halFlags = {};
-    for (const auto& flag : flags) {
-        audio_output_flags_t halFlag;
-        if (!xsd::isUnknownAudioInOutFlag(flag) &&
-            audio_output_flag_from_string(flag.c_str(), &halFlag)) {
-            *halFlags = static_cast<audio_output_flags_t>(*halFlags | halFlag);
-        } else {
-            ALOGE("Unknown audio output flag \"%s\"", flag.c_str());
-            success = false;
-        }
-    }
-    return success;
-}
-
-status_t sinkMetadataToHalV7(const SinkMetadata& sinkMetadata,
-                             std::vector<record_track_metadata_v7_t>* halTracks) {
-    std::vector<record_track_metadata> bases;
-    status_t result = sinkMetadataToHal(sinkMetadata, halTracks != nullptr ? &bases : nullptr);
-    if (halTracks != nullptr) {
-        halTracks->reserve(bases.size());
-    }
-    auto baseIter = std::make_move_iterator(bases.begin());
-    for (auto& metadata : sinkMetadata.tracks) {
-        record_track_metadata_v7_t halTrackMetadata;
-        CONVERT_CHECKED(HidlUtils::audioChannelMaskToHal(metadata.channelMask,
-                                                         &halTrackMetadata.channel_mask),
-                        result);
-        CONVERT_CHECKED(HidlUtils::audioTagsToHal(metadata.tags, halTrackMetadata.tags), result);
-        if (halTracks != nullptr) {
-            halTrackMetadata.base = std::move(*baseIter++);
-            halTracks->push_back(std::move(halTrackMetadata));
-        }
-    }
-    return result;
-}
-
-status_t sourceMetadataToHalV7(const SourceMetadata& sourceMetadata,
-                               std::vector<playback_track_metadata_v7_t>* halTracks) {
-    std::vector<playback_track_metadata_t> bases;
-    status_t result = sourceMetadataToHal(sourceMetadata, halTracks != nullptr ? &bases : nullptr);
-    if (halTracks != nullptr) {
-        halTracks->reserve(bases.size());
-    }
-    auto baseIter = std::make_move_iterator(bases.begin());
-    for (auto& metadata : sourceMetadata.tracks) {
-        playback_track_metadata_v7_t halTrackMetadata;
-        CONVERT_CHECKED(HidlUtils::audioChannelMaskToHal(metadata.channelMask,
-                                                         &halTrackMetadata.channel_mask),
-                        result);
-        CONVERT_CHECKED(HidlUtils::audioTagsToHal(metadata.tags, halTrackMetadata.tags), result);
-        if (halTracks != nullptr) {
-            halTrackMetadata.base = std::move(*baseIter++);
-            halTracks->push_back(std::move(halTrackMetadata));
-        }
-    }
-    return result;
-}
-#endif
-
-}  // namespace implementation
-}  // namespace CPP_VERSION
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
diff --git a/audio/core/all-versions/default/Device.cpp b/audio/core/all-versions/default/Device.cpp
index 7caed44..70a1a4d 100644
--- a/audio/core/all-versions/default/Device.cpp
+++ b/audio/core/all-versions/default/Device.cpp
@@ -17,9 +17,7 @@
 #define LOG_TAG "DeviceHAL"
 
 #include "core/default/Device.h"
-#include <HidlUtils.h>
 #include "common/all-versions/default/EffectMap.h"
-#include "core/default/Conversions.h"
 #include "core/default/StreamIn.h"
 #include "core/default/StreamOut.h"
 #include "core/default/Util.h"
@@ -33,6 +31,8 @@
 
 #include <android/log.h>
 
+#include <HidlUtils.h>
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -160,11 +160,11 @@
     audio_stream_out_t* halStream;
     audio_devices_t halDevice;
     char halDeviceAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
-    if (deviceAddressToHal(device, &halDevice, halDeviceAddress) != NO_ERROR) {
+    if (CoreUtils::deviceAddressToHal(device, &halDevice, halDeviceAddress) != NO_ERROR) {
         return {Result::INVALID_ARGUMENTS, nullptr};
     }
     audio_output_flags_t halFlags;
-    if (!audioOutputFlagsToHal(flags, &halFlags)) {
+    if (CoreUtils::audioOutputFlagsToHal(flags, &halFlags) != NO_ERROR) {
         return {Result::INVALID_ARGUMENTS, nullptr};
     }
     ALOGV("open_output_stream handle: %d devices: %x flags: %#x "
@@ -195,12 +195,12 @@
     audio_stream_in_t* halStream;
     audio_devices_t halDevice;
     char halDeviceAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
-    if (deviceAddressToHal(device, &halDevice, halDeviceAddress) != NO_ERROR) {
+    if (CoreUtils::deviceAddressToHal(device, &halDevice, halDeviceAddress) != NO_ERROR) {
         return {Result::INVALID_ARGUMENTS, nullptr};
     }
     audio_input_flags_t halFlags;
     audio_source_t halSource;
-    if (!audioInputFlagsToHal(flags, &halFlags) ||
+    if (CoreUtils::audioInputFlagsToHal(flags, &halFlags) != NO_ERROR ||
         HidlUtils::audioSourceToHal(source, &halSource) != NO_ERROR) {
         return {Result::INVALID_ARGUMENTS, nullptr};
     }
@@ -254,9 +254,12 @@
                                       const SourceMetadata& sourceMetadata,
                                       openOutputStream_cb _hidl_cb) {
 #if MAJOR_VERSION <= 6
-    if (status_t status = sourceMetadataToHal(sourceMetadata, nullptr); status != NO_ERROR) {
+    if (status_t status = CoreUtils::sourceMetadataToHal(sourceMetadata, nullptr);
+        status != NO_ERROR) {
 #else
-    if (status_t status = sourceMetadataToHalV7(sourceMetadata, nullptr); status != NO_ERROR) {
+    if (status_t status = CoreUtils::sourceMetadataToHalV7(sourceMetadata,
+                                                           false /*ignoreNonVendorTags*/, nullptr);
+        status != NO_ERROR) {
 #endif
         _hidl_cb(analyzeStatus("sourceMetadataToHal", status), nullptr, AudioConfig{});
         return Void();
@@ -288,9 +291,11 @@
         return Void();
     }
 #if MAJOR_VERSION <= 6
-    if (status_t status = sinkMetadataToHal(sinkMetadata, nullptr); status != NO_ERROR) {
+    if (status_t status = CoreUtils::sinkMetadataToHal(sinkMetadata, nullptr); status != NO_ERROR) {
 #else
-    if (status_t status = sinkMetadataToHalV7(sinkMetadata, nullptr); status != NO_ERROR) {
+    if (status_t status = CoreUtils::sinkMetadataToHalV7(sinkMetadata,
+                                                         false /*ignoreNonVendorTags*/, nullptr);
+        status != NO_ERROR) {
 #endif
         _hidl_cb(analyzeStatus("sinkMetadataToHal", status), nullptr, AudioConfig{});
         return Void();
@@ -444,7 +449,7 @@
         mDevice->get_microphones(mDevice, &mic_array[0], &actual_mics) == 0) {
         microphones.resize(actual_mics);
         for (size_t i = 0; i < actual_mics; ++i) {
-            halToMicrophoneCharacteristics(&microphones[i], mic_array[i]);
+            (void)CoreUtils::microphoneInfoFromHal(mic_array[i], &microphones[i]);
         }
         retval = Result::OK;
     }
diff --git a/audio/core/all-versions/default/ParametersUtil.cpp b/audio/core/all-versions/default/ParametersUtil.cpp
index 694eb73..4d53645 100644
--- a/audio/core/all-versions/default/ParametersUtil.cpp
+++ b/audio/core/all-versions/default/ParametersUtil.cpp
@@ -15,11 +15,12 @@
  */
 
 #include "core/default/ParametersUtil.h"
-#include "core/default/Conversions.h"
 #include "core/default/Util.h"
 
 #include <system/audio.h>
 
+#include <util/CoreUtils.h>
+
 namespace android {
 namespace hardware {
 namespace audio {
@@ -153,7 +154,7 @@
 Result ParametersUtil::setParam(const char* name, const DeviceAddress& address) {
     audio_devices_t halDeviceType;
     char halDeviceAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
-    if (deviceAddressToHal(address, &halDeviceType, halDeviceAddress) != NO_ERROR) {
+    if (CoreUtils::deviceAddressToHal(address, &halDeviceType, halDeviceAddress) != NO_ERROR) {
         return Result::INVALID_ARGUMENTS;
     }
     AudioParameter params{String8(halDeviceAddress)};
diff --git a/audio/core/all-versions/default/Stream.cpp b/audio/core/all-versions/default/Stream.cpp
index 3f8efd2..7e32573 100644
--- a/audio/core/all-versions/default/Stream.cpp
+++ b/audio/core/all-versions/default/Stream.cpp
@@ -19,7 +19,6 @@
 #include "core/default/Stream.h"
 #include "common/all-versions/HidlSupport.h"
 #include "common/all-versions/default/EffectMap.h"
-#include "core/default/Conversions.h"
 #include "core/default/Util.h"
 
 #include <inttypes.h>
@@ -30,6 +29,7 @@
 #include <hardware/audio_effect.h>
 #include <media/AudioContainers.h>
 #include <media/TypeConverter.h>
+#include <util/CoreUtils.h>
 
 namespace android {
 namespace hardware {
@@ -373,9 +373,10 @@
     hidl_vec<DeviceAddress> devices;
     if (retval == Result::OK) {
         devices.resize(1);
-        retval = Stream::analyzeStatus("get_devices",
-                                       deviceAddressFromHal(static_cast<audio_devices_t>(halDevice),
-                                                            nullptr, &devices[0]));
+        retval = Stream::analyzeStatus(
+                "get_devices",
+                CoreUtils::deviceAddressFromHal(static_cast<audio_devices_t>(halDevice), nullptr,
+                                                &devices[0]));
     }
     _hidl_cb(retval, devices);
     return Void();
diff --git a/audio/core/all-versions/default/StreamIn.cpp b/audio/core/all-versions/default/StreamIn.cpp
index c670a4d..599f3c3 100644
--- a/audio/core/all-versions/default/StreamIn.cpp
+++ b/audio/core/all-versions/default/StreamIn.cpp
@@ -17,7 +17,6 @@
 #define LOG_TAG "StreamInHAL"
 
 #include "core/default/StreamIn.h"
-#include "core/default/Conversions.h"
 #include "core/default/Util.h"
 #include "common/all-versions/HidlSupport.h"
 
@@ -27,6 +26,7 @@
 #include <HidlUtils.h>
 #include <android/log.h>
 #include <hardware/audio.h>
+#include <util/CoreUtils.h>
 #include <utils/Trace.h>
 #include <cmath>
 #include <memory>
@@ -481,13 +481,15 @@
 Result StreamIn::doUpdateSinkMetadata(const SinkMetadata& sinkMetadata) {
     std::vector<record_track_metadata> halTracks;
 #if MAJOR_VERSION <= 6
-    (void)sinkMetadataToHal(sinkMetadata, &halTracks);
+    (void)CoreUtils::sinkMetadataToHal(sinkMetadata, &halTracks);
 #else
     // Validate whether a conversion to V7 is possible. This is needed
     // to have a consistent behavior of the HAL regardless of the API
     // version of the legacy HAL (and also to be consistent with openInputStream).
     std::vector<record_track_metadata_v7> halTracksV7;
-    if (status_t status = sinkMetadataToHalV7(sinkMetadata, &halTracksV7); status == NO_ERROR) {
+    if (status_t status = CoreUtils::sinkMetadataToHalV7(
+                sinkMetadata, false /*ignoreNonVendorTags*/, &halTracksV7);
+        status == NO_ERROR) {
         halTracks.reserve(halTracksV7.size());
         for (auto metadata_v7 : halTracksV7) {
             halTracks.push_back(std::move(metadata_v7.base));
@@ -507,7 +509,9 @@
 #if MAJOR_VERSION >= 7
 Result StreamIn::doUpdateSinkMetadataV7(const SinkMetadata& sinkMetadata) {
     std::vector<record_track_metadata_v7> halTracks;
-    if (status_t status = sinkMetadataToHalV7(sinkMetadata, &halTracks); status != NO_ERROR) {
+    if (status_t status = CoreUtils::sinkMetadataToHalV7(sinkMetadata,
+                                                         false /*ignoreNonVendorTags*/, &halTracks);
+        status != NO_ERROR) {
         return Stream::analyzeStatus("sinkMetadataToHal", status);
     }
     const sink_metadata_v7_t halMetadata = {
@@ -553,7 +557,7 @@
         mStream->get_active_microphones(mStream, &mic_array[0], &actual_mics) == 0) {
         microphones.resize(actual_mics);
         for (size_t i = 0; i < actual_mics; ++i) {
-            halToMicrophoneCharacteristics(&microphones[i], mic_array[i]);
+            (void)CoreUtils::microphoneInfoFromHal(mic_array[i], &microphones[i]);
         }
         retval = Result::OK;
     }
diff --git a/audio/core/all-versions/default/StreamOut.cpp b/audio/core/all-versions/default/StreamOut.cpp
index c2ad720..5e4dd2a 100644
--- a/audio/core/all-versions/default/StreamOut.cpp
+++ b/audio/core/all-versions/default/StreamOut.cpp
@@ -17,7 +17,6 @@
 #define LOG_TAG "StreamOutHAL"
 
 #include "core/default/StreamOut.h"
-#include "core/default/Conversions.h"
 #include "core/default/Util.h"
 
 //#define LOG_NDEBUG 0
@@ -30,6 +29,7 @@
 #include <HidlUtils.h>
 #include <android/log.h>
 #include <hardware/audio.h>
+#include <util/CoreUtils.h>
 #include <utils/Trace.h>
 
 namespace android {
@@ -589,13 +589,15 @@
 Result StreamOut::doUpdateSourceMetadata(const SourceMetadata& sourceMetadata) {
     std::vector<playback_track_metadata_t> halTracks;
 #if MAJOR_VERSION <= 6
-    (void)sourceMetadataToHal(sourceMetadata, &halTracks);
+    (void)CoreUtils::sourceMetadataToHal(sourceMetadata, &halTracks);
 #else
     // Validate whether a conversion to V7 is possible. This is needed
     // to have a consistent behavior of the HAL regardless of the API
     // version of the legacy HAL (and also to be consistent with openOutputStream).
     std::vector<playback_track_metadata_v7> halTracksV7;
-    if (status_t status = sourceMetadataToHalV7(sourceMetadata, &halTracksV7); status == NO_ERROR) {
+    if (status_t status = CoreUtils::sourceMetadataToHalV7(
+                sourceMetadata, false /*ignoreNonVendorTags*/, &halTracksV7);
+        status == NO_ERROR) {
         halTracks.reserve(halTracksV7.size());
         for (auto metadata_v7 : halTracksV7) {
             halTracks.push_back(std::move(metadata_v7.base));
@@ -615,7 +617,9 @@
 #if MAJOR_VERSION >= 7
 Result StreamOut::doUpdateSourceMetadataV7(const SourceMetadata& sourceMetadata) {
     std::vector<playback_track_metadata_v7> halTracks;
-    if (status_t status = sourceMetadataToHalV7(sourceMetadata, &halTracks); status != NO_ERROR) {
+    if (status_t status = CoreUtils::sourceMetadataToHalV7(
+                sourceMetadata, false /*ignoreNonVendorTags*/, &halTracks);
+        status != NO_ERROR) {
         return Stream::analyzeStatus("sourceMetadataToHal", status);
     }
     const source_metadata_v7_t halMetadata = {
diff --git a/audio/core/all-versions/default/TEST_MAPPING b/audio/core/all-versions/default/TEST_MAPPING
new file mode 100644
index 0000000..d53c97a
--- /dev/null
+++ b/audio/core/all-versions/default/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "android.hardware.audio@7.0-util_tests"
+    }
+  ]
+}
diff --git a/audio/core/all-versions/default/include/core/default/Conversions.h b/audio/core/all-versions/default/include/core/default/Conversions.h
deleted file mode 100644
index 61720d5..0000000
--- a/audio/core/all-versions/default/include/core/default/Conversions.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2018 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_AUDIO_CONVERSIONS_H_
-#define ANDROID_HARDWARE_AUDIO_CONVERSIONS_H_
-
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
-
-#include <string>
-
-#include <system/audio.h>
-
-#include <VersionUtils.h>
-
-namespace android {
-namespace hardware {
-namespace audio {
-namespace CPP_VERSION {
-namespace implementation {
-
-using ::android::hardware::hidl_vec;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
-using namespace ::android::hardware::audio::CPP_VERSION;
-
-status_t deviceAddressToHal(const DeviceAddress& device, audio_devices_t* halDeviceType,
-                            char* halDeviceAddress);
-status_t deviceAddressFromHal(audio_devices_t halDeviceType, const char* halDeviceAddress,
-                              DeviceAddress* device);
-
-#if MAJOR_VERSION >= 4
-bool halToMicrophoneCharacteristics(MicrophoneInfo* pDst,
-                                    const struct audio_microphone_characteristic_t& src);
-status_t sinkMetadataToHal(const SinkMetadata& sinkMetadata,
-                           std::vector<record_track_metadata>* halTracks);
-status_t sourceMetadataToHal(const SourceMetadata& sourceMetadata,
-                             std::vector<playback_track_metadata_t>* halTracks);
-#endif
-
-#if MAJOR_VERSION <= 6
-using AudioInputFlags =
-        ::android::hardware::audio::common::CPP_VERSION::implementation::AudioInputFlagBitfield;
-using AudioOutputFlags =
-        ::android::hardware::audio::common::CPP_VERSION::implementation::AudioOutputFlagBitfield;
-
-inline bool audioInputFlagsToHal(AudioInputFlags flags, audio_input_flags_t* halFlags) {
-    *halFlags = static_cast<audio_input_flags_t>(flags);
-    return true;
-}
-
-inline bool audioOutputFlagsToHal(AudioOutputFlags flags, audio_output_flags_t* halFlags) {
-    *halFlags = static_cast<audio_output_flags_t>(flags);
-    return true;
-}
-#else
-bool audioInputFlagsToHal(const hidl_vec<AudioInOutFlag>& flags, audio_input_flags_t* halFlags);
-bool audioOutputFlagsToHal(const hidl_vec<AudioInOutFlag>& flags, audio_output_flags_t* halFlags);
-// Overloading isn't convenient when passing a nullptr.
-status_t sinkMetadataToHalV7(const SinkMetadata& sinkMetadata,
-                             std::vector<record_track_metadata_v7_t>* halTracks);
-status_t sourceMetadataToHalV7(const SourceMetadata& sourceMetadata,
-                               std::vector<playback_track_metadata_v7_t>* halTracks);
-#endif
-
-}  // namespace implementation
-}  // namespace CPP_VERSION
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_AUDIO_CONVERSIONS_H_
diff --git a/audio/core/all-versions/default/include/core/default/Device.h b/audio/core/all-versions/default/include/core/default/Device.h
index 2a4d226..5851fc9 100644
--- a/audio/core/all-versions/default/include/core/default/Device.h
+++ b/audio/core/all-versions/default/include/core/default/Device.h
@@ -31,6 +31,7 @@
 #include <hidl/MQDescriptor.h>
 
 #include <VersionUtils.h>
+#include <util/CoreUtils.h>
 
 namespace android {
 namespace hardware {
@@ -43,17 +44,10 @@
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-#if MAJOR_VERSION <= 6
-using AudioInputFlags =
-        ::android::hardware::audio::common::CPP_VERSION::implementation::AudioInputFlagBitfield;
-using AudioOutputFlags =
-        ::android::hardware::audio::common::CPP_VERSION::implementation::AudioOutputFlagBitfield;
-#else
-using AudioInputFlags = hidl_vec<::android::hardware::audio::CPP_VERSION::AudioInOutFlag>;
-using AudioOutputFlags = hidl_vec<::android::hardware::audio::CPP_VERSION::AudioInOutFlag>;
-#endif
 using namespace ::android::hardware::audio::common::CPP_VERSION;
 using namespace ::android::hardware::audio::CPP_VERSION;
+using AudioInputFlags = CoreUtils::AudioInputFlags;
+using AudioOutputFlags = CoreUtils::AudioOutputFlags;
 
 struct Device : public IDevice, public ParametersUtil {
     explicit Device(audio_hw_device_t* device);
diff --git a/audio/core/all-versions/default/util/Android.bp b/audio/core/all-versions/default/util/Android.bp
new file mode 100644
index 0000000..447184b
--- /dev/null
+++ b/audio/core/all-versions/default/util/Android.bp
@@ -0,0 +1,139 @@
+cc_defaults {
+    name: "android.hardware.audio-util_default",
+    defaults: ["hidl_defaults"],
+
+    vendor_available: true,
+
+    export_include_dirs: ["include"],
+
+    srcs: [
+        "CoreUtils.cpp",
+    ],
+
+    shared_libs: [
+        "liblog",
+        "libutils",
+        "libhidlbase",
+        "android.hardware.audio.common-util",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.audio.common-util",
+    ],
+
+    header_libs: [
+        "libaudio_system_headers",
+        "libhardware_headers",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.audio@2.0-util",
+    defaults: ["android.hardware.audio-util_default"],
+    shared_libs: [
+        "android.hardware.audio.common@2.0",
+        "android.hardware.audio.common@2.0-util",
+        "android.hardware.audio@2.0",
+    ],
+    cflags: [
+        "-DMAJOR_VERSION=2",
+        "-DMINOR_VERSION=0",
+        "-include common/all-versions/VersionMacro.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.audio@4.0-util",
+    defaults: ["android.hardware.audio-util_default"],
+    shared_libs: [
+        "android.hardware.audio.common@4.0",
+        "android.hardware.audio.common@4.0-util",
+        "android.hardware.audio@4.0",
+    ],
+    cflags: [
+        "-DMAJOR_VERSION=4",
+        "-DMINOR_VERSION=0",
+        "-include common/all-versions/VersionMacro.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.audio@5.0-util",
+    defaults: ["android.hardware.audio-util_default"],
+    shared_libs: [
+        "android.hardware.audio.common@5.0",
+        "android.hardware.audio.common@5.0-util",
+        "android.hardware.audio@5.0",
+    ],
+    cflags: [
+        "-DMAJOR_VERSION=5",
+        "-DMINOR_VERSION=0",
+        "-include common/all-versions/VersionMacro.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.audio@6.0-util",
+    defaults: ["android.hardware.audio-util_default"],
+    shared_libs: [
+        "android.hardware.audio.common@6.0",
+        "android.hardware.audio.common@6.0-util",
+        "android.hardware.audio@6.0",
+    ],
+    cflags: [
+        "-DMAJOR_VERSION=6",
+        "-DMINOR_VERSION=0",
+        "-include common/all-versions/VersionMacro.h",
+    ],
+}
+
+cc_library {
+    name: "android.hardware.audio@7.0-util",
+    defaults: ["android.hardware.audio-util_default"],
+    shared_libs: [
+        "android.hardware.audio.common@7.0",
+        "android.hardware.audio.common@7.0-enums",
+        "android.hardware.audio.common@7.0-util",
+        "android.hardware.audio@7.0",
+        "libbase",
+        "libxml2",
+    ],
+    cflags: [
+        "-DMAJOR_VERSION=7",
+        "-DMINOR_VERSION=0",
+        "-include common/all-versions/VersionMacro.h",
+    ],
+}
+
+// Note: this isn't a VTS test, but rather a unit test
+// to verify correctness of conversion utilities.
+cc_test {
+    name: "android.hardware.audio@7.0-util_tests",
+    defaults: ["android.hardware.audio-util_default"],
+
+    srcs: ["tests/coreutils_tests.cpp"],
+
+    // Use static linking to allow running in presubmit on
+    // targets that don't have HAL V7.
+    static_libs: [
+        "android.hardware.audio.common@7.0",
+        "android.hardware.audio.common@7.0-enums",
+        "android.hardware.audio.common@7.0-util",
+        "android.hardware.audio@7.0",
+        "android.hardware.audio@7.0-util",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libxml2",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+        "-DMAJOR_VERSION=7",
+        "-DMINOR_VERSION=0",
+        "-include common/all-versions/VersionMacro.h",
+    ],
+
+    test_suites: ["device-tests"],
+}
diff --git a/audio/core/all-versions/default/util/CoreUtils.cpp b/audio/core/all-versions/default/util/CoreUtils.cpp
new file mode 100644
index 0000000..14f76f3
--- /dev/null
+++ b/audio/core/all-versions/default/util/CoreUtils.cpp
@@ -0,0 +1,476 @@
+/*
+ * 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.
+ */
+
+#if MAJOR_VERSION >= 7
+#include <android_audio_policy_configuration_V7_0-enums.h>
+#endif
+#include <HidlUtils.h>
+#include <log/log.h>
+
+#include "util/CoreUtils.h"
+
+using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+#if MAJOR_VERSION >= 7
+namespace xsd {
+using namespace ::android::audio::policy::configuration::V7_0;
+}
+#endif
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace CPP_VERSION {
+namespace implementation {
+
+#define CONVERT_CHECKED(expr, result)                   \
+    if (status_t status = (expr); status != NO_ERROR) { \
+        result = status;                                \
+    }
+
+status_t CoreUtils::deviceAddressToHal(const DeviceAddress& device, audio_devices_t* halDeviceType,
+                                       char* halDeviceAddress) {
+#if MAJOR_VERSION >= 5
+    return HidlUtils::deviceAddressToHal(device, halDeviceType, halDeviceAddress);
+#else
+    return HidlUtils::deviceAddressToHalImpl(device, halDeviceType, halDeviceAddress);
+#endif
+}
+
+status_t CoreUtils::deviceAddressFromHal(audio_devices_t halDeviceType,
+                                         const char* halDeviceAddress, DeviceAddress* device) {
+#if MAJOR_VERSION >= 5
+    return HidlUtils::deviceAddressFromHal(halDeviceType, halDeviceAddress, device);
+#else
+    return HidlUtils::deviceAddressFromHalImpl(halDeviceType, halDeviceAddress, device);
+#endif
+}
+
+#if MAJOR_VERSION >= 4
+status_t CoreUtils::microphoneInfoFromHal(
+        const struct audio_microphone_characteristic_t& halMicInfo, MicrophoneInfo* micInfo) {
+    status_t result = NO_ERROR;
+    micInfo->deviceId = halMicInfo.device_id;
+    CONVERT_CHECKED(
+            deviceAddressFromHal(halMicInfo.device, halMicInfo.address, &micInfo->deviceAddress),
+            result);
+    size_t chCount;
+    for (chCount = 0; chCount < AUDIO_CHANNEL_COUNT_MAX; ++chCount) {
+        if (halMicInfo.channel_mapping[chCount] == AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED) {
+            break;
+        }
+    }
+    micInfo->channelMapping.resize(chCount);
+    for (size_t ch = 0; ch < micInfo->channelMapping.size(); ch++) {
+        micInfo->channelMapping[ch] = AudioMicrophoneChannelMapping(halMicInfo.channel_mapping[ch]);
+    }
+    micInfo->location = AudioMicrophoneLocation(halMicInfo.location);
+    micInfo->group = AudioMicrophoneGroup(halMicInfo.group);
+    micInfo->indexInTheGroup = static_cast<uint32_t>(halMicInfo.index_in_the_group);
+    micInfo->sensitivity = halMicInfo.sensitivity;
+    micInfo->maxSpl = halMicInfo.max_spl;
+    micInfo->minSpl = halMicInfo.min_spl;
+    micInfo->directionality = AudioMicrophoneDirectionality(halMicInfo.directionality);
+    micInfo->frequencyResponse.resize(halMicInfo.num_frequency_responses);
+    for (size_t k = 0; k < halMicInfo.num_frequency_responses; k++) {
+        micInfo->frequencyResponse[k].frequency = halMicInfo.frequency_responses[0][k];
+        micInfo->frequencyResponse[k].level = halMicInfo.frequency_responses[1][k];
+    }
+    micInfo->position.x = halMicInfo.geometric_location.x;
+    micInfo->position.y = halMicInfo.geometric_location.y;
+    micInfo->position.z = halMicInfo.geometric_location.z;
+    micInfo->orientation.x = halMicInfo.orientation.x;
+    micInfo->orientation.y = halMicInfo.orientation.y;
+    micInfo->orientation.z = halMicInfo.orientation.z;
+    return result;
+}
+
+status_t CoreUtils::microphoneInfoToHal(const MicrophoneInfo& micInfo,
+                                        audio_microphone_characteristic_t* halMicInfo) {
+    status_t result = NO_ERROR;
+    strncpy(halMicInfo->device_id, micInfo.deviceId.c_str(), AUDIO_MICROPHONE_ID_MAX_LEN);
+    halMicInfo->device_id[AUDIO_MICROPHONE_ID_MAX_LEN - 1] = '\0';
+    if (micInfo.deviceId.size() >= AUDIO_MICROPHONE_ID_MAX_LEN) {
+        ALOGE("HIDL MicrophoneInfo device ID is too long: %zu", micInfo.deviceId.size());
+        result = BAD_VALUE;
+    }
+    CONVERT_CHECKED(
+            deviceAddressToHal(micInfo.deviceAddress, &halMicInfo->device, halMicInfo->address),
+            result);
+    if (micInfo.channelMapping.size() > AUDIO_CHANNEL_COUNT_MAX) {
+        ALOGE("HIDL MicrophoneInfo has too many channelMapping elements: %zu",
+              micInfo.channelMapping.size());
+        result = BAD_VALUE;
+    }
+    size_t ch;
+    for (ch = 0; ch < micInfo.channelMapping.size() && ch < AUDIO_CHANNEL_COUNT_MAX; ch++) {
+        halMicInfo->channel_mapping[ch] =
+                static_cast<audio_microphone_channel_mapping_t>(micInfo.channelMapping[ch]);
+    }
+    for (; ch < AUDIO_CHANNEL_COUNT_MAX; ch++) {
+        halMicInfo->channel_mapping[ch] = AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED;
+    }
+    halMicInfo->location = static_cast<audio_microphone_location_t>(micInfo.location);
+    halMicInfo->group = static_cast<audio_microphone_group_t>(micInfo.group);
+    halMicInfo->index_in_the_group = static_cast<unsigned int>(micInfo.indexInTheGroup);
+    halMicInfo->sensitivity = micInfo.sensitivity;
+    halMicInfo->max_spl = micInfo.maxSpl;
+    halMicInfo->min_spl = micInfo.minSpl;
+    halMicInfo->directionality =
+            static_cast<audio_microphone_directionality_t>(micInfo.directionality);
+    halMicInfo->num_frequency_responses =
+            static_cast<unsigned int>(micInfo.frequencyResponse.size());
+    if (halMicInfo->num_frequency_responses > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
+        ALOGE("HIDL MicrophoneInfo has too many frequency responses: %u",
+              halMicInfo->num_frequency_responses);
+        halMicInfo->num_frequency_responses = AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES;
+        result = BAD_VALUE;
+    }
+    for (size_t k = 0; k < halMicInfo->num_frequency_responses; k++) {
+        halMicInfo->frequency_responses[0][k] = micInfo.frequencyResponse[k].frequency;
+        halMicInfo->frequency_responses[1][k] = micInfo.frequencyResponse[k].level;
+    }
+    halMicInfo->geometric_location.x = micInfo.position.x;
+    halMicInfo->geometric_location.y = micInfo.position.y;
+    halMicInfo->geometric_location.z = micInfo.position.z;
+    halMicInfo->orientation.x = micInfo.orientation.x;
+    halMicInfo->orientation.y = micInfo.orientation.y;
+    halMicInfo->orientation.z = micInfo.orientation.z;
+    return result;
+}
+
+status_t CoreUtils::sinkMetadataFromHal(const std::vector<record_track_metadata_t>& halTracks,
+                                        SinkMetadata* sinkMetadata) {
+    status_t result = NO_ERROR;
+    sinkMetadata->tracks.resize(halTracks.size());
+    for (size_t i = 0; i < sinkMetadata->tracks.size(); ++i) {
+        const auto& halTrackMetadata = halTracks[i];
+        RecordTrackMetadata trackMetadata{};
+        CONVERT_CHECKED(
+                HidlUtils::audioSourceFromHal(halTrackMetadata.source, &trackMetadata.source),
+                result);
+        trackMetadata.gain = halTrackMetadata.gain;
+#if MAJOR_VERSION >= 5
+        if (halTrackMetadata.dest_device != AUDIO_DEVICE_NONE) {
+            DeviceAddress address;
+            if (status_t status =
+                        deviceAddressFromHal(halTrackMetadata.dest_device,
+                                             halTrackMetadata.dest_device_address, &address);
+                status == NO_ERROR) {
+                trackMetadata.destination.device(std::move(address));
+            } else {
+                result = status;
+            }
+        }
+#if MAJOR_VERSION >= 7
+        trackMetadata.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
+#endif
+#endif  // MAJOR_VERSION >= 5
+        sinkMetadata->tracks[i] = std::move(trackMetadata);
+    }
+    return result;
+}
+
+status_t CoreUtils::sinkMetadataFromHalV7(const std::vector<record_track_metadata_v7_t>& halTracks,
+                                          bool ignoreNonVendorTags, SinkMetadata* sinkMetadata) {
+    std::vector<record_track_metadata_t> bases;
+    bases.reserve(halTracks.size());
+    std::transform(halTracks.begin(), halTracks.end(), std::back_inserter(bases),
+                   [](const record_track_metadata_v7_t& src) -> record_track_metadata_t {
+                       record_track_metadata_t result;
+                       record_track_metadata_from_v7(&result, &src);
+                       return result;
+                   });
+    status_t result = sinkMetadataFromHal(bases, sinkMetadata);
+#if MAJOR_VERSION >= 7
+    for (size_t i = 0; i < halTracks.size(); ++i) {
+        auto& trackMetadata = sinkMetadata->tracks[i];
+        const auto& halTrackMetadata = halTracks[i];
+        CONVERT_CHECKED(
+                HidlUtils::audioChannelMaskFromHal(halTrackMetadata.channel_mask, true /*isInput*/,
+                                                   &trackMetadata.channelMask),
+                result);
+        std::vector<std::string> strTags = HidlUtils::splitAudioTags(halTrackMetadata.tags);
+        if (ignoreNonVendorTags) {
+            strTags = HidlUtils::filterOutNonVendorTags(strTags);
+        }
+        CONVERT_CHECKED(HidlUtils::audioTagsFromHal(strTags, &trackMetadata.tags), result);
+    }
+#else
+    (void)ignoreNonVendorTags;
+#endif
+    return result;
+}
+
+status_t CoreUtils::sinkMetadataToHal(const SinkMetadata& sinkMetadata,
+                                      std::vector<record_track_metadata_t>* halTracks) {
+    status_t result = NO_ERROR;
+    if (halTracks != nullptr) {
+        halTracks->reserve(sinkMetadata.tracks.size());
+    }
+    for (auto& trackMetadata : sinkMetadata.tracks) {
+        record_track_metadata halTrackMetadata{.gain = trackMetadata.gain};
+        CONVERT_CHECKED(HidlUtils::audioSourceToHal(trackMetadata.source, &halTrackMetadata.source),
+                        result);
+#if MAJOR_VERSION >= 5
+        if (trackMetadata.destination.getDiscriminator() ==
+            RecordTrackMetadata::Destination::hidl_discriminator::device) {
+            CONVERT_CHECKED(deviceAddressToHal(trackMetadata.destination.device(),
+                                               &halTrackMetadata.dest_device,
+                                               halTrackMetadata.dest_device_address),
+                            result);
+        }
+#endif
+        if (halTracks != nullptr) {
+            halTracks->push_back(std::move(halTrackMetadata));
+        }
+    }
+    return result;
+}
+
+status_t CoreUtils::sinkMetadataToHalV7(const SinkMetadata& sinkMetadata, bool ignoreNonVendorTags,
+                                        std::vector<record_track_metadata_v7_t>* halTracks) {
+    std::vector<record_track_metadata> bases;
+    status_t result = sinkMetadataToHal(sinkMetadata, halTracks != nullptr ? &bases : nullptr);
+    if (halTracks != nullptr) {
+        halTracks->reserve(sinkMetadata.tracks.size());
+    }
+    for (size_t i = 0; i < sinkMetadata.tracks.size(); ++i) {
+        record_track_metadata_v7_t halTrackMetadata;
+        if (halTracks != nullptr) {
+            record_track_metadata_to_v7(&halTrackMetadata, &bases[i]);
+        }
+#if MAJOR_VERSION >= 7
+        const auto& trackMetadata = sinkMetadata.tracks[i];
+        CONVERT_CHECKED(HidlUtils::audioChannelMaskToHal(trackMetadata.channelMask,
+                                                         &halTrackMetadata.channel_mask),
+                        result);
+        if (ignoreNonVendorTags) {
+            CONVERT_CHECKED(
+                    HidlUtils::audioTagsToHal(HidlUtils::filterOutNonVendorTags(trackMetadata.tags),
+                                              halTrackMetadata.tags),
+                    result);
+        } else {
+            CONVERT_CHECKED(HidlUtils::audioTagsToHal(trackMetadata.tags, halTrackMetadata.tags),
+                            result);
+        }
+#else
+        (void)ignoreNonVendorTags;
+#endif
+        if (halTracks != nullptr) {
+            halTracks->push_back(std::move(halTrackMetadata));
+        }
+    }
+    return result;
+}
+
+status_t CoreUtils::sourceMetadataFromHal(const std::vector<playback_track_metadata_t>& halTracks,
+                                          SourceMetadata* sourceMetadata) {
+    status_t result = NO_ERROR;
+    sourceMetadata->tracks.resize(halTracks.size());
+    for (size_t i = 0; i < sourceMetadata->tracks.size(); ++i) {
+        const auto& halTrackMetadata = halTracks[i];
+        PlaybackTrackMetadata trackMetadata{};
+        CONVERT_CHECKED(HidlUtils::audioUsageFromHal(halTrackMetadata.usage, &trackMetadata.usage),
+                        result);
+        CONVERT_CHECKED(HidlUtils::audioContentTypeFromHal(halTrackMetadata.content_type,
+                                                           &trackMetadata.contentType),
+                        result);
+        trackMetadata.gain = halTrackMetadata.gain;
+#if MAJOR_VERSION >= 7
+        trackMetadata.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
+#endif
+        sourceMetadata->tracks[i] = std::move(trackMetadata);
+    }
+    return result;
+}
+
+status_t CoreUtils::sourceMetadataFromHalV7(
+        const std::vector<playback_track_metadata_v7_t>& halTracks, bool ignoreNonVendorTags,
+        SourceMetadata* sourceMetadata) {
+    std::vector<playback_track_metadata_t> bases;
+    bases.reserve(halTracks.size());
+    std::transform(halTracks.begin(), halTracks.end(), std::back_inserter(bases),
+                   [](const playback_track_metadata_v7_t& src) -> playback_track_metadata_t {
+                       playback_track_metadata_t result;
+                       playback_track_metadata_from_v7(&result, &src);
+                       return result;
+                   });
+    status_t result = sourceMetadataFromHal(bases, sourceMetadata);
+#if MAJOR_VERSION >= 7
+    for (size_t i = 0; i < halTracks.size(); ++i) {
+        auto& trackMetadata = sourceMetadata->tracks[i];
+        const auto& halTrackMetadata = halTracks[i];
+        CONVERT_CHECKED(
+                HidlUtils::audioChannelMaskFromHal(halTrackMetadata.channel_mask, false /*isInput*/,
+                                                   &trackMetadata.channelMask),
+                result);
+        std::vector<std::string> strTags = HidlUtils::splitAudioTags(halTrackMetadata.tags);
+        if (ignoreNonVendorTags) {
+            strTags = HidlUtils::filterOutNonVendorTags(strTags);
+        }
+        CONVERT_CHECKED(HidlUtils::audioTagsFromHal(strTags, &trackMetadata.tags), result);
+    }
+#else
+    (void)ignoreNonVendorTags;
+#endif
+    return result;
+}
+
+status_t CoreUtils::sourceMetadataToHal(const SourceMetadata& sourceMetadata,
+                                        std::vector<playback_track_metadata_t>* halTracks) {
+    status_t result = NO_ERROR;
+    if (halTracks != nullptr) {
+        halTracks->reserve(sourceMetadata.tracks.size());
+    }
+    for (auto& trackMetadata : sourceMetadata.tracks) {
+        playback_track_metadata_t halTrackMetadata{.gain = trackMetadata.gain};
+        CONVERT_CHECKED(HidlUtils::audioUsageToHal(trackMetadata.usage, &halTrackMetadata.usage),
+                        result);
+        CONVERT_CHECKED(HidlUtils::audioContentTypeToHal(trackMetadata.contentType,
+                                                         &halTrackMetadata.content_type),
+                        result);
+        if (halTracks != nullptr) {
+            halTracks->push_back(std::move(halTrackMetadata));
+        }
+    }
+    return result;
+}
+
+status_t CoreUtils::sourceMetadataToHalV7(const SourceMetadata& sourceMetadata,
+                                          bool ignoreNonVendorTags,
+                                          std::vector<playback_track_metadata_v7_t>* halTracks) {
+    std::vector<playback_track_metadata_t> bases;
+    status_t result = sourceMetadataToHal(sourceMetadata, halTracks != nullptr ? &bases : nullptr);
+    if (halTracks != nullptr) {
+        halTracks->reserve(sourceMetadata.tracks.size());
+    }
+    for (size_t i = 0; i < sourceMetadata.tracks.size(); ++i) {
+        playback_track_metadata_v7_t halTrackMetadata;
+        if (halTracks != nullptr) {
+            playback_track_metadata_to_v7(&halTrackMetadata, &bases[i]);
+        }
+#if MAJOR_VERSION >= 7
+        const auto& trackMetadata = sourceMetadata.tracks[i];
+        CONVERT_CHECKED(HidlUtils::audioChannelMaskToHal(trackMetadata.channelMask,
+                                                         &halTrackMetadata.channel_mask),
+                        result);
+        if (ignoreNonVendorTags) {
+            CONVERT_CHECKED(
+                    HidlUtils::audioTagsToHal(HidlUtils::filterOutNonVendorTags(trackMetadata.tags),
+                                              halTrackMetadata.tags),
+                    result);
+        } else {
+            CONVERT_CHECKED(HidlUtils::audioTagsToHal(trackMetadata.tags, halTrackMetadata.tags),
+                            result);
+        }
+#else
+        (void)ignoreNonVendorTags;
+#endif
+        if (halTracks != nullptr) {
+            halTracks->push_back(std::move(halTrackMetadata));
+        }
+    }
+    return result;
+}
+#endif  // MAJOR_VERSION >= 4
+
+#if MAJOR_VERSION >= 7
+namespace xsd {
+using namespace ::android::audio::policy::configuration::V7_0;
+}
+
+status_t CoreUtils::audioInputFlagsFromHal(audio_input_flags_t halFlagMask,
+                                           AudioInputFlags* flags) {
+    status_t status = NO_ERROR;
+    std::vector<AudioInOutFlag> result;
+    for (uint32_t bit = 0; halFlagMask != 0 && bit < sizeof(audio_input_flags_t) * 8; ++bit) {
+        audio_input_flags_t flag = static_cast<audio_input_flags_t>(1u << bit);
+        if ((flag & halFlagMask) == flag) {
+            AudioInOutFlag flagStr = audio_input_flag_to_string(flag);
+            if (!flagStr.empty() && !xsd::isUnknownAudioInOutFlag(flagStr)) {
+                result.push_back(flagStr);
+            } else {
+                ALOGE("Unknown audio input flag value 0x%X", flag);
+                status = BAD_VALUE;
+            }
+            halFlagMask = static_cast<audio_input_flags_t>(halFlagMask & ~flag);
+        }
+    }
+    *flags = result;
+    return status;
+}
+
+status_t CoreUtils::audioInputFlagsToHal(const AudioInputFlags& flags,
+                                         audio_input_flags_t* halFlagMask) {
+    status_t status = NO_ERROR;
+    *halFlagMask = {};
+    for (const auto& flag : flags) {
+        audio_input_flags_t halFlag;
+        if (!xsd::isUnknownAudioInOutFlag(flag) &&
+            audio_input_flag_from_string(flag.c_str(), &halFlag)) {
+            *halFlagMask = static_cast<audio_input_flags_t>(*halFlagMask | halFlag);
+        } else {
+            ALOGE("Unknown audio input flag \"%s\"", flag.c_str());
+            status = BAD_VALUE;
+        }
+    }
+    return status;
+}
+
+status_t CoreUtils::audioOutputFlagsFromHal(audio_output_flags_t halFlagMask,
+                                            AudioOutputFlags* flags) {
+    status_t status = NO_ERROR;
+    std::vector<AudioInOutFlag> result;
+    for (uint32_t bit = 0; halFlagMask != 0 && bit < sizeof(audio_output_flags_t) * 8; ++bit) {
+        audio_output_flags_t flag = static_cast<audio_output_flags_t>(1u << bit);
+        if ((flag & halFlagMask) == flag) {
+            AudioInOutFlag flagStr = audio_output_flag_to_string(flag);
+            if (!flagStr.empty() && !xsd::isUnknownAudioInOutFlag(flagStr)) {
+                result.push_back(flagStr);
+            } else {
+                ALOGE("Unknown audio output flag value 0x%X", flag);
+                status = BAD_VALUE;
+            }
+            halFlagMask = static_cast<audio_output_flags_t>(halFlagMask & ~flag);
+        }
+    }
+    *flags = result;
+    return status;
+}
+
+status_t CoreUtils::audioOutputFlagsToHal(const AudioOutputFlags& flags,
+                                          audio_output_flags_t* halFlagMask) {
+    status_t status = NO_ERROR;
+    *halFlagMask = {};
+    for (const auto& flag : flags) {
+        audio_output_flags_t halFlag;
+        if (!xsd::isUnknownAudioInOutFlag(flag) &&
+            audio_output_flag_from_string(flag.c_str(), &halFlag)) {
+            *halFlagMask = static_cast<audio_output_flags_t>(*halFlagMask | halFlag);
+        } else {
+            ALOGE("Unknown audio output flag \"%s\"", flag.c_str());
+            status = BAD_VALUE;
+        }
+    }
+    return status;
+}
+#endif
+
+}  // namespace implementation
+}  // namespace CPP_VERSION
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/core/all-versions/default/util/include/util/CoreUtils.h b/audio/core/all-versions/default/util/include/util/CoreUtils.h
new file mode 100644
index 0000000..1e5272a
--- /dev/null
+++ b/audio/core/all-versions/default/util/include/util/CoreUtils.h
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+// clang-format off
+#include PATH(android/hardware/audio/FILE_VERSION/types.h)
+// clang-format off
+
+#include <vector>
+
+#include <system/audio.h>
+
+#include <common/all-versions/VersionUtils.h>
+#include <VersionUtils.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace CPP_VERSION {
+namespace implementation {
+
+using ::android::hardware::audio::common::utils::EnumBitfield;
+using ::android::hardware::hidl_vec;
+using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::CPP_VERSION;
+
+struct CoreUtils {
+    // Note: the converters for DeviceAddress have to be in CoreUtils for HAL V4
+    // because DeviceAddress used to be defined in the core HAL. For V5 and above
+    // these functions simply delegate to HidlUtils.
+    static status_t deviceAddressToHal(const DeviceAddress& device, audio_devices_t* halDeviceType,
+            char* halDeviceAddress);
+    static status_t deviceAddressFromHal(audio_devices_t halDeviceType, const char* halDeviceAddress,
+            DeviceAddress* device);
+#if MAJOR_VERSION >= 4
+    static status_t microphoneInfoFromHal(const struct audio_microphone_characteristic_t& halMicInfo,
+            MicrophoneInfo* micInfo);
+    static status_t microphoneInfoToHal(const MicrophoneInfo& micInfo, audio_microphone_characteristic_t* halMicInfo);
+    // Note: {Sink|Source}Metadata types are defined in 'common' (since V5), so they can be used
+    // by the BT HAL. However, the converters are defined here, not in HidlUtils to avoid adding
+    // conditionals to handle V4. The converters are only used by 'core' HAL anyways.
+    static status_t sinkMetadataFromHal(const std::vector<record_track_metadata_t>& halTracks,
+            SinkMetadata* sinkMetadata);
+    static status_t sinkMetadataFromHalV7(const std::vector<record_track_metadata_v7_t>& halTracks,
+            bool ignoreNonVendorTags, SinkMetadata* sinkMetadata);
+    static status_t sinkMetadataToHal(const SinkMetadata& sinkMetadata,
+            std::vector<record_track_metadata_t>* halTracks);
+    static status_t sinkMetadataToHalV7(const SinkMetadata& sinkMetadata, bool ignoreNonVendorTags,
+            std::vector<record_track_metadata_v7_t>* halTracks);
+    static status_t sourceMetadataFromHal(const std::vector<playback_track_metadata_t>& halTracks,
+            SourceMetadata* sourceMetadata);
+    static status_t sourceMetadataFromHalV7(const std::vector<playback_track_metadata_v7_t>& halTracks,
+            bool ignoreNonVendorTags, SourceMetadata* sourceMetadata);
+    static status_t sourceMetadataToHal(const SourceMetadata& sourceMetadata,
+            std::vector<playback_track_metadata_t>* halTracks);
+    static status_t sourceMetadataToHalV7(const SourceMetadata& sourceMetadata, bool ignoreNonVendorTags,
+            std::vector<playback_track_metadata_v7_t>* halTracks);
+#endif
+
+#if MAJOR_VERSION <= 6
+    using AudioInputFlags =
+            ::android::hardware::audio::common::CPP_VERSION::implementation::AudioInputFlagBitfield;
+    using AudioOutputFlags =
+            ::android::hardware::audio::common::CPP_VERSION::implementation::AudioOutputFlagBitfield;
+    static inline status_t audioInputFlagsFromHal(audio_input_flags_t halFlagMask, AudioInputFlags* flags) {
+        *flags = EnumBitfield<AudioInputFlag>(halFlagMask);
+        return NO_ERROR;
+    }
+    static inline status_t audioInputFlagsToHal(AudioInputFlags flags, audio_input_flags_t* halFlagMask) {
+        *halFlagMask = static_cast<audio_input_flags_t>(flags);
+        return NO_ERROR;
+    }
+    static inline status_t audioOutputFlagsFromHal(audio_output_flags_t halFlagMask, AudioOutputFlags* flags) {
+        *flags = EnumBitfield<AudioOutputFlag>(halFlagMask);
+        return NO_ERROR;
+    }
+    static inline status_t audioOutputFlagsToHal(AudioOutputFlags flags, audio_output_flags_t* halFlagMask) {
+        *halFlagMask = static_cast<audio_output_flags_t>(flags);
+        return NO_ERROR;
+    }
+#else
+    using AudioInputFlags = hidl_vec<::android::hardware::audio::CPP_VERSION::AudioInOutFlag>;
+    using AudioOutputFlags = hidl_vec<::android::hardware::audio::CPP_VERSION::AudioInOutFlag>;
+    static status_t audioInputFlagsFromHal(audio_input_flags_t halFlagMask, AudioInputFlags* flags);
+    static status_t audioInputFlagsToHal(const AudioInputFlags& flags, audio_input_flags_t* halFlagMask);
+    static status_t audioOutputFlagsFromHal(audio_output_flags_t halFlagMask, AudioOutputFlags* flags);
+    static status_t audioOutputFlagsToHal(const AudioOutputFlags& flags, audio_output_flags_t* halFlagMask);
+#endif
+
+};
+
+}  // namespace implementation
+}  // namespace CPP_VERSION
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/core/all-versions/default/util/tests/coreutils_tests.cpp b/audio/core/all-versions/default/util/tests/coreutils_tests.cpp
new file mode 100644
index 0000000..0c18482
--- /dev/null
+++ b/audio/core/all-versions/default/util/tests/coreutils_tests.cpp
@@ -0,0 +1,525 @@
+/*
+ * 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 <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#define LOG_TAG "CoreUtils_Test"
+#include <log/log.h>
+
+#include <android_audio_policy_configuration_V7_0-enums.h>
+#include <system/audio.h>
+#include <util/CoreUtils.h>
+#include <xsdc/XsdcSupport.h>
+
+using namespace android;
+using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::CPP_VERSION;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::audio::CPP_VERSION::implementation::CoreUtils;
+namespace xsd {
+using namespace ::android::audio::policy::configuration::V7_0;
+}
+
+static constexpr audio_channel_mask_t kInvalidHalChannelMask = AUDIO_CHANNEL_INVALID;
+static constexpr audio_content_type_t kInvalidHalContentType =
+        static_cast<audio_content_type_t>(0xFFFFFFFFU);
+static constexpr audio_devices_t kInvalidHalDevice = static_cast<audio_devices_t>(0xFFFFFFFFU);
+static constexpr audio_input_flags_t kInvalidInputFlags =
+        static_cast<audio_input_flags_t>(0xFFFFFFFFU);
+static constexpr audio_output_flags_t kInvalidOutputFlags =
+        static_cast<audio_output_flags_t>(0xFFFFFFFFU);
+// AUDIO_SOURCE_INVALID is framework-only.
+static constexpr audio_source_t kInvalidHalSource = static_cast<audio_source_t>(-1);
+static constexpr audio_usage_t kInvalidHalUsage = static_cast<audio_usage_t>(0xFFFFFFFFU);
+
+static bool isInputFlag(xsd::AudioInOutFlag flag) {
+    return toString(flag).find("_INPUT_FLAG_") != std::string::npos;
+}
+
+static bool isOutputFlag(xsd::AudioInOutFlag flag) {
+    return toString(flag).find("_OUTPUT_FLAG_") != std::string::npos;
+}
+
+TEST(CoreUtils, ConvertInvalidInputFlagMask) {
+    CoreUtils::AudioInputFlags invalid;
+    EXPECT_EQ(BAD_VALUE, CoreUtils::audioInputFlagsFromHal(kInvalidInputFlags, &invalid));
+    audio_input_flags_t halInvalid;
+    invalid.resize(1);
+    invalid[0] = "random string";
+    EXPECT_EQ(BAD_VALUE, CoreUtils::audioInputFlagsToHal(invalid, &halInvalid));
+}
+
+TEST(CoreUtils, ConvertInputFlagMask) {
+    CoreUtils::AudioInputFlags emptyInputFlags;
+    audio_input_flags_t halEmptyInputFlags;
+    EXPECT_EQ(NO_ERROR, CoreUtils::audioInputFlagsToHal(emptyInputFlags, &halEmptyInputFlags));
+    EXPECT_EQ(AUDIO_INPUT_FLAG_NONE, halEmptyInputFlags);
+    CoreUtils::AudioInputFlags emptyInputFlagsBack;
+    EXPECT_EQ(NO_ERROR,
+              CoreUtils::audioInputFlagsFromHal(halEmptyInputFlags, &emptyInputFlagsBack));
+    EXPECT_EQ(emptyInputFlags, emptyInputFlagsBack);
+    CoreUtils::AudioInputFlags emptyInputFlagsFromNone;
+    EXPECT_EQ(NO_ERROR,
+              CoreUtils::audioInputFlagsFromHal(AUDIO_INPUT_FLAG_NONE, &emptyInputFlagsFromNone));
+    EXPECT_EQ(emptyInputFlags, emptyInputFlagsFromNone);
+
+    std::vector<std::string> allEnumValues;
+    for (const auto enumVal : xsdc_enum_range<xsd::AudioInOutFlag>{}) {
+        if (isInputFlag(enumVal)) {
+            allEnumValues.push_back(toString(enumVal));
+        }
+    }
+    CoreUtils::AudioInputFlags allInputFlags;
+    allInputFlags.resize(allEnumValues.size());
+    for (size_t i = 0; i < allEnumValues.size(); ++i) {
+        allInputFlags[i] = allEnumValues[i];
+    }
+    audio_input_flags_t halAllInputFlags;
+    EXPECT_EQ(NO_ERROR, CoreUtils::audioInputFlagsToHal(allInputFlags, &halAllInputFlags));
+    CoreUtils::AudioInputFlags allInputFlagsBack;
+    EXPECT_EQ(NO_ERROR, CoreUtils::audioInputFlagsFromHal(halAllInputFlags, &allInputFlagsBack));
+    EXPECT_EQ(allInputFlags, allInputFlagsBack);
+}
+
+TEST(CoreUtils, ConvertInvalidOutputFlagMask) {
+    CoreUtils::AudioOutputFlags invalid;
+    EXPECT_EQ(BAD_VALUE, CoreUtils::audioOutputFlagsFromHal(kInvalidOutputFlags, &invalid));
+    audio_output_flags_t halInvalid;
+    invalid.resize(1);
+    invalid[0] = "random string";
+    EXPECT_EQ(BAD_VALUE, CoreUtils::audioOutputFlagsToHal(invalid, &halInvalid));
+}
+
+TEST(CoreUtils, ConvertOutputFlagMask) {
+    CoreUtils::AudioOutputFlags emptyOutputFlags;
+    audio_output_flags_t halEmptyOutputFlags;
+    EXPECT_EQ(NO_ERROR, CoreUtils::audioOutputFlagsToHal(emptyOutputFlags, &halEmptyOutputFlags));
+    EXPECT_EQ(AUDIO_OUTPUT_FLAG_NONE, halEmptyOutputFlags);
+    CoreUtils::AudioOutputFlags emptyOutputFlagsBack;
+    EXPECT_EQ(NO_ERROR,
+              CoreUtils::audioOutputFlagsFromHal(halEmptyOutputFlags, &emptyOutputFlagsBack));
+    EXPECT_EQ(emptyOutputFlags, emptyOutputFlagsBack);
+    CoreUtils::AudioOutputFlags emptyOutputFlagsFromNone;
+    EXPECT_EQ(NO_ERROR, CoreUtils::audioOutputFlagsFromHal(AUDIO_OUTPUT_FLAG_NONE,
+                                                           &emptyOutputFlagsFromNone));
+    EXPECT_EQ(emptyOutputFlags, emptyOutputFlagsFromNone);
+
+    std::vector<std::string> allEnumValues;
+    for (const auto enumVal : xsdc_enum_range<xsd::AudioInOutFlag>{}) {
+        if (isOutputFlag(enumVal)) {
+            allEnumValues.push_back(toString(enumVal));
+        }
+    }
+    CoreUtils::AudioOutputFlags allOutputFlags;
+    allOutputFlags.resize(allEnumValues.size());
+    for (size_t i = 0; i < allEnumValues.size(); ++i) {
+        allOutputFlags[i] = allEnumValues[i];
+    }
+    audio_output_flags_t halAllOutputFlags;
+    EXPECT_EQ(NO_ERROR, CoreUtils::audioOutputFlagsToHal(allOutputFlags, &halAllOutputFlags));
+    CoreUtils::AudioOutputFlags allOutputFlagsBack;
+    EXPECT_EQ(NO_ERROR, CoreUtils::audioOutputFlagsFromHal(halAllOutputFlags, &allOutputFlagsBack));
+    EXPECT_EQ(allOutputFlags, allOutputFlagsBack);
+}
+
+static MicrophoneInfo generateValidMicrophoneInfo() {
+    MicrophoneInfo micInfo{};
+    micInfo.deviceAddress.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC);
+    micInfo.channelMapping.resize(1);
+    micInfo.channelMapping[0] = AudioMicrophoneChannelMapping::DIRECT;
+    micInfo.location = AudioMicrophoneLocation::MAINBODY_MOVABLE;
+    micInfo.group = 42;
+    micInfo.indexInTheGroup = 13;
+    micInfo.sensitivity = 65.5;
+    micInfo.maxSpl = 100.5;
+    micInfo.minSpl = 36.6;
+    micInfo.directionality = AudioMicrophoneDirectionality::HYPER_CARDIOID;
+    micInfo.frequencyResponse.resize(1);
+    micInfo.frequencyResponse[0].frequency = 1000;
+    micInfo.frequencyResponse[0].level = 85;
+    micInfo.position.x = 0;
+    micInfo.position.y = 1;
+    micInfo.position.z = 0;
+    micInfo.orientation.x = 0;
+    micInfo.orientation.y = 0;
+    micInfo.orientation.z = 1;
+    return micInfo;
+}
+
+TEST(CoreUtils, ConvertInvalidMicrophoneInfo) {
+    MicrophoneInfo invalid;
+    audio_microphone_characteristic_t halInvalid{};
+    halInvalid.device = kInvalidHalDevice;
+    EXPECT_EQ(BAD_VALUE, CoreUtils::microphoneInfoFromHal(halInvalid, &invalid));
+
+    MicrophoneInfo oversizeDeviceId = generateValidMicrophoneInfo();
+    oversizeDeviceId.deviceId = std::string(AUDIO_MICROPHONE_ID_MAX_LEN + 1, 'A');
+    EXPECT_EQ(BAD_VALUE, CoreUtils::microphoneInfoToHal(oversizeDeviceId, &halInvalid));
+    MicrophoneInfo invalidDeviceType = generateValidMicrophoneInfo();
+    invalidDeviceType.deviceAddress.deviceType = "random string";
+    EXPECT_EQ(BAD_VALUE, CoreUtils::microphoneInfoToHal(invalidDeviceType, &halInvalid));
+    MicrophoneInfo oversizeChannelMapping = generateValidMicrophoneInfo();
+    oversizeChannelMapping.channelMapping.resize(AUDIO_CHANNEL_COUNT_MAX + 1);
+    EXPECT_EQ(BAD_VALUE, CoreUtils::microphoneInfoToHal(oversizeChannelMapping, &halInvalid));
+    MicrophoneInfo oversizeFrequencyResponses = generateValidMicrophoneInfo();
+    oversizeFrequencyResponses.frequencyResponse.resize(AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES +
+                                                        1);
+    EXPECT_EQ(BAD_VALUE, CoreUtils::microphoneInfoToHal(oversizeFrequencyResponses, &halInvalid));
+}
+
+TEST(CoreUtils, ConvertMicrophoneInfo) {
+    MicrophoneInfo micInfo = generateValidMicrophoneInfo();
+    audio_microphone_characteristic_t halMicInfo;
+    EXPECT_EQ(NO_ERROR, CoreUtils::microphoneInfoToHal(micInfo, &halMicInfo));
+    MicrophoneInfo micInfoBack;
+    EXPECT_EQ(NO_ERROR, CoreUtils::microphoneInfoFromHal(halMicInfo, &micInfoBack));
+    EXPECT_EQ(micInfo, micInfoBack);
+}
+
+static RecordTrackMetadata generateMinimalRecordTrackMetadata() {
+    RecordTrackMetadata metadata{};
+    metadata.source = toString(xsd::AudioSource::AUDIO_SOURCE_DEFAULT);
+    metadata.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
+    return metadata;
+}
+
+static RecordTrackMetadata generateValidRecordTrackMetadata() {
+    RecordTrackMetadata metadata = generateMinimalRecordTrackMetadata();
+    metadata.tags.resize(1);
+    metadata.tags[0] = "VX_GOOGLE_42";
+    metadata.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO);
+    metadata.gain = 1.0;
+    return metadata;
+}
+
+static RecordTrackMetadata generateValidRecordTrackMetadataWithDevice() {
+    RecordTrackMetadata metadata = generateValidRecordTrackMetadata();
+    metadata.destination.device({});
+    metadata.destination.device().deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_SPEAKER);
+    return metadata;
+}
+
+using SinkTracks = hidl_vec<RecordTrackMetadata>;
+
+TEST(CoreUtils, ConvertInvalidSinkMetadata) {
+    SinkMetadata invalidSource;
+    invalidSource.tracks = SinkTracks{generateMinimalRecordTrackMetadata()};
+    invalidSource.tracks[0].source = "random string";
+    EXPECT_EQ(BAD_VALUE, CoreUtils::sinkMetadataToHal(invalidSource, nullptr));
+    EXPECT_EQ(BAD_VALUE, CoreUtils::sinkMetadataToHalV7(invalidSource,
+                                                        false /*ignoreNonVendorTags*/, nullptr));
+    EXPECT_EQ(BAD_VALUE,
+              CoreUtils::sinkMetadataToHalV7(invalidSource, true /*ignoreNonVendorTags*/, nullptr));
+    SinkMetadata invalidDeviceType;
+    invalidDeviceType.tracks = SinkTracks{generateValidRecordTrackMetadataWithDevice()};
+    invalidDeviceType.tracks[0].destination.device().deviceType = "random string";
+    EXPECT_EQ(BAD_VALUE, CoreUtils::sinkMetadataToHal(invalidDeviceType, nullptr));
+    EXPECT_EQ(BAD_VALUE, CoreUtils::sinkMetadataToHalV7(invalidDeviceType,
+                                                        false /*ignoreNonVendorTags*/, nullptr));
+    EXPECT_EQ(BAD_VALUE, CoreUtils::sinkMetadataToHalV7(invalidDeviceType,
+                                                        true /*ignoreNonVendorTags*/, nullptr));
+    SinkMetadata invalidChannelMask;
+    invalidChannelMask.tracks = SinkTracks{generateValidRecordTrackMetadata()};
+    invalidChannelMask.tracks[0].channelMask = "random string";
+    // Channel mask is sliced away by 'sinkMetadataToHal'
+    EXPECT_EQ(NO_ERROR, CoreUtils::sinkMetadataToHal(invalidChannelMask, nullptr));
+    EXPECT_EQ(BAD_VALUE, CoreUtils::sinkMetadataToHalV7(invalidChannelMask,
+                                                        false /*ignoreNonVendorTags*/, nullptr));
+    EXPECT_EQ(BAD_VALUE, CoreUtils::sinkMetadataToHalV7(invalidChannelMask,
+                                                        true /*ignoreNonVendorTags*/, nullptr));
+    SinkMetadata invalidTags;
+    invalidTags.tracks = SinkTracks{generateValidRecordTrackMetadata()};
+    invalidTags.tracks[0].tags[0] = "random string";
+    // Tags are sliced away by 'sinkMetadataToHal'
+    EXPECT_EQ(NO_ERROR, CoreUtils::sinkMetadataToHal(invalidTags, nullptr));
+    EXPECT_EQ(BAD_VALUE,
+              CoreUtils::sinkMetadataToHalV7(invalidTags, false /*ignoreNonVendorTags*/, nullptr));
+    // Non-vendor tags should be filtered out.
+    EXPECT_EQ(NO_ERROR,
+              CoreUtils::sinkMetadataToHalV7(invalidTags, true /*ignoreNonVendorTags*/, nullptr));
+
+    // Verify that a default-initialized metadata is valid.
+    std::vector<record_track_metadata_t> halValid(1, record_track_metadata_t{});
+    std::vector<record_track_metadata_v7_t> halValidV7(1, record_track_metadata_v7_t{});
+    SinkMetadata valid;
+    EXPECT_EQ(NO_ERROR, CoreUtils::sinkMetadataFromHal(halValid, &valid));
+    EXPECT_EQ(NO_ERROR,
+              CoreUtils::sinkMetadataFromHalV7(halValidV7, false /*ignoreNonVendorTags*/, &valid));
+    EXPECT_EQ(NO_ERROR,
+              CoreUtils::sinkMetadataFromHalV7(halValidV7, true /*ignoreNonVendorTags*/, &valid));
+
+    std::vector<record_track_metadata_t> halInvalidSource = {{.source = kInvalidHalSource}};
+    std::vector<record_track_metadata_v7_t> halInvalidSourceV7 = {
+            {.base = {.source = kInvalidHalSource}}};
+    EXPECT_EQ(BAD_VALUE, CoreUtils::sinkMetadataFromHal(halInvalidSource, &invalidSource));
+    EXPECT_EQ(BAD_VALUE,
+              CoreUtils::sinkMetadataFromHalV7(halInvalidSourceV7, false /*ignoreNonVendorTags*/,
+                                               &invalidSource));
+    EXPECT_EQ(BAD_VALUE, CoreUtils::sinkMetadataFromHalV7(
+                                 halInvalidSourceV7, true /*ignoreNonVendorTags*/, &invalidSource));
+    std::vector<record_track_metadata_t> halInvalidDeviceType = {
+            {.dest_device = kInvalidHalDevice}};
+    std::vector<record_track_metadata_v7_t> halInvalidDeviceTypeV7 = {
+            {.base = {.dest_device = kInvalidHalDevice}}};
+    EXPECT_EQ(BAD_VALUE, CoreUtils::sinkMetadataFromHal(halInvalidDeviceType, &invalidDeviceType));
+    EXPECT_EQ(BAD_VALUE,
+              CoreUtils::sinkMetadataFromHalV7(halInvalidDeviceTypeV7,
+                                               false /*ignoreNonVendorTags*/, &invalidDeviceType));
+    EXPECT_EQ(BAD_VALUE,
+              CoreUtils::sinkMetadataFromHalV7(halInvalidDeviceTypeV7, true /*ignoreNonVendorTags*/,
+                                               &invalidDeviceType));
+    std::vector<record_track_metadata_v7_t> halInvalidChannelMaskV7 = {
+            {.channel_mask = kInvalidHalChannelMask}};
+    EXPECT_EQ(BAD_VALUE,
+              CoreUtils::sinkMetadataFromHalV7(halInvalidChannelMaskV7,
+                                               false /*ignoreNonVendorTags*/, &invalidChannelMask));
+    EXPECT_EQ(BAD_VALUE,
+              CoreUtils::sinkMetadataFromHalV7(halInvalidChannelMaskV7,
+                                               true /*ignoreNonVendorTags*/, &invalidChannelMask));
+    std::vector<record_track_metadata_v7_t> halInvalidTagsV7 = {{.tags = "random string"}};
+    EXPECT_EQ(BAD_VALUE, CoreUtils::sinkMetadataFromHalV7(
+                                 halInvalidTagsV7, false /*ignoreNonVendorTags*/, &invalidTags));
+    // Non-vendor tags should be filtered out.
+    EXPECT_EQ(NO_ERROR, CoreUtils::sinkMetadataFromHalV7(
+                                halInvalidTagsV7, true /*ignoreNonVendorTags*/, &invalidTags));
+}
+
+TEST(CoreUtils, ConvertEmptySinkMetadata) {
+    SinkMetadata emptySinkMetadata;
+    std::vector<record_track_metadata_t> halEmptySinkMetadata;
+    EXPECT_EQ(NO_ERROR, CoreUtils::sinkMetadataToHal(emptySinkMetadata, &halEmptySinkMetadata));
+    EXPECT_TRUE(halEmptySinkMetadata.empty());
+    SinkMetadata emptySinkMetadataBack;
+    EXPECT_EQ(NO_ERROR,
+              CoreUtils::sinkMetadataFromHal(halEmptySinkMetadata, &emptySinkMetadataBack));
+    EXPECT_EQ(emptySinkMetadata, emptySinkMetadataBack);
+    std::vector<record_track_metadata_v7_t> halEmptySinkMetadataV7;
+    EXPECT_EQ(NO_ERROR,
+              CoreUtils::sinkMetadataToHalV7(emptySinkMetadata, false /*ignoreNonVendorTags*/,
+                                             &halEmptySinkMetadataV7));
+    EXPECT_TRUE(halEmptySinkMetadataV7.empty());
+    SinkMetadata emptySinkMetadataBackFromV7;
+    EXPECT_EQ(NO_ERROR, CoreUtils::sinkMetadataFromHalV7(halEmptySinkMetadataV7,
+                                                         false /*ignoreNonVendorTags*/,
+                                                         &emptySinkMetadataBackFromV7));
+    EXPECT_EQ(emptySinkMetadata, emptySinkMetadataBackFromV7);
+}
+
+class SinkMetadataConvertTest : public ::testing::TestWithParam<SinkTracks> {};
+
+TEST_P(SinkMetadataConvertTest, ToFromHal) {
+    SinkMetadata sinkMetadata;
+    sinkMetadata.tracks = GetParam();
+    std::vector<record_track_metadata_t> halSinkMetadata;
+    EXPECT_EQ(NO_ERROR, CoreUtils::sinkMetadataToHal(sinkMetadata, &halSinkMetadata));
+    EXPECT_EQ(sinkMetadata.tracks.size(), halSinkMetadata.size());
+    SinkMetadata sinkMetadataBackTrimmed;
+    EXPECT_EQ(NO_ERROR, CoreUtils::sinkMetadataFromHal(halSinkMetadata, &sinkMetadataBackTrimmed));
+    // Can't compare 'sinkMetadata' to 'sinkMetadataBackTrimmed'
+    std::vector<record_track_metadata_v7_t> halSinkMetadataV7;
+    EXPECT_EQ(NO_ERROR, CoreUtils::sinkMetadataToHalV7(sinkMetadata, false /*ignoreNonVendorTags*/,
+                                                       &halSinkMetadataV7));
+    EXPECT_EQ(sinkMetadata.tracks.size(), halSinkMetadataV7.size());
+    SinkMetadata sinkMetadataBackFromV7;
+    EXPECT_EQ(NO_ERROR,
+              CoreUtils::sinkMetadataFromHalV7(halSinkMetadataV7, false /*ignoreNonVendorTags*/,
+                                               &sinkMetadataBackFromV7));
+    EXPECT_EQ(sinkMetadata, sinkMetadataBackFromV7);
+    std::vector<record_track_metadata_v7_t> halSinkMetadataV7FromTrimmed;
+    EXPECT_EQ(NO_ERROR,
+              CoreUtils::sinkMetadataToHalV7(sinkMetadataBackTrimmed, false /*ignoreNonVendorTags*/,
+                                             &halSinkMetadataV7FromTrimmed));
+    EXPECT_EQ(sinkMetadata.tracks.size(), halSinkMetadataV7FromTrimmed.size());
+    SinkMetadata sinkMetadataBackFromV7Trimmed;
+    EXPECT_EQ(NO_ERROR, CoreUtils::sinkMetadataFromHalV7(halSinkMetadataV7FromTrimmed,
+                                                         false /*ignoreNonVendorTags*/,
+                                                         &sinkMetadataBackFromV7Trimmed));
+    EXPECT_EQ(sinkMetadataBackTrimmed, sinkMetadataBackFromV7Trimmed);
+}
+
+INSTANTIATE_TEST_SUITE_P(ValidRecordTrackMetadatas, SinkMetadataConvertTest,
+                         ::testing::Values(SinkTracks{generateMinimalRecordTrackMetadata()},
+                                           SinkTracks{generateValidRecordTrackMetadata()},
+                                           SinkTracks{generateValidRecordTrackMetadataWithDevice()},
+                                           SinkTracks{
+                                                   generateMinimalRecordTrackMetadata(),
+                                                   generateValidRecordTrackMetadata(),
+                                                   generateValidRecordTrackMetadataWithDevice()}));
+
+static PlaybackTrackMetadata generateMinimalPlaybackTrackMetadata() {
+    PlaybackTrackMetadata metadata{};
+    metadata.usage = toString(xsd::AudioUsage::AUDIO_USAGE_UNKNOWN);
+    metadata.contentType = toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_UNKNOWN);
+    metadata.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_NONE);
+    return metadata;
+}
+
+static PlaybackTrackMetadata generateValidPlaybackTrackMetadata() {
+    PlaybackTrackMetadata metadata = generateMinimalPlaybackTrackMetadata();
+    metadata.tags.resize(1);
+    metadata.tags[0] = "VX_GOOGLE_42";
+    metadata.channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO);
+    metadata.gain = 1.0;
+    return metadata;
+}
+
+using SourceTracks = hidl_vec<PlaybackTrackMetadata>;
+
+TEST(CoreUtils, ConvertInvalidSourceMetadata) {
+    SourceMetadata invalidUsage;
+    invalidUsage.tracks = SourceTracks{generateMinimalPlaybackTrackMetadata()};
+    invalidUsage.tracks[0].usage = "random string";
+    EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataToHal(invalidUsage, nullptr));
+    EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataToHalV7(invalidUsage,
+                                                          false /*ignoreNonVendorTags*/, nullptr));
+    SourceMetadata invalidContentType;
+    invalidContentType.tracks = SourceTracks{generateMinimalPlaybackTrackMetadata()};
+    invalidContentType.tracks[0].contentType = "random string";
+    EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataToHal(invalidContentType, nullptr));
+    EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataToHalV7(invalidContentType,
+                                                          false /*ignoreNonVendorTags*/, nullptr));
+    EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataToHalV7(invalidContentType,
+                                                          true /*ignoreNonVendorTags*/, nullptr));
+    SourceMetadata invalidChannelMask;
+    invalidChannelMask.tracks = SourceTracks{generateValidPlaybackTrackMetadata()};
+    invalidChannelMask.tracks[0].channelMask = "random string";
+    // Channel mask is sliced away by 'sourceMetadataToHal'
+    EXPECT_EQ(NO_ERROR, CoreUtils::sourceMetadataToHal(invalidChannelMask, nullptr));
+    EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataToHalV7(invalidChannelMask,
+                                                          false /*ignoreNonVendorTags*/, nullptr));
+    EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataToHalV7(invalidChannelMask,
+                                                          true /*ignoreNonVendorTags*/, nullptr));
+    SourceMetadata invalidTags;
+    invalidTags.tracks = SourceTracks{generateValidPlaybackTrackMetadata()};
+    invalidTags.tracks[0].tags[0] = "random string";
+    // Tags are sliced away by 'sourceMetadataToHal'
+    EXPECT_EQ(NO_ERROR, CoreUtils::sourceMetadataToHal(invalidTags, nullptr));
+    EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataToHalV7(invalidTags,
+                                                          false /*ignoreNonVendorTags*/, nullptr));
+    // Non-vendor tags should be filtered out.
+    EXPECT_EQ(NO_ERROR,
+              CoreUtils::sourceMetadataToHalV7(invalidTags, true /*ignoreNonVendorTags*/, nullptr));
+
+    // Verify that a default-initialized metadata is valid.
+    std::vector<playback_track_metadata_t> halValid(1, playback_track_metadata_t{});
+    std::vector<playback_track_metadata_v7_t> halValidV7(1, playback_track_metadata_v7_t{});
+    SourceMetadata valid;
+    EXPECT_EQ(NO_ERROR, CoreUtils::sourceMetadataFromHal(halValid, &valid));
+    EXPECT_EQ(NO_ERROR, CoreUtils::sourceMetadataFromHalV7(halValidV7,
+                                                           false /*ignoreNonVendorTags*/, &valid));
+    EXPECT_EQ(NO_ERROR,
+              CoreUtils::sourceMetadataFromHalV7(halValidV7, true /*ignoreNonVendorTags*/, &valid));
+
+    std::vector<playback_track_metadata_t> halInvalidUsage = {{.usage = kInvalidHalUsage}};
+    std::vector<playback_track_metadata_v7_t> halInvalidUsageV7 = {
+            {.base = {.usage = kInvalidHalUsage}}};
+    EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataFromHal(halInvalidUsage, &invalidUsage));
+    EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataFromHalV7(
+                                 halInvalidUsageV7, false /*ignoreNonVendorTags*/, &invalidUsage));
+    EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataFromHalV7(
+                                 halInvalidUsageV7, true /*ignoreNonVendorTags*/, &invalidUsage));
+    std::vector<playback_track_metadata_t> halInvalidContentType = {
+            {.content_type = kInvalidHalContentType}};
+    std::vector<playback_track_metadata_v7_t> halInvalidContentTypeV7 = {
+            {.base = {.content_type = kInvalidHalContentType}}};
+    EXPECT_EQ(BAD_VALUE,
+              CoreUtils::sourceMetadataFromHal(halInvalidContentType, &invalidContentType));
+    EXPECT_EQ(BAD_VALUE,
+              CoreUtils::sourceMetadataFromHalV7(
+                      halInvalidContentTypeV7, false /*ignoreNonVendorTags*/, &invalidContentType));
+    EXPECT_EQ(BAD_VALUE,
+              CoreUtils::sourceMetadataFromHalV7(
+                      halInvalidContentTypeV7, true /*ignoreNonVendorTags*/, &invalidContentType));
+    std::vector<playback_track_metadata_v7_t> halInvalidChannelMaskV7 = {
+            {.channel_mask = kInvalidHalChannelMask}};
+    EXPECT_EQ(BAD_VALUE,
+              CoreUtils::sourceMetadataFromHalV7(
+                      halInvalidChannelMaskV7, false /*ignoreNonVendorTags*/, &invalidChannelMask));
+    EXPECT_EQ(BAD_VALUE,
+              CoreUtils::sourceMetadataFromHalV7(
+                      halInvalidChannelMaskV7, true /*ignoreNonVendorTags*/, &invalidChannelMask));
+    std::vector<playback_track_metadata_v7_t> halInvalidTagsV7 = {{.tags = "random string"}};
+    EXPECT_EQ(BAD_VALUE, CoreUtils::sourceMetadataFromHalV7(
+                                 halInvalidTagsV7, false /*ignoreNonVendorTags*/, &invalidTags));
+    // Non-vendor tags should be filtered out.
+    EXPECT_EQ(NO_ERROR, CoreUtils::sourceMetadataFromHalV7(
+                                halInvalidTagsV7, true /*ignoreNonVendorTags*/, &invalidTags));
+}
+
+TEST(CoreUtils, ConvertEmptySourceMetadata) {
+    SourceMetadata emptySourceMetadata;
+    std::vector<playback_track_metadata_t> halEmptySourceMetadata;
+    EXPECT_EQ(NO_ERROR,
+              CoreUtils::sourceMetadataToHal(emptySourceMetadata, &halEmptySourceMetadata));
+    EXPECT_TRUE(halEmptySourceMetadata.empty());
+    SourceMetadata emptySourceMetadataBack;
+    EXPECT_EQ(NO_ERROR,
+              CoreUtils::sourceMetadataFromHal(halEmptySourceMetadata, &emptySourceMetadataBack));
+    EXPECT_EQ(emptySourceMetadata, emptySourceMetadataBack);
+    std::vector<playback_track_metadata_v7_t> halEmptySourceMetadataV7;
+    EXPECT_EQ(NO_ERROR,
+              CoreUtils::sourceMetadataToHalV7(emptySourceMetadata, false /*ignoreNonVendorTags*/,
+                                               &halEmptySourceMetadataV7));
+    EXPECT_TRUE(halEmptySourceMetadataV7.empty());
+    SourceMetadata emptySourceMetadataBackFromV7;
+    EXPECT_EQ(NO_ERROR, CoreUtils::sourceMetadataFromHalV7(halEmptySourceMetadataV7,
+                                                           false /*ignoreNonVendorTags*/,
+                                                           &emptySourceMetadataBackFromV7));
+    EXPECT_EQ(emptySourceMetadata, emptySourceMetadataBackFromV7);
+}
+
+class SourceMetadataConvertTest : public ::testing::TestWithParam<SourceTracks> {};
+
+TEST_P(SourceMetadataConvertTest, ToFromHal) {
+    SourceMetadata sourceMetadata;
+    sourceMetadata.tracks = GetParam();
+    std::vector<playback_track_metadata_t> halSourceMetadata;
+    EXPECT_EQ(NO_ERROR, CoreUtils::sourceMetadataToHal(sourceMetadata, &halSourceMetadata));
+    EXPECT_EQ(sourceMetadata.tracks.size(), halSourceMetadata.size());
+    SourceMetadata sourceMetadataBackTrimmed;
+    EXPECT_EQ(NO_ERROR,
+              CoreUtils::sourceMetadataFromHal(halSourceMetadata, &sourceMetadataBackTrimmed));
+    // Can't compare 'sourceMetadata' to 'sourceMetadataBackTrimmed'
+    std::vector<playback_track_metadata_v7_t> halSourceMetadataV7;
+    EXPECT_EQ(NO_ERROR,
+              CoreUtils::sourceMetadataToHalV7(sourceMetadata, false /*ignoreNonVendorTags*/,
+                                               &halSourceMetadataV7));
+    EXPECT_EQ(sourceMetadata.tracks.size(), halSourceMetadataV7.size());
+    SourceMetadata sourceMetadataBackFromV7;
+    EXPECT_EQ(NO_ERROR,
+              CoreUtils::sourceMetadataFromHalV7(halSourceMetadataV7, false /*ignoreNonVendorTags*/,
+                                                 &sourceMetadataBackFromV7));
+    EXPECT_EQ(sourceMetadata, sourceMetadataBackFromV7);
+    std::vector<playback_track_metadata_v7_t> halSourceMetadataV7FromTrimmed;
+    EXPECT_EQ(NO_ERROR, CoreUtils::sourceMetadataToHalV7(sourceMetadataBackTrimmed,
+                                                         false /*ignoreNonVendorTags*/,
+                                                         &halSourceMetadataV7FromTrimmed));
+    EXPECT_EQ(sourceMetadata.tracks.size(), halSourceMetadataV7FromTrimmed.size());
+    SourceMetadata sourceMetadataBackFromV7Trimmed;
+    EXPECT_EQ(NO_ERROR, CoreUtils::sourceMetadataFromHalV7(halSourceMetadataV7FromTrimmed,
+                                                           false /*ignoreNonVendorTags*/,
+                                                           &sourceMetadataBackFromV7Trimmed));
+    EXPECT_EQ(sourceMetadataBackTrimmed, sourceMetadataBackFromV7Trimmed);
+}
+
+INSTANTIATE_TEST_SUITE_P(ValidPlaybackTrackMetadatas, SourceMetadataConvertTest,
+                         ::testing::Values(SourceTracks{generateMinimalPlaybackTrackMetadata()},
+                                           SourceTracks{generateValidPlaybackTrackMetadata()},
+                                           SourceTracks{generateMinimalPlaybackTrackMetadata(),
+                                                        generateValidPlaybackTrackMetadata()}));
diff --git a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
index 5076dcf..bb7c6d3 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
@@ -336,24 +336,24 @@
     ASSERT_RESULT(okOrNotSupported, stream->updateSourceMetadata(
         {{{toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
                       toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC),
-                      {},
+                      0.1, // gain
                       toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO),
-                      0.1},
+                      {}}, // tags
           {toString(xsd::AudioUsage::AUDIO_USAGE_VOICE_COMMUNICATION),
                       toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_SPEECH),
-                      {}, // tags
+                      1.0,
                       toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO),
-                      1.0},
+                      {}},
           {toString(xsd::AudioUsage::AUDIO_USAGE_ALARM),
                       toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_SONIFICATION),
-                      {}, // tags
+                      0.0,
                       toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO),
-                      0.0},
+                      {}},
           {toString(xsd::AudioUsage::AUDIO_USAGE_ASSISTANT),
                       toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_UNKNOWN),
-                      {},
+                      0.3,
                       toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO),
-                      0.3}}}
+                      {}}}}
     ));
     // clang-format on
     // Set no metadata as if all stream track had stopped
diff --git a/audio/effect/all-versions/default/Android.bp b/audio/effect/all-versions/default/Android.bp
index a0cd612..99b1120 100644
--- a/audio/effect/all-versions/default/Android.bp
+++ b/audio/effect/all-versions/default/Android.bp
@@ -8,7 +8,6 @@
         "AudioBufferManager.cpp",
         "AutomaticGainControlEffect.cpp",
         "BassBoostEffect.cpp",
-        "Conversions.cpp",
         "DownmixEffect.cpp",
         "Effect.cpp",
         "EffectsFactory.cpp",
@@ -51,6 +50,7 @@
         "android.hardware.audio.common@2.0",
         "android.hardware.audio.common@2.0-util",
         "android.hardware.audio.effect@2.0",
+        "android.hardware.audio.effect@2.0-util",
     ],
     cflags: [
         "-DMAJOR_VERSION=2",
@@ -66,6 +66,7 @@
         "android.hardware.audio.common@4.0",
         "android.hardware.audio.common@4.0-util",
         "android.hardware.audio.effect@4.0",
+        "android.hardware.audio.effect@4.0-util",
     ],
     cflags: [
         "-DMAJOR_VERSION=4",
@@ -81,6 +82,7 @@
         "android.hardware.audio.common@5.0",
         "android.hardware.audio.common@5.0-util",
         "android.hardware.audio.effect@5.0",
+        "android.hardware.audio.effect@5.0-util",
     ],
     cflags: [
         "-DMAJOR_VERSION=5",
@@ -96,6 +98,7 @@
         "android.hardware.audio.common@6.0",
         "android.hardware.audio.common@6.0-util",
         "android.hardware.audio.effect@6.0",
+        "android.hardware.audio.effect@6.0-util",
     ],
     cflags: [
         "-DMAJOR_VERSION=6",
@@ -111,6 +114,7 @@
         "android.hardware.audio.common@7.0",
         "android.hardware.audio.common@7.0-util",
         "android.hardware.audio.effect@7.0",
+        "android.hardware.audio.effect@7.0-util",
     ],
     cflags: [
         "-DMAJOR_VERSION=7",
diff --git a/audio/effect/all-versions/default/Conversions.cpp b/audio/effect/all-versions/default/Conversions.cpp
deleted file mode 100644
index 0cc8767..0000000
--- a/audio/effect/all-versions/default/Conversions.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2018 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 "Conversions.h"
-#include "UuidUtils.h"
-
-#include <memory.h>
-#include <stdio.h>
-
-#include <common/all-versions/VersionUtils.h>
-
-using ::android::hardware::audio::common::utils::EnumBitfield;
-
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace CPP_VERSION {
-namespace implementation {
-
-using ::android::hardware::audio::common::CPP_VERSION::implementation::UuidUtils;
-
-void effectDescriptorFromHal(const effect_descriptor_t& halDescriptor,
-                             EffectDescriptor* descriptor) {
-    UuidUtils::uuidFromHal(halDescriptor.type, &descriptor->type);
-    UuidUtils::uuidFromHal(halDescriptor.uuid, &descriptor->uuid);
-    descriptor->flags = EnumBitfield<EffectFlags>(halDescriptor.flags);
-    descriptor->cpuLoad = halDescriptor.cpuLoad;
-    descriptor->memoryUsage = halDescriptor.memoryUsage;
-    memcpy(descriptor->name.data(), halDescriptor.name, descriptor->name.size());
-    memcpy(descriptor->implementor.data(), halDescriptor.implementor,
-           descriptor->implementor.size());
-}
-
-std::string uuidToString(const effect_uuid_t& halUuid) {
-    char str[64];
-    snprintf(str, sizeof(str), "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", halUuid.timeLow,
-             halUuid.timeMid, halUuid.timeHiAndVersion, halUuid.clockSeq, halUuid.node[0],
-             halUuid.node[1], halUuid.node[2], halUuid.node[3], halUuid.node[4], halUuid.node[5]);
-    return str;
-}
-
-}  // namespace implementation
-}  // namespace CPP_VERSION
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
diff --git a/audio/effect/all-versions/default/Conversions.h b/audio/effect/all-versions/default/Conversions.h
deleted file mode 100644
index 75aab24..0000000
--- a/audio/effect/all-versions/default/Conversions.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2018 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_AUDIO_EFFECT_CONVERSIONS_H_
-#define ANDROID_HARDWARE_AUDIO_EFFECT_CONVERSIONS_H_
-
-#include PATH(android/hardware/audio/effect/FILE_VERSION/types.h)
-
-#include <string>
-
-#include <system/audio_effect.h>
-
-namespace android {
-namespace hardware {
-namespace audio {
-namespace effect {
-namespace CPP_VERSION {
-namespace implementation {
-
-using ::android::hardware::audio::effect::CPP_VERSION::EffectDescriptor;
-
-void effectDescriptorFromHal(const effect_descriptor_t& halDescriptor,
-                             EffectDescriptor* descriptor);
-std::string uuidToString(const effect_uuid_t& halUuid);
-
-}  // namespace implementation
-}  // namespace CPP_VERSION
-}  // namespace effect
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_CONVERSIONS_H_
diff --git a/audio/effect/all-versions/default/Effect.cpp b/audio/effect/all-versions/default/Effect.cpp
index 58f1779..ccfc6b2 100644
--- a/audio/effect/all-versions/default/Effect.cpp
+++ b/audio/effect/all-versions/default/Effect.cpp
@@ -19,7 +19,6 @@
 #define LOG_TAG "EffectHAL"
 #define ATRACE_TAG ATRACE_TAG_AUDIO
 
-#include "Conversions.h"
 #include "Effect.h"
 #include "common/all-versions/default/EffectMap.h"
 
@@ -30,6 +29,7 @@
 #include <HidlUtils.h>
 #include <android/log.h>
 #include <media/EffectsFactoryApi.h>
+#include <util/EffectUtils.h>
 #include <utils/Trace.h>
 
 #include "VersionUtils.h"
@@ -202,34 +202,6 @@
     halConfig->aux_channels = static_cast<audio_channel_mask_t>(config.auxChannels);
 }
 
-void Effect::effectBufferConfigFromHal(const buffer_config_t& halConfig,
-                                       EffectBufferConfig* config) {
-    config->buffer.id = 0;
-    config->buffer.frameCount = 0;
-    config->samplingRateHz = halConfig.samplingRate;
-    config->channels = AudioChannelBitfield(halConfig.channels);
-    config->format = AudioFormat(halConfig.format);
-    config->accessMode = EffectBufferAccess(halConfig.accessMode);
-    config->mask = static_cast<decltype(config->mask)>(halConfig.mask);
-}
-
-// static
-void Effect::effectBufferConfigToHal(const EffectBufferConfig& config, buffer_config_t* halConfig) {
-    // Note: setting the buffers directly is considered obsolete. They need to be set
-    // using 'setProcessBuffers'.
-    halConfig->buffer.frameCount = 0;
-    halConfig->buffer.raw = NULL;
-    halConfig->samplingRate = config.samplingRateHz;
-    halConfig->channels = static_cast<uint32_t>(config.channels);
-    // Note: The framework code does not use BP.
-    halConfig->bufferProvider.cookie = NULL;
-    halConfig->bufferProvider.getBuffer = NULL;
-    halConfig->bufferProvider.releaseBuffer = NULL;
-    halConfig->format = static_cast<uint8_t>(config.format);
-    halConfig->accessMode = static_cast<uint8_t>(config.accessMode);
-    halConfig->mask = static_cast<uint8_t>(config.mask);
-}
-
 #else  // MAJOR_VERSION <= 6
 
 void Effect::effectAuxChannelsConfigFromHal(const channel_config_t& halConfig,
@@ -247,68 +219,8 @@
     (void)HidlUtils::audioChannelMaskToHal(config.auxChannels, &halConfig->aux_channels);
 }
 
-void Effect::effectBufferConfigFromHal(const buffer_config_t& halConfig,
-                                       EffectBufferConfig* config) {
-    config->buffer.unspecified();
-    audio_config_base_t halConfigBase = {halConfig.samplingRate,
-                                         static_cast<audio_channel_mask_t>(halConfig.channels),
-                                         static_cast<audio_format_t>(halConfig.format)};
-    (void)HidlUtils::audioConfigBaseOptionalFromHal(
-            halConfigBase, mIsInput, halConfig.mask & EFFECT_CONFIG_FORMAT,
-            halConfig.mask & EFFECT_CONFIG_SMP_RATE, halConfig.mask & EFFECT_CONFIG_CHANNELS,
-            &config->base);
-    if (halConfig.mask & EFFECT_CONFIG_ACC_MODE) {
-        config->accessMode.value(EffectBufferAccess(halConfig.accessMode));
-    }
-}
-
-// static
-void Effect::effectBufferConfigToHal(const EffectBufferConfig& config, buffer_config_t* halConfig) {
-    // Note: setting the buffers directly is considered obsolete. They need to be set
-    // using 'setProcessBuffers'.
-    halConfig->buffer.frameCount = 0;
-    halConfig->buffer.raw = nullptr;
-    audio_config_base_t halConfigBase = AUDIO_CONFIG_BASE_INITIALIZER;
-    bool formatSpecified = false, sRateSpecified = false, channelMaskSpecified = false;
-    (void)HidlUtils::audioConfigBaseOptionalToHal(config.base, &halConfigBase, &formatSpecified,
-                                                  &sRateSpecified, &channelMaskSpecified);
-    halConfig->mask = 0;
-    if (sRateSpecified) {
-        halConfig->mask |= EFFECT_CONFIG_SMP_RATE;
-        halConfig->samplingRate = halConfigBase.sample_rate;
-    }
-    if (channelMaskSpecified) {
-        halConfig->mask |= EFFECT_CONFIG_CHANNELS;
-        halConfig->channels = halConfigBase.channel_mask;
-    }
-    if (formatSpecified) {
-        halConfig->mask |= EFFECT_CONFIG_FORMAT;
-        halConfig->format = halConfigBase.format;
-    }
-    // Note: The framework code does not use BP.
-    halConfig->bufferProvider.cookie = nullptr;
-    halConfig->bufferProvider.getBuffer = nullptr;
-    halConfig->bufferProvider.releaseBuffer = nullptr;
-    if (config.accessMode.getDiscriminator() ==
-        EffectBufferConfig::OptionalAccessMode::hidl_discriminator::value) {
-        halConfig->mask |= EFFECT_CONFIG_ACC_MODE;
-        halConfig->accessMode = static_cast<uint8_t>(config.accessMode.value());
-    }
-}
-
 #endif  // MAJOR_VERSION <= 6
 
-void Effect::effectConfigFromHal(const effect_config_t& halConfig, EffectConfig* config) {
-    effectBufferConfigFromHal(halConfig.inputCfg, &config->inputCfg);
-    effectBufferConfigFromHal(halConfig.outputCfg, &config->outputCfg);
-}
-
-// static
-void Effect::effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig) {
-    effectBufferConfigToHal(config.inputCfg, &halConfig->inputCfg);
-    effectBufferConfigToHal(config.outputCfg, &halConfig->outputCfg);
-}
-
 // static
 void Effect::effectOffloadParamToHal(const EffectOffloadParameter& offload,
                                      effect_offload_param_t* halOffload) {
@@ -373,7 +285,7 @@
         (*mHandle)->command(mHandle, commandCode, 0, NULL, &halResultSize, &halConfig);
     EffectConfig config;
     if (status == OK) {
-        effectConfigFromHal(halConfig, &config);
+        status = EffectUtils::effectConfigFromHal(halConfig, mIsInput, &config);
     }
     cb(analyzeCommandStatus(commandName, sContextCallToCommand, status), config);
 }
@@ -538,7 +450,7 @@
                              const sp<IEffectBufferProviderCallback>& inputBufferProvider,
                              const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
     effect_config_t halConfig;
-    effectConfigToHal(config, &halConfig);
+    EffectUtils::effectConfigToHal(config, &halConfig);
     if (inputBufferProvider != 0) {
         LOG_FATAL("Using input buffer provider is not supported");
     }
@@ -733,7 +645,7 @@
     status_t status = (*mHandle)->get_descriptor(mHandle, &halDescriptor);
     EffectDescriptor descriptor;
     if (status == OK) {
-        effectDescriptorFromHal(halDescriptor, &descriptor);
+        status = EffectUtils::effectDescriptorFromHal(halDescriptor, &descriptor);
     }
     _hidl_cb(analyzeStatus("get_descriptor", "", sContextCallFunction, status), descriptor);
     return Void();
diff --git a/audio/effect/all-versions/default/Effect.h b/audio/effect/all-versions/default/Effect.h
index 9aa47ea..d5218f7 100644
--- a/audio/effect/all-versions/default/Effect.h
+++ b/audio/effect/all-versions/default/Effect.h
@@ -203,11 +203,6 @@
                                         EffectAuxChannelsConfig* config);
     static void effectAuxChannelsConfigToHal(const EffectAuxChannelsConfig& config,
                                              channel_config_t* halConfig);
-    void effectBufferConfigFromHal(const buffer_config_t& halConfig, EffectBufferConfig* config);
-    static void effectBufferConfigToHal(const EffectBufferConfig& config,
-                                        buffer_config_t* halConfig);
-    void effectConfigFromHal(const effect_config_t& halConfig, EffectConfig* config);
-    static void effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig);
     static void effectOffloadParamToHal(const EffectOffloadParameter& offload,
                                         effect_offload_param_t* halOffload);
     static std::vector<uint8_t> parameterToHal(uint32_t paramSize, const void* paramData,
diff --git a/audio/effect/all-versions/default/EffectsFactory.cpp b/audio/effect/all-versions/default/EffectsFactory.cpp
index 1ea990b..eb1cb49 100644
--- a/audio/effect/all-versions/default/EffectsFactory.cpp
+++ b/audio/effect/all-versions/default/EffectsFactory.cpp
@@ -19,7 +19,6 @@
 #include "AcousticEchoCancelerEffect.h"
 #include "AutomaticGainControlEffect.h"
 #include "BassBoostEffect.h"
-#include "Conversions.h"
 #include "DownmixEffect.h"
 #include "Effect.h"
 #include "EnvironmentalReverbEffect.h"
@@ -27,11 +26,11 @@
 #include "LoudnessEnhancerEffect.h"
 #include "NoiseSuppressionEffect.h"
 #include "PresetReverbEffect.h"
-#include "UuidUtils.h"
 #include "VirtualizerEffect.h"
 #include "VisualizerEffect.h"
 #include "common/all-versions/default/EffectMap.h"
 
+#include <UuidUtils.h>
 #include <android/log.h>
 #include <media/EffectsFactoryApi.h>
 #include <system/audio_effects/effect_aec.h>
@@ -45,6 +44,7 @@
 #include <system/audio_effects/effect_presetreverb.h>
 #include <system/audio_effects/effect_virtualizer.h>
 #include <system/audio_effects/effect_visualizer.h>
+#include <util/EffectUtils.h>
 
 namespace android {
 namespace hardware {
@@ -107,7 +107,7 @@
         effect_descriptor_t halDescriptor;
         status = EffectQueryEffect(i, &halDescriptor);
         if (status == OK) {
-            effectDescriptorFromHal(halDescriptor, &result[i]);
+            EffectUtils::effectDescriptorFromHal(halDescriptor, &result[i]);
         } else {
             ALOGE("Error querying effect at position %d / %d: %s", i, numEffects,
                   strerror(-status));
@@ -141,11 +141,11 @@
     effect_descriptor_t halDescriptor;
     status_t status = EffectGetDescriptor(&halUuid, &halDescriptor);
     EffectDescriptor descriptor;
-    effectDescriptorFromHal(halDescriptor, &descriptor);
+    EffectUtils::effectDescriptorFromHal(halDescriptor, &descriptor);
     Result retval(Result::OK);
     if (status != OK) {
-        ALOGE("Error querying effect descriptor for %s: %s", uuidToString(halUuid).c_str(),
-              strerror(-status));
+        ALOGE("Error querying effect descriptor for %s: %s",
+              UuidUtils::uuidToString(halUuid).c_str(), strerror(-status));
         if (status == -ENOENT) {
             retval = Result::INVALID_ARGUMENTS;
         } else {
@@ -191,13 +191,14 @@
             effect = dispatchEffectInstanceCreation(halDescriptor, handle);
             effectId = EffectMap::getInstance().add(handle);
         } else {
-            ALOGE("Error querying effect descriptor for %s: %s", uuidToString(halUuid).c_str(),
-                  strerror(-status));
+            ALOGE("Error querying effect descriptor for %s: %s",
+                  UuidUtils::uuidToString(halUuid).c_str(), strerror(-status));
             EffectRelease(handle);
         }
     }
     if (status != OK) {
-        ALOGE("Error creating effect %s: %s", uuidToString(halUuid).c_str(), strerror(-status));
+        ALOGE("Error creating effect %s: %s", UuidUtils::uuidToString(halUuid).c_str(),
+              strerror(-status));
         if (status == -ENOENT) {
             retval = Result::INVALID_ARGUMENTS;
         } else {
diff --git a/audio/effect/all-versions/default/TEST_MAPPING b/audio/effect/all-versions/default/TEST_MAPPING
new file mode 100644
index 0000000..b66e4e4
--- /dev/null
+++ b/audio/effect/all-versions/default/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "android.hardware.audio.effect@7.0-util_tests"
+    }
+  ]
+}
diff --git a/audio/effect/all-versions/default/util/Android.bp b/audio/effect/all-versions/default/util/Android.bp
new file mode 100644
index 0000000..5ba19d3
--- /dev/null
+++ b/audio/effect/all-versions/default/util/Android.bp
@@ -0,0 +1,136 @@
+cc_defaults {
+    name: "android.hardware.audio.effect-util_default",
+    defaults: ["hidl_defaults"],
+
+    vendor_available: true,
+
+    export_include_dirs: ["include"],
+
+    srcs: [
+        "EffectUtils.cpp",
+    ],
+
+    shared_libs: [
+        "liblog",
+        "libutils",
+        "libhidlbase",
+        "android.hardware.audio.common-util",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.audio.common-util",
+    ],
+
+    header_libs: [
+        "libaudio_system_headers",
+        "libhardware_headers",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.audio.effect@2.0-util",
+    defaults: ["android.hardware.audio.effect-util_default"],
+    shared_libs: [
+        "android.hardware.audio.common@2.0",
+        "android.hardware.audio.common@2.0-util",
+        "android.hardware.audio.effect@2.0",
+    ],
+    cflags: [
+        "-DMAJOR_VERSION=2",
+        "-DMINOR_VERSION=0",
+        "-include common/all-versions/VersionMacro.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.audio.effect@4.0-util",
+    defaults: ["android.hardware.audio.effect-util_default"],
+    shared_libs: [
+        "android.hardware.audio.common@4.0",
+        "android.hardware.audio.common@4.0-util",
+        "android.hardware.audio.effect@4.0",
+    ],
+    cflags: [
+        "-DMAJOR_VERSION=4",
+        "-DMINOR_VERSION=0",
+        "-include common/all-versions/VersionMacro.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.audio.effect@5.0-util",
+    defaults: ["android.hardware.audio.effect-util_default"],
+    shared_libs: [
+        "android.hardware.audio.common@5.0",
+        "android.hardware.audio.common@5.0-util",
+        "android.hardware.audio.effect@5.0",
+    ],
+    cflags: [
+        "-DMAJOR_VERSION=5",
+        "-DMINOR_VERSION=0",
+        "-include common/all-versions/VersionMacro.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.audio.effect@6.0-util",
+    defaults: ["android.hardware.audio.effect-util_default"],
+    shared_libs: [
+        "android.hardware.audio.common@6.0",
+        "android.hardware.audio.common@6.0-util",
+        "android.hardware.audio.effect@6.0",
+    ],
+    cflags: [
+        "-DMAJOR_VERSION=6",
+        "-DMINOR_VERSION=0",
+        "-include common/all-versions/VersionMacro.h",
+    ],
+}
+
+cc_library {
+    name: "android.hardware.audio.effect@7.0-util",
+    defaults: ["android.hardware.audio.effect-util_default"],
+    shared_libs: [
+        "android.hardware.audio.common@7.0",
+        "android.hardware.audio.common@7.0-util",
+        "android.hardware.audio.effect@7.0",
+    ],
+    cflags: [
+        "-DMAJOR_VERSION=7",
+        "-DMINOR_VERSION=0",
+        "-include common/all-versions/VersionMacro.h",
+    ],
+}
+
+// Note: this isn't a VTS test, but rather a unit test
+// to verify correctness of conversion utilities.
+cc_test {
+    name: "android.hardware.audio.effect@7.0-util_tests",
+    defaults: ["android.hardware.audio.effect-util_default"],
+
+    srcs: ["tests/effectutils_tests.cpp"],
+
+    // Use static linking to allow running in presubmit on
+    // targets that don't have HAL V7.
+    static_libs: [
+        "android.hardware.audio.common@7.0",
+        "android.hardware.audio.common@7.0-enums",
+        "android.hardware.audio.common@7.0-util",
+        "android.hardware.audio.effect@7.0",
+        "android.hardware.audio.effect@7.0-util",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libxml2",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+        "-DMAJOR_VERSION=7",
+        "-DMINOR_VERSION=0",
+        "-include common/all-versions/VersionMacro.h",
+    ],
+
+    test_suites: ["device-tests"],
+}
diff --git a/audio/effect/all-versions/default/util/EffectUtils.cpp b/audio/effect/all-versions/default/util/EffectUtils.cpp
new file mode 100644
index 0000000..1c0419a
--- /dev/null
+++ b/audio/effect/all-versions/default/util/EffectUtils.cpp
@@ -0,0 +1,183 @@
+/*
+ * 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 <memory.h>
+
+#include <HidlUtils.h>
+#include <UuidUtils.h>
+#include <common/all-versions/VersionUtils.h>
+
+#include "util/EffectUtils.h"
+
+using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::common::CPP_VERSION::implementation::UuidUtils;
+using ::android::hardware::audio::common::utils::EnumBitfield;
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace CPP_VERSION {
+namespace implementation {
+
+using namespace ::android::hardware::audio::common::CPP_VERSION;
+
+#define CONVERT_CHECKED(expr, result)                   \
+    if (status_t status = (expr); status != NO_ERROR) { \
+        result = status;                                \
+    }
+
+#if MAJOR_VERSION <= 6
+
+status_t EffectUtils::effectBufferConfigFromHal(const buffer_config_t& halConfig, bool /*isInput*/,
+                                                EffectBufferConfig* config) {
+    config->buffer.id = 0;
+    config->buffer.frameCount = 0;
+    config->samplingRateHz = halConfig.samplingRate;
+    config->channels = EnumBitfield<AudioChannelMask>(halConfig.channels);
+    config->format = AudioFormat(halConfig.format);
+    config->accessMode = EffectBufferAccess(halConfig.accessMode);
+    config->mask = EnumBitfield<EffectConfigParameters>(halConfig.mask);
+    return NO_ERROR;
+}
+
+status_t EffectUtils::effectBufferConfigToHal(const EffectBufferConfig& config,
+                                              buffer_config_t* halConfig) {
+    // Note: setting the buffers directly is considered obsolete. They need to be set
+    // using 'setProcessBuffers'.
+    halConfig->buffer.frameCount = 0;
+    halConfig->buffer.raw = nullptr;
+    halConfig->samplingRate = config.samplingRateHz;
+    halConfig->channels = static_cast<uint32_t>(config.channels);
+    // Note: The framework code does not use BP.
+    halConfig->bufferProvider.cookie = nullptr;
+    halConfig->bufferProvider.getBuffer = nullptr;
+    halConfig->bufferProvider.releaseBuffer = nullptr;
+    halConfig->format = static_cast<uint8_t>(config.format);
+    halConfig->accessMode = static_cast<uint8_t>(config.accessMode);
+    halConfig->mask = static_cast<uint8_t>(config.mask);
+    return NO_ERROR;
+}
+
+#else
+
+status_t EffectUtils::effectBufferConfigFromHal(const buffer_config_t& halConfig, bool isInput,
+                                                EffectBufferConfig* config) {
+    status_t result = NO_ERROR;
+    config->buffer.unspecified();
+    audio_config_base_t halConfigBase = {halConfig.samplingRate,
+                                         static_cast<audio_channel_mask_t>(halConfig.channels),
+                                         static_cast<audio_format_t>(halConfig.format)};
+    CONVERT_CHECKED(HidlUtils::audioConfigBaseOptionalFromHal(
+                            halConfigBase, isInput, halConfig.mask & EFFECT_CONFIG_FORMAT,
+                            halConfig.mask & EFFECT_CONFIG_SMP_RATE,
+                            halConfig.mask & EFFECT_CONFIG_CHANNELS, &config->base),
+                    result);
+    if (halConfig.mask & EFFECT_CONFIG_ACC_MODE) {
+        config->accessMode.value(EffectBufferAccess(halConfig.accessMode));
+    }
+    return result;
+}
+
+status_t EffectUtils::effectBufferConfigToHal(const EffectBufferConfig& config,
+                                              buffer_config_t* halConfig) {
+    status_t result = NO_ERROR;
+    // Note: setting the buffers directly is considered obsolete. They need to be set
+    // using 'setProcessBuffers'.
+    halConfig->buffer.frameCount = 0;
+    halConfig->buffer.raw = nullptr;
+    audio_config_base_t halConfigBase = AUDIO_CONFIG_BASE_INITIALIZER;
+    bool formatSpecified = false, sRateSpecified = false, channelMaskSpecified = false;
+    CONVERT_CHECKED(
+            HidlUtils::audioConfigBaseOptionalToHal(config.base, &halConfigBase, &formatSpecified,
+                                                    &sRateSpecified, &channelMaskSpecified),
+            result);
+    halConfig->mask = 0;
+    if (sRateSpecified) {
+        halConfig->mask |= EFFECT_CONFIG_SMP_RATE;
+        halConfig->samplingRate = halConfigBase.sample_rate;
+    }
+    if (channelMaskSpecified) {
+        halConfig->mask |= EFFECT_CONFIG_CHANNELS;
+        halConfig->channels = halConfigBase.channel_mask;
+    }
+    if (formatSpecified) {
+        halConfig->mask |= EFFECT_CONFIG_FORMAT;
+        halConfig->format = halConfigBase.format;
+    }
+    // Note: The framework code does not use BP.
+    halConfig->bufferProvider.cookie = nullptr;
+    halConfig->bufferProvider.getBuffer = nullptr;
+    halConfig->bufferProvider.releaseBuffer = nullptr;
+    if (config.accessMode.getDiscriminator() ==
+        EffectBufferConfig::OptionalAccessMode::hidl_discriminator::value) {
+        halConfig->mask |= EFFECT_CONFIG_ACC_MODE;
+        halConfig->accessMode = static_cast<uint8_t>(config.accessMode.value());
+    }
+    return result;
+}
+
+#endif  // MAJOR_VERSION >= 6
+
+status_t EffectUtils::effectConfigFromHal(const effect_config_t& halConfig, bool isInput,
+                                          EffectConfig* config) {
+    status_t result = NO_ERROR;
+    CONVERT_CHECKED(effectBufferConfigFromHal(halConfig.inputCfg, isInput, &config->inputCfg),
+                    result);
+    CONVERT_CHECKED(effectBufferConfigFromHal(halConfig.outputCfg, isInput, &config->outputCfg),
+                    result);
+    return result;
+}
+
+status_t EffectUtils::effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig) {
+    status_t result = NO_ERROR;
+    CONVERT_CHECKED(effectBufferConfigToHal(config.inputCfg, &halConfig->inputCfg), result);
+    CONVERT_CHECKED(effectBufferConfigToHal(config.outputCfg, &halConfig->outputCfg), result);
+    return result;
+}
+
+status_t EffectUtils::effectDescriptorFromHal(const effect_descriptor_t& halDescriptor,
+                                              EffectDescriptor* descriptor) {
+    UuidUtils::uuidFromHal(halDescriptor.type, &descriptor->type);
+    UuidUtils::uuidFromHal(halDescriptor.uuid, &descriptor->uuid);
+    descriptor->flags = EnumBitfield<EffectFlags>(halDescriptor.flags);
+    descriptor->cpuLoad = halDescriptor.cpuLoad;
+    descriptor->memoryUsage = halDescriptor.memoryUsage;
+    memcpy(descriptor->name.data(), halDescriptor.name, descriptor->name.size());
+    memcpy(descriptor->implementor.data(), halDescriptor.implementor,
+           descriptor->implementor.size());
+    return NO_ERROR;
+}
+
+status_t EffectUtils::effectDescriptorToHal(const EffectDescriptor& descriptor,
+                                            effect_descriptor_t* halDescriptor) {
+    UuidUtils::uuidToHal(descriptor.type, &halDescriptor->type);
+    UuidUtils::uuidToHal(descriptor.uuid, &halDescriptor->uuid);
+    halDescriptor->flags = static_cast<uint32_t>(descriptor.flags);
+    halDescriptor->cpuLoad = descriptor.cpuLoad;
+    halDescriptor->memoryUsage = descriptor.memoryUsage;
+    memcpy(halDescriptor->name, descriptor.name.data(), descriptor.name.size());
+    memcpy(halDescriptor->implementor, descriptor.implementor.data(),
+           descriptor.implementor.size());
+    return NO_ERROR;
+}
+
+}  // namespace implementation
+}  // namespace CPP_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/util/include/util/EffectUtils.h b/audio/effect/all-versions/default/util/include/util/EffectUtils.h
new file mode 100644
index 0000000..23963b4
--- /dev/null
+++ b/audio/effect/all-versions/default/util/include/util/EffectUtils.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.
+ */
+
+#pragma once
+
+// clang-format off
+#include PATH(android/hardware/audio/effect/FILE_VERSION/types.h)
+// clang-format on
+
+#include <system/audio_effect.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace CPP_VERSION {
+namespace implementation {
+
+using namespace ::android::hardware::audio::effect::CPP_VERSION;
+
+struct EffectUtils {
+    static status_t effectBufferConfigFromHal(const buffer_config_t& halConfig, bool isInput,
+                                              EffectBufferConfig* config);
+    static status_t effectBufferConfigToHal(const EffectBufferConfig& config,
+                                            buffer_config_t* halConfig);
+    static status_t effectConfigFromHal(const effect_config_t& halConfig, bool isInput,
+                                        EffectConfig* config);
+    static status_t effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig);
+    static status_t effectDescriptorFromHal(const effect_descriptor_t& halDescriptor,
+                                            EffectDescriptor* descriptor);
+    static status_t effectDescriptorToHal(const EffectDescriptor& descriptor,
+                                          effect_descriptor_t* halDescriptor);
+};
+
+}  // namespace implementation
+}  // namespace CPP_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/all-versions/default/util/tests/effectutils_tests.cpp b/audio/effect/all-versions/default/util/tests/effectutils_tests.cpp
new file mode 100644
index 0000000..7eb8cd2
--- /dev/null
+++ b/audio/effect/all-versions/default/util/tests/effectutils_tests.cpp
@@ -0,0 +1,144 @@
+/*
+ * 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 <string>
+
+#include <gtest/gtest.h>
+
+#define LOG_TAG "EffectUtils_Test"
+#include <log/log.h>
+
+#include <android_audio_policy_configuration_V7_0-enums.h>
+#include <system/audio_effect.h>
+#include <util/EffectUtils.h>
+#include <xsdc/XsdcSupport.h>
+
+using namespace android;
+using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::effect::CPP_VERSION;
+using ::android::hardware::audio::effect::CPP_VERSION::implementation::EffectUtils;
+namespace xsd {
+using namespace ::android::audio::policy::configuration::V7_0;
+}
+
+static constexpr audio_channel_mask_t kInvalidHalChannelMask = AUDIO_CHANNEL_INVALID;
+static constexpr audio_format_t kInvalidHalFormat = AUDIO_FORMAT_INVALID;
+
+// Not generated automatically because AudioBuffer contains
+// instances of hidl_memory which can't be compared properly
+// in general case due to presence of handles.
+//
+// However, in this particular case, handles must not present
+// thus comparison is possible.
+//
+// operator== must be defined in the same namespace as the structures.
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace CPP_VERSION {
+inline bool operator==(const AudioBuffer& lhs, const AudioBuffer& rhs) {
+    return lhs.id == rhs.id && lhs.frameCount == rhs.frameCount && lhs.data.handle() == nullptr &&
+           rhs.data.handle() == nullptr;
+}
+
+inline bool operator==(const EffectBufferConfig& lhs, const EffectBufferConfig& rhs) {
+    return lhs.buffer.getDiscriminator() == rhs.buffer.getDiscriminator() &&
+           (lhs.buffer.getDiscriminator() ==
+                    EffectBufferConfig::OptionalBuffer::hidl_discriminator::unspecified ||
+            lhs.buffer.buf() == rhs.buffer.buf()) &&
+           lhs.base == rhs.base && lhs.accessMode == rhs.accessMode;
+}
+
+inline bool operator==(const EffectConfig& lhs, const EffectConfig& rhs) {
+    return lhs.inputCfg == rhs.inputCfg && lhs.outputCfg == rhs.outputCfg;
+}
+}  // namespace CPP_VERSION
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+TEST(EffectUtils, ConvertInvalidBufferConfig) {
+    buffer_config_t halInvalid;
+    EffectBufferConfig invalidChannelMask;
+    invalidChannelMask.base.channelMask.value("random string");
+    EXPECT_EQ(BAD_VALUE, EffectUtils::effectBufferConfigToHal(invalidChannelMask, &halInvalid));
+    EffectBufferConfig invalidFormat;
+    invalidFormat.base.format.value("random string");
+    EXPECT_EQ(BAD_VALUE, EffectUtils::effectBufferConfigToHal(invalidFormat, &halInvalid));
+
+    buffer_config_t halInvalidChannelMask;
+    EffectBufferConfig invalid;
+    halInvalidChannelMask.channels = kInvalidHalChannelMask;
+    halInvalidChannelMask.mask = EFFECT_CONFIG_CHANNELS;
+    EXPECT_EQ(BAD_VALUE, EffectUtils::effectBufferConfigFromHal(halInvalidChannelMask,
+                                                                false /*isInput*/, &invalid));
+    EXPECT_EQ(BAD_VALUE, EffectUtils::effectBufferConfigFromHal(halInvalidChannelMask,
+                                                                true /*isInput*/, &invalid));
+    buffer_config_t halInvalidFormat;
+    halInvalidFormat.format = (uint8_t)kInvalidHalFormat;
+    halInvalidFormat.mask = EFFECT_CONFIG_FORMAT;
+    EXPECT_EQ(BAD_VALUE, EffectUtils::effectBufferConfigFromHal(halInvalidFormat, false /*isInput*/,
+                                                                &invalid));
+    EXPECT_EQ(BAD_VALUE,
+              EffectUtils::effectBufferConfigFromHal(halInvalidFormat, true /*isInput*/, &invalid));
+}
+
+TEST(EffectUtils, ConvertBufferConfig) {
+    EffectBufferConfig empty;
+    buffer_config_t halEmpty;
+    EXPECT_EQ(NO_ERROR, EffectUtils::effectBufferConfigToHal(empty, &halEmpty));
+    EffectBufferConfig emptyBackOut;
+    EXPECT_EQ(NO_ERROR,
+              EffectUtils::effectBufferConfigFromHal(halEmpty, false /*isInput*/, &emptyBackOut));
+    EXPECT_EQ(empty, emptyBackOut);
+    EffectBufferConfig emptyBackIn;
+    EXPECT_EQ(NO_ERROR,
+              EffectUtils::effectBufferConfigFromHal(halEmpty, true /*isInput*/, &emptyBackIn));
+    EXPECT_EQ(empty, emptyBackIn);
+
+    EffectBufferConfig chanMask;
+    chanMask.base.channelMask.value(toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO));
+    buffer_config_t halChanMask;
+    EXPECT_EQ(NO_ERROR, EffectUtils::effectBufferConfigToHal(chanMask, &halChanMask));
+    EffectBufferConfig chanMaskBack;
+    EXPECT_EQ(NO_ERROR, EffectUtils::effectBufferConfigFromHal(halChanMask, false /*isInput*/,
+                                                               &chanMaskBack));
+    EXPECT_EQ(chanMask, chanMaskBack);
+
+    EffectBufferConfig format;
+    format.base.format.value(toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT));
+    buffer_config_t halFormat;
+    EXPECT_EQ(NO_ERROR, EffectUtils::effectBufferConfigToHal(format, &halFormat));
+    EffectBufferConfig formatBackOut;
+    EXPECT_EQ(NO_ERROR,
+              EffectUtils::effectBufferConfigFromHal(halFormat, false /*isInput*/, &formatBackOut));
+    EXPECT_EQ(format, formatBackOut);
+    EffectBufferConfig formatBackIn;
+    EXPECT_EQ(NO_ERROR,
+              EffectUtils::effectBufferConfigFromHal(halFormat, true /*isInput*/, &formatBackIn));
+    EXPECT_EQ(format, formatBackIn);
+}
+
+TEST(EffectUtils, ConvertDescriptor) {
+    EffectDescriptor desc{};
+    effect_descriptor_t halDesc;
+    EXPECT_EQ(NO_ERROR, EffectUtils::effectDescriptorToHal(desc, &halDesc));
+    EffectDescriptor descBack;
+    EXPECT_EQ(NO_ERROR, EffectUtils::effectDescriptorFromHal(halDesc, &descBack));
+    EXPECT_EQ(desc, descBack);
+}
diff --git a/camera/provider/2.4/default/service.cpp b/camera/provider/2.4/default/service.cpp
index 84f4839..0a4f787 100644
--- a/camera/provider/2.4/default/service.cpp
+++ b/camera/provider/2.4/default/service.cpp
@@ -22,9 +22,9 @@
 
 #include <android/hardware/camera/provider/2.4/ICameraProvider.h>
 #include <binder/ProcessState.h>
-#include <cutils/memory.h>
 #include <cutils/properties.h>
 #include <hidl/LegacySupport.h>
+#include <malloc.h>
 
 using android::status_t;
 using android::hardware::defaultLazyPassthroughServiceImplementation;
@@ -46,7 +46,13 @@
 
     // b/166675194
     if (property_get_bool("ro.vendor.camera.provider24.disable_mem_init", false)) {
-        process_disable_memory_mitigations();
+        if (mallopt(M_BIONIC_ZERO_INIT, 0) == 0) {
+            // Note - heap initialization is only present on devices with Scudo.
+            // Devices with jemalloc don't have heap-init, and thus the mallopt
+            // will fail. On these devices, you probably just want to remove the
+            // property.
+            ALOGE("Disabling heap initialization failed.");
+        }
     }
 
     status_t status;
diff --git a/cas/1.0/default/Android.bp b/cas/1.0/default/Android.bp
index f9977ff..70f4371 100644
--- a/cas/1.0/default/Android.bp
+++ b/cas/1.0/default/Android.bp
@@ -12,7 +12,7 @@
       "TypeConvert.cpp",
     ],
 
-    compile_multilib: "32",
+    compile_multilib: "prefer32",
 
     shared_libs: [
       "android.hardware.cas@1.0",
diff --git a/cas/1.0/default/FactoryLoader.h b/cas/1.0/default/FactoryLoader.h
index 18c2186..45e515a 100644
--- a/cas/1.0/default/FactoryLoader.h
+++ b/cas/1.0/default/FactoryLoader.h
@@ -92,7 +92,12 @@
     }
 
     // no luck, have to search
+#ifdef __LP64__
+    String8 dirPath("/vendor/lib64/mediacas");
+#else
     String8 dirPath("/vendor/lib/mediacas");
+#endif
+
     DIR* pDir = opendir(dirPath.string());
 
     if (pDir == NULL) {
@@ -127,7 +132,12 @@
 
     results->clear();
 
+#ifdef __LP64__
+    String8 dirPath("/vendor/lib64/mediacas");
+#else
     String8 dirPath("/vendor/lib/mediacas");
+#endif
+
     DIR* pDir = opendir(dirPath.string());
 
     if (pDir == NULL) {
diff --git a/cas/1.1/default/Android.bp b/cas/1.1/default/Android.bp
index 66a1eb8..8e1f207 100644
--- a/cas/1.1/default/Android.bp
+++ b/cas/1.1/default/Android.bp
@@ -12,7 +12,7 @@
       "TypeConvert.cpp",
     ],
 
-    compile_multilib: "32",
+    compile_multilib: "prefer32",
 
     shared_libs: [
       "android.hardware.cas@1.0",
diff --git a/cas/1.1/default/FactoryLoader.h b/cas/1.1/default/FactoryLoader.h
index c4a48e2..121f90c 100644
--- a/cas/1.1/default/FactoryLoader.h
+++ b/cas/1.1/default/FactoryLoader.h
@@ -85,7 +85,11 @@
     }
 
     // no luck, have to search
+#ifdef __LP64__
+    String8 dirPath("/vendor/lib64/mediacas");
+#else
     String8 dirPath("/vendor/lib/mediacas");
+#endif
     DIR* pDir = opendir(dirPath.string());
 
     if (pDir == NULL) {
@@ -118,7 +122,11 @@
 
     results->clear();
 
+#ifdef __LP64__
+    String8 dirPath("/vendor/lib64/mediacas");
+#else
     String8 dirPath("/vendor/lib/mediacas");
+#endif
     DIR* pDir = opendir(dirPath.string());
 
     if (pDir == NULL) {
diff --git a/cas/1.2/default/Android.bp b/cas/1.2/default/Android.bp
index 9e53148..d855e85 100644
--- a/cas/1.2/default/Android.bp
+++ b/cas/1.2/default/Android.bp
@@ -12,7 +12,7 @@
       "TypeConvert.cpp",
     ],
 
-    compile_multilib: "32",
+    compile_multilib: "prefer32",
 
     shared_libs: [
       "android.hardware.cas@1.0",
diff --git a/cas/1.2/default/FactoryLoader.h b/cas/1.2/default/FactoryLoader.h
index 7403f86..a374b31 100644
--- a/cas/1.2/default/FactoryLoader.h
+++ b/cas/1.2/default/FactoryLoader.h
@@ -85,7 +85,11 @@
     }
 
     // no luck, have to search
+#ifdef __LP64__
+    String8 dirPath("/vendor/lib64/mediacas");
+#else
     String8 dirPath("/vendor/lib/mediacas");
+#endif
     DIR* pDir = opendir(dirPath.string());
 
     if (pDir == NULL) {
@@ -118,7 +122,11 @@
 
     results->clear();
 
+#ifdef __LP64__
+    String8 dirPath("/vendor/lib64/mediacas");
+#else
     String8 dirPath("/vendor/lib/mediacas");
+#endif
     DIR* pDir = opendir(dirPath.string());
 
     if (pDir == NULL) {
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 23fd541..4bcfba9 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -73,6 +73,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.automotive.occupant_awareness</name>
+        <version>1</version>
         <interface>
             <name>IOccupantAwareness</name>
             <instance>default</instance>
@@ -82,7 +83,7 @@
         <name>android.hardware.automotive.sv</name>
         <version>1.0</version>
         <interface>
-            <name>ISurroundView</name>
+            <name>ISurroundViewService</name>
             <instance>default</instance>
         </interface>
     </hal>
@@ -336,6 +337,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.security.keymint</name>
+        <version>1</version>
         <interface>
             <name>IKeyMintDevice</name>
             <instance>default</instance>
@@ -344,6 +346,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.light</name>
+        <version>1</version>
         <interface>
             <name>ILights</name>
             <instance>default</instance>
@@ -372,6 +375,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.memtrack</name>
+        <version>1</version>
         <interface>
             <name>IMemtrack</name>
             <instance>default</instance>
@@ -411,6 +415,7 @@
     </hal>
     <hal format="aidl" optional="false">
         <name>android.hardware.power</name>
+        <version>1</version>
         <interface>
             <name>IPower</name>
             <instance>default</instance>
@@ -470,6 +475,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.rebootescrow</name>
+        <version>1</version>
         <interface>
             <name>IRebootEscrow</name>
             <instance>default</instance>
@@ -486,6 +492,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.security.secureclock</name>
+        <version>1</version>
         <interface>
             <name>ISecureClock</name>
             <instance>default</instance>
@@ -493,6 +500,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.security.sharedsecret</name>
+        <version>1</version>
         <interface>
             <name>ISharedSecret</name>
             <instance>default</instance>
diff --git a/health/storage/impl_common/impl_common.cpp b/health/storage/impl_common/impl_common.cpp
index 6e753d4..1a7a7f1 100644
--- a/health/storage/impl_common/impl_common.cpp
+++ b/health/storage/impl_common/impl_common.cpp
@@ -45,32 +45,59 @@
     return "";
 }
 
-Result GarbageCollect(uint64_t timeout_seconds) {
-    std::string path = GetGarbageCollectPath();
+static std::string GetWriteBoosterPath() {
+    Fstab fstab;
+    ReadDefaultFstab(&fstab);
 
-    if (path.empty()) {
+    for (const auto& entry : fstab) {
+        if (!entry.sysfs_path.empty()) {
+            return entry.sysfs_path + "/attributes/wb_avail_buf";
+        }
+    }
+
+    return "";
+}
+
+Result GarbageCollect(uint64_t timeout_seconds) {
+    std::string gc_path = GetGarbageCollectPath();
+
+    if (gc_path.empty()) {
         LOG(WARNING) << "Cannot find Dev GC path";
         return Result::UNKNOWN_ERROR;
     }
 
     Result result = Result::SUCCESS;
     Timer timer;
-    LOG(INFO) << "Start Dev GC on " << path;
+    LOG(INFO) << "Start Dev GC on " << gc_path;
     while (1) {
-        std::string require;
-        if (!ReadFileToString(path, &require)) {
-            PLOG(WARNING) << "Reading manual_gc failed in " << path;
+        std::string require_gc;
+        if (!ReadFileToString(gc_path, &require_gc)) {
+            PLOG(WARNING) << "Reading manual_gc failed in " << gc_path;
             result = Result::IO_ERROR;
             break;
         }
-        require = Trim(require);
-        if (require == "" || require == "off" || require == "disabled") {
+        require_gc = Trim(require_gc);
+
+        std::string wb_path = GetWriteBoosterPath();
+        // Let's flush WB till 100% available
+        std::string wb_avail = "0x0000000A";
+        if (!wb_path.empty() && !ReadFileToString(wb_path, &wb_avail)) {
+            PLOG(WARNING) << "Reading wb_avail_buf failed in " << wb_path;
+        }
+        wb_avail = Trim(wb_avail);
+
+        if (require_gc == "disabled") {
+            LOG(DEBUG) << "Disabled Dev GC";
+            break;
+        }
+        if ((require_gc == "" || require_gc == "off") && wb_avail == "0x0000000A") {
             LOG(DEBUG) << "No more to do Dev GC";
             break;
         }
-        LOG(DEBUG) << "Trigger Dev GC on " << path;
-        if (!WriteStringToFile("1", path)) {
-            PLOG(WARNING) << "Start Dev GC failed on " << path;
+        LOG(DEBUG) << "Trigger Dev GC on " << gc_path << " having " << require_gc << ", WB on "
+                   << wb_path << " having " << wb_avail;
+        if (!WriteStringToFile("1", gc_path)) {
+            PLOG(WARNING) << "Start Dev GC failed on " << gc_path;
             result = Result::IO_ERROR;
             break;
         }
@@ -81,9 +108,9 @@
         }
         sleep(2);
     }
-    LOG(INFO) << "Stop Dev GC on " << path;
-    if (!WriteStringToFile("0", path)) {
-        PLOG(WARNING) << "Stop Dev GC failed on " << path;
+    LOG(INFO) << "Stop Dev GC on " << gc_path;
+    if (!WriteStringToFile("0", gc_path)) {
+        PLOG(WARNING) << "Stop Dev GC failed on " << gc_path;
         result = Result::IO_ERROR;
     }
 
@@ -97,17 +124,26 @@
     if (path.empty()) {
         output << "Cannot find Dev GC path";
     } else {
-        std::string require;
+        std::string require_gc;
 
-        if (ReadFileToString(path, &require)) {
-            output << path << ":" << require << std::endl;
+        if (ReadFileToString(path, &require_gc)) {
+            output << path << ":" << require_gc << std::endl;
         }
 
         if (WriteStringToFile("0", path)) {
             output << "stop success" << std::endl;
         }
     }
+    std::string wb_path = GetWriteBoosterPath();
+    if (wb_path.empty()) {
+        output << "Cannot find Dev WriteBooster path";
+    } else {
+        std::string wb_available;
 
+        if (ReadFileToString(wb_path, &wb_available)) {
+            output << wb_path << ":" << wb_available << std::endl;
+        }
+    }
     if (!WriteStringToFd(output.str(), fd)) {
         PLOG(WARNING) << "debug: cannot write to fd";
     }
diff --git a/memtrack/aidl/vts/VtsHalMemtrackTargetTest.cpp b/memtrack/aidl/vts/VtsHalMemtrackTargetTest.cpp
index 2393c56..d5f4612 100644
--- a/memtrack/aidl/vts/VtsHalMemtrackTargetTest.cpp
+++ b/memtrack/aidl/vts/VtsHalMemtrackTargetTest.cpp
@@ -79,10 +79,10 @@
 
     auto status = memtrack_->getGpuDeviceInfo(&device_info);
 
-    // Devices with < 5.10 kernels aren't required to provide an implementation of
+    // Devices with < 5.4 kernels aren't required to provide an implementation of
     // getGpuDeviceInfo(), and can return EX_UNSUPPORTED_OPERATION
     if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
-        KernelVersion min_kernel_version = KernelVersion(5, 10, 0);
+        KernelVersion min_kernel_version = KernelVersion(5, 4, 0);
         KernelVersion kernel_version = VintfObject::GetInstance()
                                                ->getRuntimeInfo(RuntimeInfo::FetchFlag::CPU_VERSION)
                                                ->kernelVersion();
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Algorithm.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Algorithm.aidl
index a6c3e65..29ff8f8 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Algorithm.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Algorithm.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BeginResult.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BeginResult.aidl
index 84395af..4421619 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BeginResult.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BeginResult.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BlockMode.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BlockMode.aidl
index e914823..e9652c3 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BlockMode.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/BlockMode.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ByteArray.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ByteArray.aidl
index cef8eca..34f2749 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ByteArray.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ByteArray.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Certificate.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Certificate.aidl
index 2277831..5d1cc68 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Certificate.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Certificate.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * Copyright 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Digest.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Digest.aidl
index 2e583ce..5055d75 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Digest.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Digest.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/EcCurve.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/EcCurve.aidl
index b372822..1a7e9b5 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/EcCurve.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/EcCurve.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl
index aa8c071..594844a 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthToken.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthToken.aidl
index 5858c77..bd304f1 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthToken.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthToken.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * Copyright 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthenticatorType.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthenticatorType.aidl
index 9ab00c1..ae64110 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthenticatorType.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthenticatorType.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * Copyright 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
index c95145d..132135b 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintOperation.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintOperation.aidl
index e6ab4c8..a9b9a05 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintOperation.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintOperation.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCharacteristics.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCharacteristics.aidl
index 49ea8af..b430da9 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCharacteristics.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCharacteristics.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCreationResult.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCreationResult.aidl
index 4b9ac79..4139436 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCreationResult.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyCreationResult.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyFormat.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyFormat.aidl
index 4eb5a78..1ad7c51 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyFormat.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyFormat.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyMintHardwareInfo.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
index 0390ec9..93966ea 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -17,7 +31,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
-@VintfStability
+@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
 parcelable KeyMintHardwareInfo {
   int versionNumber;
   android.hardware.security.keymint.SecurityLevel securityLevel;
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyOrigin.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyOrigin.aidl
index e84cf74..acaf60d 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyOrigin.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyOrigin.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl
index 6829a2b..f534952 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterArray.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterArray.aidl
index 882ca89..2706623 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterArray.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterArray.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterValue.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterValue.aidl
index 6c11a92..c79614a 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterValue.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterValue.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyPurpose.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyPurpose.aidl
index ab5e815..c1e92af 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyPurpose.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyPurpose.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/PaddingMode.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/PaddingMode.aidl
index 6c61312..96b63e1 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/PaddingMode.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/PaddingMode.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/SecurityLevel.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/SecurityLevel.aidl
index c4812ed..c720d6d 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/SecurityLevel.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/SecurityLevel.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -22,4 +36,5 @@
   SOFTWARE = 0,
   TRUSTED_ENVIRONMENT = 1,
   STRONGBOX = 2,
+  KEYSTORE = 100,
 }
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl
index a6be6b1..b924a13 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/TagType.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/TagType.aidl
index 41c8832..75a19a3 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/TagType.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/TagType.aidl
@@ -1,4 +1,18 @@
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * 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.
+ *////////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
index b149ac9..69bec2d7 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
@@ -36,7 +36,6 @@
      * deciding whether a given tag from `keyParams` argument to the generation/import method should
      * be returned in `keyCharacteristics` are:
      *
-     * - If the IKeyMintDevice cannot fully enforce the semantics of the tag, it should be omitted.
      * - If the semantics of the tag are fully enforced by the IKeyMintDevice, without any
      *   assistance from components running at other security levels, it should be included in an
      *   entry with the SecurityLevel of the IKeyMintDevice.
@@ -45,6 +44,9 @@
      *   SecurityLevel of the involved components.  For example if a StrongBox IKeyMintDevice relies
      *   on a TEE to validate biometric authentication, biometric authentication tags go in an entry
      *   with SecurityLevel::TRUSTED_ENVIRONMENT.
+     * - If the semantics are not enforced by KeyMint at all, SecurityLevel::KEYSTORE is used to
+     *   indicate that Keystore should enforce.  Note that in Keymaster (predecessor to KeyMint),
+     *   these tags would have been in SecurityLevel::SOFTWARE.
      */
     KeyCharacteristics[] keyCharacteristics;
 
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyMintHardwareInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
index d3d7368..1a107ba 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
@@ -22,6 +22,7 @@
  * KeyMintHardwareInfo is the hardware information returned by calling KeyMint getHardwareInfo()
  */
 @VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
 parcelable KeyMintHardwareInfo {
     /**
      * Implementation version of the keymint hardware.  The version number is implementation
diff --git a/security/keymint/aidl/android/hardware/security/keymint/SecurityLevel.aidl b/security/keymint/aidl/android/hardware/security/keymint/SecurityLevel.aidl
index 10363e9..c63859c 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/SecurityLevel.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/SecurityLevel.aidl
@@ -17,16 +17,59 @@
 package android.hardware.security.keymint;
 
 /**
- * Device security levels.
+ * Device security levels.  These enum values are used in two ways:
+ *
+ * 1.  Returned from IKeyMintDevice::getHardwareInfo to identify the security level of the
+ *     IKeyMintDevice.  This characterizes the sort of environment in which the KeyMint
+ *     implementation runs, and therefore the security of its operations.
+ *
+ * 2.  Associated with individual KeyMint authorization Tags in KeyCharacteristics or in attestation
+ *     certificates.  This specifies the security level of the weakest environment involved in
+ *     enforcing that particular tag, i.e. the sort of security environment an attacker would have
+ *     to subvert in order to break the enforcement of that tag.
  */
 @VintfStability
 @Backing(type="int")
 enum SecurityLevel {
+    /**
+     * The SOFTWARE security level represents a KeyMint implementation that runs in an Android
+     * process, or a tag enforced by such an implementation.  An attacker who can compromise that
+     * process, or obtain root, or subvert the kernel on the device can defeat it.
+     *
+     * Note that the distinction between SOFTWARE and KEYSTORE is only relevant on-device.  For
+     * attestation purposes, these categories are combined into the software-enforced authorization
+     * list.
+     */
     SOFTWARE = 0,
+
+    /**
+     * The TRUSTED_ENVIRONMENT security level represents a KeyMint implementation that runs in an
+     * Android process, or a tag enforced by such an implementation.  An attacker who completely
+     * compromises Android, including the Linux kernel, does not have the ability to subvert it.  At
+     * attacker who can find an exploit that gains them control of the trusted environment, or who
+     * has access to the physical device and can mount a sophisticated hardware attack, may be able
+     * to defeat it.
+     */
     TRUSTED_ENVIRONMENT = 1,
     /**
-     * STRONGBOX specifies that the secure hardware satisfies the requirements specified in CDD
-     * 9.11.2.
+     * The STRONGBOX security level represents a KeyMint implementation that runs in security
+     * hardware that satisfies the requirements specified in CDD 9.11.2.  Roughly speaking, these
+     * are discrete, security-focus computing environments that are hardened against physical and
+     * side channel attack, and have had their security formally validated by a competent
+     * penetration testing lab.
      */
     STRONGBOX = 2,
+
+    /**
+     * KeyMint implementations must never return the KEYSTORE security level from getHardwareInfo.
+     * It is used to specify tags that are not enforced by the IKeyMintDevice, but are instead
+     * to be enforced by Keystore.  An attacker who can subvert the keystore process or gain root or
+     * subvert the kernel can prevent proper enforcement of these tags.
+     *
+     *
+     * Note that the distinction between SOFTWARE and KEYSTORE is only relevant on-device.  When
+     * KeyMint generates an attestation certificate, these categories are combined into the
+     * software-enforced authorization list.
+     */
+    KEYSTORE = 100
 }
diff --git a/security/keymint/support/include/keymint_support/keymint_tags.h b/security/keymint/support/include/keymint_support/keymint_tags.h
index 8d2fe28..43cfb63 100644
--- a/security/keymint/support/include/keymint_support/keymint_tags.h
+++ b/security/keymint/support/include/keymint_support/keymint_tags.h
@@ -326,7 +326,9 @@
 inline std::optional<
         std::reference_wrapper<const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>>
 authorizationValue(TypedTag<tag_type, tag> ttag, const KeyParameter& param) {
-    if (TypedTag2ValueType<TypedTag<tag_type, tag>>::unionTag != param.value.getTag()) return {};
+    // We only check if the parameter has the correct tag here; accessTagValue checks if the correct
+    // union field was initialized.
+    if (tag != param.tag) return {};
     return accessTagValue(ttag, param);
 }
 
diff --git a/sensors/common/default/2.X/Sensor.cpp b/sensors/common/default/2.X/Sensor.cpp
index 642fc89..1a7c628 100644
--- a/sensors/common/default/2.X/Sensor.cpp
+++ b/sensors/common/default/2.X/Sensor.cpp
@@ -313,7 +313,7 @@
     mSensorInfo.maxRange = 1000.0f * M_PI / 180.0f;
     mSensorInfo.resolution = 1000.0f * M_PI / (180.0f * 32768.0f);
     mSensorInfo.power = 0.001f;
-    mSensorInfo.minDelay = 2.5f * 1000;  // microseconds
+    mSensorInfo.minDelay = 10 * 1000;  // microseconds
     mSensorInfo.maxDelay = kDefaultMaxDelayUs;
     mSensorInfo.fifoReservedEventCount = 0;
     mSensorInfo.fifoMaxEventCount = 0;
diff --git a/tetheroffload/control/1.1/IOffloadControl.hal b/tetheroffload/control/1.1/IOffloadControl.hal
index eb5b8a1..2eb54c8 100644
--- a/tetheroffload/control/1.1/IOffloadControl.hal
+++ b/tetheroffload/control/1.1/IOffloadControl.hal
@@ -37,11 +37,9 @@
      * offload is started. This is because the quota values would likely become stale over
      * time and would not reflect any new traffic that has occurred.
      *
-     * This API replaces {@link @1.0::IOffloadControl::setDataLimit}, the framework would always
-     * calls this API if 1.1 HAL is supported. Otherwise, calls the other one. Thus, no
-     * interaction between the two APIs need to be addressed. However, the hardware implementation
-     * still needs to keep functionality of both in case of shipping with older framework that
-     * doesn't support 1.1 HAL.
+     * This API replaces {@link @1.0::IOffloadControl::setDataLimit}, the framework will always
+     * call setDataWarningAndLimit on 1.1 implementations, and setDataLimit on 1.0 implementations.
+     * Thus, no interaction between the two APIs need to be addressed.
      *
      * The specified quota bytes MUST replace any previous quotas set by
      * {@code setDataWarningAndLimit} specified on the same interface. It may be interpreted as
diff --git a/wifi/1.5/IWifiApIface.hal b/wifi/1.5/IWifiApIface.hal
index 9625a6b..c638f1d 100644
--- a/wifi/1.5/IWifiApIface.hal
+++ b/wifi/1.5/IWifiApIface.hal
@@ -37,4 +37,18 @@
      *         |WifiStatusCode.ERROR_UNKNOWN|
      */
     resetToFactoryMacAddress() generates (WifiStatus status);
+
+    /**
+     * Get the names of the bridged AP instances.
+     *
+     * @return status WifiStatus of the operation
+     *         Possible status codes:
+     *         |WifiStatusCode.SUCCESS|,
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     *
+     * @return instances A vector which contains the names of the bridged AP
+     * instances. Note: Returns an empty vector for a non-bridged AP.
+     */
+    getBridgedInstances() generates (WifiStatus status, vec<string> instances);
 };
diff --git a/wifi/1.5/IWifiChip.hal b/wifi/1.5/IWifiChip.hal
index b2960cf..209190a 100644
--- a/wifi/1.5/IWifiChip.hal
+++ b/wifi/1.5/IWifiChip.hal
@@ -234,4 +234,33 @@
      *         |WifiStatusCode.FAILURE_IFACE_INVALID|
      */
     setCountryCode(int8_t[2] code) generates (WifiStatus status);
+
+    /**
+     * Retrieve list of usable Wifi channels for the specified band &
+     * operational modes.
+     *
+     * The list of usable Wifi channels in a given band depends on factors
+     * like current country code, operational mode (e.g. STA, SAP, CLI, GO,
+     * TDLS, NAN) and any hard restrictons due to DFS, LTE Coex and
+     * MCC(multi channel-concurrency).
+     *
+     * @param band |WifiBand| for which list of usable channels is requested.
+     * @param ifaceModeMask Bitmask of the modes represented by |WifiIfaceMode|
+     *        Bitmask respresents all the modes that the caller is interested
+     *        in (e.g. STA, SAP, CLI, GO, TDLS, NAN).
+     *        Note: Bitmask does not represent concurrency matrix.
+     * @return status WifiStatus of the operation.
+     *         Possible status codes:
+     *         |WifiStatusCode.SUCCESS|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.FAILURE_UNKNOWN|
+     * @return channels List of channels represented by |WifiUsableChannel|
+     *         Each entry represents a channel frequency, bandwidth and
+     *         bitmask of operational modes (e.g. STA, SAP, CLI, GO, TDLS, NAN)
+     *         allowed on that channel.
+     *         Note: Bitmask does not represent concurrency matrix.
+     */
+    getUsableChannels(WifiBand band, bitfield<WifiIfaceMode> ifaceModeMask)
+        generates (WifiStatus status, vec<WifiUsableChannel> channels);
 };
diff --git a/wifi/1.5/default/hidl_struct_util.cpp b/wifi/1.5/default/hidl_struct_util.cpp
index 8e2e647..7cee4cd 100644
--- a/wifi/1.5/default/hidl_struct_util.cpp
+++ b/wifi/1.5/default/hidl_struct_util.cpp
@@ -356,6 +356,129 @@
     return true;
 }
 
+uint32_t convertHidlWifiBandToLegacyMacBand(V1_5::WifiBand hidl_band) {
+    switch (hidl_band) {
+        case V1_5::WifiBand::BAND_24GHZ:
+            return legacy_hal::WLAN_MAC_2_4_BAND;
+        case V1_5::WifiBand::BAND_5GHZ:
+        case V1_5::WifiBand::BAND_5GHZ_DFS:
+        case V1_5::WifiBand::BAND_5GHZ_WITH_DFS:
+            return legacy_hal::WLAN_MAC_5_0_BAND;
+        case V1_5::WifiBand::BAND_24GHZ_5GHZ:
+        case V1_5::WifiBand::BAND_24GHZ_5GHZ_WITH_DFS:
+            return (legacy_hal::WLAN_MAC_2_4_BAND |
+                    legacy_hal::WLAN_MAC_5_0_BAND);
+        case V1_5::WifiBand::BAND_6GHZ:
+            return legacy_hal::WLAN_MAC_6_0_BAND;
+        case V1_5::WifiBand::BAND_5GHZ_6GHZ:
+            return (legacy_hal::WLAN_MAC_5_0_BAND |
+                    legacy_hal::WLAN_MAC_6_0_BAND);
+        case V1_5::WifiBand::BAND_24GHZ_5GHZ_6GHZ:
+        case V1_5::WifiBand::BAND_24GHZ_5GHZ_WITH_DFS_6GHZ:
+            return (legacy_hal::WLAN_MAC_2_4_BAND |
+                    legacy_hal::WLAN_MAC_5_0_BAND |
+                    legacy_hal::WLAN_MAC_6_0_BAND);
+        case V1_5::WifiBand::BAND_60GHZ:
+            return legacy_hal::WLAN_MAC_60_0_BAND;
+        default:
+            return (
+                legacy_hal::WLAN_MAC_2_4_BAND | legacy_hal::WLAN_MAC_5_0_BAND |
+                legacy_hal::WLAN_MAC_6_0_BAND | legacy_hal::WLAN_MAC_60_0_BAND);
+    }
+}
+
+uint32_t convertHidlWifiIfaceModeToLegacy(uint32_t hidl_iface_mask) {
+    uint32_t legacy_iface_mask = 0;
+    if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_STA) {
+        legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_STA);
+    }
+    if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_SOFTAP) {
+        legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_SOFTAP);
+    }
+    if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_P2P_CLIENT) {
+        legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_P2P_CLIENT);
+    }
+    if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_P2P_GO) {
+        legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_P2P_GO);
+    }
+    if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_NAN) {
+        legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_NAN);
+    }
+    if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_TDLS) {
+        legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_TDLS);
+    }
+    if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_MESH) {
+        legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_MESH);
+    }
+    if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_IBSS) {
+        legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_IBSS);
+    }
+    return legacy_iface_mask;
+}
+
+uint32_t convertLegacyWifiInterfaceModeToHidl(uint32_t legacy_iface_mask) {
+    uint32_t hidl_iface_mask = 0;
+    if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_STA)) {
+        hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_STA;
+    }
+    if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_SOFTAP)) {
+        hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_SOFTAP;
+    }
+    if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_P2P_CLIENT)) {
+        hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_P2P_CLIENT;
+    }
+    if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_P2P_GO)) {
+        hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_P2P_GO;
+    }
+    if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_NAN)) {
+        hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_NAN;
+    }
+    if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_TDLS)) {
+        hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_TDLS;
+    }
+    if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_MESH)) {
+        hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_MESH;
+    }
+    if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_IBSS)) {
+        hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_IBSS;
+    }
+    return hidl_iface_mask;
+}
+
+bool convertLegacyWifiUsableChannelToHidl(
+    const legacy_hal::wifi_usable_channel& legacy_usable_channel,
+    V1_5::WifiUsableChannel* hidl_usable_channel) {
+    if (!hidl_usable_channel) {
+        return false;
+    }
+    *hidl_usable_channel = {};
+    hidl_usable_channel->channel = legacy_usable_channel.freq;
+    hidl_usable_channel->channelBandwidth =
+        convertLegacyWifiChannelWidthToHidl(legacy_usable_channel.width);
+    hidl_usable_channel->ifaceModeMask = convertLegacyWifiInterfaceModeToHidl(
+        legacy_usable_channel.iface_mode_mask);
+
+    return true;
+}
+
+bool convertLegacyWifiUsableChannelsToHidl(
+    const std::vector<legacy_hal::wifi_usable_channel>& legacy_usable_channels,
+    std::vector<V1_5::WifiUsableChannel>* hidl_usable_channels) {
+    if (!hidl_usable_channels) {
+        return false;
+    }
+    *hidl_usable_channels = {};
+    for (const auto& legacy_usable_channel : legacy_usable_channels) {
+        V1_5::WifiUsableChannel hidl_usable_channel;
+        if (!convertLegacyWifiUsableChannelToHidl(legacy_usable_channel,
+                                                  &hidl_usable_channel)) {
+            return false;
+        }
+        hidl_usable_channels->push_back(hidl_usable_channel);
+    }
+    return true;
+}
+
 bool convertLegacyWifiMacInfosToHidl(
     const std::vector<legacy_hal::WifiMacInfo>& legacy_mac_infos,
     std::vector<V1_4::IWifiChipEventCallback::RadioModeInfo>*
diff --git a/wifi/1.5/default/hidl_struct_util.h b/wifi/1.5/default/hidl_struct_util.h
index feb47ef..c0d7bf8 100644
--- a/wifi/1.5/default/hidl_struct_util.h
+++ b/wifi/1.5/default/hidl_struct_util.h
@@ -206,6 +206,11 @@
 bool convertLegacyVectorOfRttResultToHidl(
     const std::vector<const legacy_hal::wifi_rtt_result*>& legacy_results,
     std::vector<V1_4::RttResult>* hidl_results);
+uint32_t convertHidlWifiBandToLegacyMacBand(V1_5::WifiBand band);
+uint32_t convertHidlWifiIfaceModeToLegacy(uint32_t hidl_iface_mask);
+bool convertLegacyWifiUsableChannelsToHidl(
+    const std::vector<legacy_hal::wifi_usable_channel>& legacy_usable_channels,
+    std::vector<V1_5::WifiUsableChannel>* hidl_usable_channels);
 }  // namespace hidl_struct_util
 }  // namespace implementation
 }  // namespace V1_5
diff --git a/wifi/1.5/default/wifi_ap_iface.cpp b/wifi/1.5/default/wifi_ap_iface.cpp
index d98aa45..b438a4a 100644
--- a/wifi/1.5/default/wifi_ap_iface.cpp
+++ b/wifi/1.5/default/wifi_ap_iface.cpp
@@ -47,6 +47,12 @@
 
 std::string WifiApIface::getName() { return ifname_; }
 
+void WifiApIface::removeInstance(std::string instance) {
+    instances_.erase(
+        std::remove(instances_.begin(), instances_.end(), instance),
+        instances_.end());
+}
+
 Return<void> WifiApIface::getName(getName_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
                            &WifiApIface::getNameInternal, hidl_status_cb);
@@ -93,6 +99,13 @@
                            hidl_status_cb);
 }
 
+Return<void> WifiApIface::getBridgedInstances(
+    getBridgedInstances_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiApIface::getBridgedInstancesInternal,
+                           hidl_status_cb);
+}
+
 std::pair<WifiStatus, std::string> WifiApIface::getNameInternal() {
     return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
 }
@@ -178,6 +191,15 @@
     }
     return createWifiStatus(WifiStatusCode::SUCCESS);
 }
+
+std::pair<WifiStatus, std::vector<hidl_string>>
+WifiApIface::getBridgedInstancesInternal() {
+    std::vector<hidl_string> instances;
+    for (const auto& instance_name : instances_) {
+        instances.push_back(instance_name);
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), instances};
+}
 }  // namespace implementation
 }  // namespace V1_5
 }  // namespace wifi
diff --git a/wifi/1.5/default/wifi_ap_iface.h b/wifi/1.5/default/wifi_ap_iface.h
index 02fb2d8..8f8387d 100644
--- a/wifi/1.5/default/wifi_ap_iface.h
+++ b/wifi/1.5/default/wifi_ap_iface.h
@@ -43,6 +43,7 @@
     void invalidate();
     bool isValid();
     std::string getName();
+    void removeInstance(std::string instance);
 
     // HIDL methods exposed.
     Return<void> getName(getName_cb hidl_status_cb) override;
@@ -59,6 +60,9 @@
     Return<void> resetToFactoryMacAddress(
         resetToFactoryMacAddress_cb hidl_status_cb) override;
 
+    Return<void> getBridgedInstances(
+        getBridgedInstances_cb hidl_status_cb) override;
+
    private:
     // Corresponding worker functions for the HIDL methods.
     std::pair<WifiStatus, std::string> getNameInternal();
@@ -70,6 +74,8 @@
     std::pair<WifiStatus, std::array<uint8_t, 6>> getFactoryMacAddressInternal(
         const std::string& ifaceName);
     WifiStatus resetToFactoryMacAddressInternal();
+    std::pair<WifiStatus, std::vector<hidl_string>>
+    getBridgedInstancesInternal();
 
     std::string ifname_;
     std::vector<std::string> instances_;
diff --git a/wifi/1.5/default/wifi_chip.cpp b/wifi/1.5/default/wifi_chip.cpp
index 414d74c..2dc7314 100644
--- a/wifi/1.5/default/wifi_chip.cpp
+++ b/wifi/1.5/default/wifi_chip.cpp
@@ -738,6 +738,14 @@
                            code);
 }
 
+Return<void> WifiChip::getUsableChannels(
+    WifiBand band, hidl_bitfield<WifiIfaceMode> ifaceModeMask,
+    getUsableChannels_cb _hidl_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::getUsableChannelsInternal, _hidl_cb, band,
+                           ifaceModeMask);
+}
+
 void WifiChip::invalidateAndRemoveAllIfaces() {
     invalidateAndClearBridgedApAll();
     invalidateAndClearAll(ap_ifaces_);
@@ -1066,6 +1074,7 @@
         }
     }
     br_ifaces_ap_instances_.erase(ifInstanceName);
+    iface->removeInstance(ifInstanceName);
     return createWifiStatus(WifiStatusCode::SUCCESS);
 }
 
@@ -1490,6 +1499,25 @@
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
+std::pair<WifiStatus, std::vector<WifiUsableChannel>>
+WifiChip::getUsableChannelsInternal(WifiBand band, uint32_t ifaceModeMask) {
+    legacy_hal::wifi_error legacy_status;
+    std::vector<legacy_hal::wifi_usable_channel> legacy_usable_channels;
+    std::tie(legacy_status, legacy_usable_channels) =
+        legacy_hal_.lock()->getUsableChannels(
+            hidl_struct_util::convertHidlWifiBandToLegacyMacBand(band),
+            hidl_struct_util::convertHidlWifiIfaceModeToLegacy(ifaceModeMask));
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), {}};
+    }
+    std::vector<WifiUsableChannel> hidl_usable_channels;
+    if (!hidl_struct_util::convertLegacyWifiUsableChannelsToHidl(
+            legacy_usable_channels, &hidl_usable_channels)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_usable_channels};
+}
+
 WifiStatus WifiChip::handleChipConfiguration(
     /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
     ChipModeId mode_id) {
diff --git a/wifi/1.5/default/wifi_chip.h b/wifi/1.5/default/wifi_chip.h
index 7d7a9b5..d542792 100644
--- a/wifi/1.5/default/wifi_chip.h
+++ b/wifi/1.5/default/wifi_chip.h
@@ -180,6 +180,9 @@
         setCoexUnsafeChannels_cb hidl_status_cb) override;
     Return<void> setCountryCode(const hidl_array<int8_t, 2>& code,
                                 setCountryCode_cb _hidl_cb) override;
+    Return<void> getUsableChannels(WifiBand band,
+                                   hidl_bitfield<WifiIfaceMode> ifaceModeMask,
+                                   getUsableChannels_cb _hidl_cb) override;
 
    private:
     void invalidateAndRemoveAllIfaces();
@@ -261,6 +264,8 @@
     WifiStatus setCoexUnsafeChannelsInternal(
         std::vector<CoexUnsafeChannel> unsafe_channels, uint32_t restrictions);
     WifiStatus setCountryCodeInternal(const std::array<int8_t, 2>& code);
+    std::pair<WifiStatus, std::vector<WifiUsableChannel>>
+    getUsableChannelsInternal(WifiBand band, uint32_t ifaceModeMask);
     WifiStatus handleChipConfiguration(
         std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id);
     WifiStatus registerDebugRingBufferCallback();
diff --git a/wifi/1.5/default/wifi_legacy_hal.cpp b/wifi/1.5/default/wifi_legacy_hal.cpp
index 3e65ee0..94603b3 100644
--- a/wifi/1.5/default/wifi_legacy_hal.cpp
+++ b/wifi/1.5/default/wifi_legacy_hal.cpp
@@ -36,6 +36,7 @@
 static constexpr uint32_t kLinkLayerStatsDataMpduSizeThreshold = 128;
 static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32;
 static constexpr uint32_t kMaxRingBuffers = 10;
+static constexpr uint32_t kMaxWifiUsableChannels = 256;
 // need a long timeout (1000ms) for chips that unload their driver.
 static constexpr uint32_t kMaxStopCompleteWaitMs = 1000;
 static constexpr char kDriverPropName[] = "wlan.driver.status";
@@ -1636,6 +1637,19 @@
                                                    multiplier);
 }
 
+std::pair<wifi_error, std::vector<wifi_usable_channel>>
+WifiLegacyHal::getUsableChannels(uint32_t band_mask, uint32_t iface_mode_mask) {
+    std::vector<wifi_usable_channel> channels;
+    channels.resize(kMaxWifiUsableChannels);
+    uint32_t size = 0;
+    wifi_error status = global_func_table_.wifi_get_usable_channels(
+        global_handle_, band_mask, iface_mode_mask, channels.size(), &size,
+        reinterpret_cast<wifi_usable_channel*>(channels.data()));
+    CHECK(size >= 0 && size <= kMaxWifiUsableChannels);
+    channels.resize(size);
+    return {status, std::move(channels)};
+}
+
 void WifiLegacyHal::invalidate() {
     global_handle_ = nullptr;
     iface_name_to_handle_.clear();
diff --git a/wifi/1.5/default/wifi_legacy_hal.h b/wifi/1.5/default/wifi_legacy_hal.h
index 0cc1cff..dc641ae 100644
--- a/wifi/1.5/default/wifi_legacy_hal.h
+++ b/wifi/1.5/default/wifi_legacy_hal.h
@@ -36,9 +36,13 @@
 namespace legacy_hal {
 // Import all the types defined inside the legacy HAL header files into this
 // namespace.
+using ::frame_info;
+using ::frame_type;
 using ::FRAME_TYPE_80211_MGMT;
 using ::FRAME_TYPE_ETHERNET_II;
 using ::FRAME_TYPE_UNKNOWN;
+using ::fw_roaming_state_t;
+using ::mac_addr;
 using ::NAN_CHANNEL_24G_BAND;
 using ::NAN_CHANNEL_5G_BAND_HIGH;
 using ::NAN_CHANNEL_5G_BAND_LOW;
@@ -80,8 +84,6 @@
 using ::NAN_RESPONSE_TCA;
 using ::NAN_RESPONSE_TRANSMIT_FOLLOWUP;
 using ::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
-using ::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
-using ::NAN_SECURITY_KEY_INPUT_PMK;
 using ::NAN_SECURITY_KEY_INPUT_PMK;
 using ::NAN_SERVICE_ACCEPT_POLICY_ALL;
 using ::NAN_SERVICE_ACCEPT_POLICY_NONE;
@@ -154,19 +156,20 @@
 using ::RTT_PEER_P2P_CLIENT;
 using ::RTT_PEER_P2P_GO;
 using ::RTT_PEER_STA;
+using ::rtt_peer_type;
 using ::RTT_STATUS_ABORTED;
-using ::RTT_STATUS_FAILURE;
 using ::RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL;
 using ::RTT_STATUS_FAIL_BUSY_TRY_LATER;
 using ::RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE;
 using ::RTT_STATUS_FAIL_INVALID_TS;
-using ::RTT_STATUS_FAIL_NOT_SCHEDULED_YET;
 using ::RTT_STATUS_FAIL_NO_CAPABILITY;
 using ::RTT_STATUS_FAIL_NO_RSP;
+using ::RTT_STATUS_FAIL_NOT_SCHEDULED_YET;
 using ::RTT_STATUS_FAIL_PROTOCOL;
 using ::RTT_STATUS_FAIL_REJECTED;
 using ::RTT_STATUS_FAIL_SCHEDULE;
 using ::RTT_STATUS_FAIL_TM_TIMEOUT;
+using ::RTT_STATUS_FAILURE;
 using ::RTT_STATUS_INVALID_REQ;
 using ::RTT_STATUS_NAN_RANGING_CONCURRENCY_NOT_SUPPORTED;
 using ::RTT_STATUS_NAN_RANGING_PROTOCOL_FAILURE;
@@ -185,6 +188,8 @@
 using ::RX_PKT_FATE_FW_DROP_OTHER;
 using ::RX_PKT_FATE_FW_QUEUED;
 using ::RX_PKT_FATE_SUCCESS;
+using ::ssid_t;
+using ::transaction_id;
 using ::TX_PKT_FATE_ACKED;
 using ::TX_PKT_FATE_DRV_DROP_INVALID;
 using ::TX_PKT_FATE_DRV_DROP_NOBUFS;
@@ -199,24 +204,31 @@
 using ::WIFI_AC_BK;
 using ::WIFI_AC_VI;
 using ::WIFI_AC_VO;
+using ::wifi_band;
 using ::WIFI_BAND_A;
-using ::WIFI_BAND_ABG;
-using ::WIFI_BAND_ABG_WITH_DFS;
 using ::WIFI_BAND_A_DFS;
 using ::WIFI_BAND_A_WITH_DFS;
+using ::WIFI_BAND_ABG;
+using ::WIFI_BAND_ABG_WITH_DFS;
 using ::WIFI_BAND_BG;
 using ::WIFI_BAND_UNSPECIFIED;
+using ::wifi_cached_scan_results;
 using ::WIFI_CHAN_WIDTH_10;
 using ::WIFI_CHAN_WIDTH_160;
 using ::WIFI_CHAN_WIDTH_20;
 using ::WIFI_CHAN_WIDTH_40;
 using ::WIFI_CHAN_WIDTH_5;
-using ::WIFI_CHAN_WIDTH_5;
 using ::WIFI_CHAN_WIDTH_80;
 using ::WIFI_CHAN_WIDTH_80P80;
 using ::WIFI_CHAN_WIDTH_INVALID;
+using ::wifi_channel_info;
+using ::wifi_channel_stat;
+using ::wifi_channel_width;
+using ::wifi_coex_restriction;
+using ::wifi_coex_unsafe_channel;
 using ::WIFI_DUAL_STA_NON_TRANSIENT_UNBIASED;
 using ::WIFI_DUAL_STA_TRANSIENT_PREFER_PRIMARY;
+using ::wifi_error;
 using ::WIFI_ERROR_BUSY;
 using ::WIFI_ERROR_INVALID_ARGS;
 using ::WIFI_ERROR_INVALID_REQUEST_ID;
@@ -228,12 +240,29 @@
 using ::WIFI_ERROR_TOO_MANY_REQUESTS;
 using ::WIFI_ERROR_UNINITIALIZED;
 using ::WIFI_ERROR_UNKNOWN;
+using ::wifi_gscan_capabilities;
+using ::wifi_hal_fn;
+using ::wifi_information_element;
+using ::WIFI_INTERFACE_IBSS;
+using ::WIFI_INTERFACE_MESH;
+using ::wifi_interface_mode;
+using ::WIFI_INTERFACE_NAN;
+using ::WIFI_INTERFACE_P2P_CLIENT;
+using ::WIFI_INTERFACE_P2P_GO;
+using ::WIFI_INTERFACE_SOFTAP;
+using ::WIFI_INTERFACE_STA;
+using ::WIFI_INTERFACE_TDLS;
+using ::wifi_interface_type;
 using ::WIFI_INTERFACE_TYPE_AP;
 using ::WIFI_INTERFACE_TYPE_NAN;
 using ::WIFI_INTERFACE_TYPE_P2P;
 using ::WIFI_INTERFACE_TYPE_STA;
+using ::WIFI_INTERFACE_UNKNOWN;
+using ::wifi_latency_mode;
 using ::WIFI_LATENCY_MODE_LOW;
 using ::WIFI_LATENCY_MODE_NORMAL;
+using ::wifi_lci_information;
+using ::wifi_lcr_information;
 using ::WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
 using ::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED;
 using ::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
@@ -242,61 +271,34 @@
 using ::WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
 using ::WIFI_MOTION_EXPECTED;
 using ::WIFI_MOTION_NOT_EXPECTED;
+using ::wifi_motion_pattern;
 using ::WIFI_MOTION_UNKNOWN;
+using ::wifi_multi_sta_use_case;
+using ::wifi_power_scenario;
 using ::WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF;
 using ::WIFI_POWER_SCENARIO_ON_BODY_CELL_ON;
 using ::WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF;
 using ::WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON;
 using ::WIFI_POWER_SCENARIO_VOICE_CALL;
-using ::WIFI_RTT_BW_10;
-using ::WIFI_RTT_BW_160;
-using ::WIFI_RTT_BW_20;
-using ::WIFI_RTT_BW_40;
-using ::WIFI_RTT_BW_5;
-using ::WIFI_RTT_BW_80;
-using ::WIFI_RTT_PREAMBLE_HE;
-using ::WIFI_RTT_PREAMBLE_HT;
-using ::WIFI_RTT_PREAMBLE_LEGACY;
-using ::WIFI_RTT_PREAMBLE_VHT;
-using ::WIFI_SCAN_FLAG_INTERRUPTED;
-using ::WIFI_SUCCESS;
-using ::WLAN_MAC_2_4_BAND;
-using ::WLAN_MAC_5_0_BAND;
-using ::WLAN_MAC_6_0_BAND;
-using ::frame_info;
-using ::frame_type;
-using ::fw_roaming_state_t;
-using ::mac_addr;
-using ::rtt_peer_type;
-using ::ssid_t;
-using ::transaction_id;
-using ::wifi_band;
-using ::wifi_cached_scan_results;
-using ::wifi_channel_info;
-using ::wifi_channel_stat;
-using ::wifi_channel_width;
-using ::wifi_coex_restriction;
-using ::wifi_coex_unsafe_channel;
-using ::wifi_error;
-using ::wifi_gscan_capabilities;
-using ::wifi_hal_fn;
-using ::wifi_information_element;
-using ::wifi_interface_type;
-using ::wifi_latency_mode;
-using ::wifi_lci_information;
-using ::wifi_lcr_information;
-using ::wifi_motion_pattern;
-using ::wifi_multi_sta_use_case;
-using ::wifi_power_scenario;
 using ::wifi_rate;
 using ::wifi_request_id;
 using ::wifi_ring_buffer_status;
 using ::wifi_roaming_capabilities;
 using ::wifi_roaming_config;
 using ::wifi_rtt_bw;
+using ::WIFI_RTT_BW_10;
+using ::WIFI_RTT_BW_160;
+using ::WIFI_RTT_BW_20;
+using ::WIFI_RTT_BW_40;
+using ::WIFI_RTT_BW_5;
+using ::WIFI_RTT_BW_80;
 using ::wifi_rtt_capabilities;
 using ::wifi_rtt_config;
 using ::wifi_rtt_preamble;
+using ::WIFI_RTT_PREAMBLE_HE;
+using ::WIFI_RTT_PREAMBLE_HT;
+using ::WIFI_RTT_PREAMBLE_LEGACY;
+using ::WIFI_RTT_PREAMBLE_VHT;
 using ::wifi_rtt_responder;
 using ::wifi_rtt_result;
 using ::wifi_rtt_status;
@@ -305,9 +307,16 @@
 using ::wifi_rx_report;
 using ::wifi_scan_bucket_spec;
 using ::wifi_scan_cmd_params;
+using ::WIFI_SCAN_FLAG_INTERRUPTED;
 using ::wifi_scan_result;
+using ::WIFI_SUCCESS;
 using ::wifi_tx_packet_fate;
 using ::wifi_tx_report;
+using ::wifi_usable_channel;
+using ::WLAN_MAC_2_4_BAND;
+using ::WLAN_MAC_5_0_BAND;
+using ::WLAN_MAC_60_0_BAND;
+using ::WLAN_MAC_6_0_BAND;
 
 // APF capabilities supported by the iface.
 struct PacketFilterCapabilities {
@@ -693,6 +702,11 @@
     wifi_error setDtimConfig(const std::string& iface_name,
                              uint32_t multiplier);
 
+    // Retrieve the list of usable channels in the requested bands
+    // for the requested modes
+    std::pair<wifi_error, std::vector<wifi_usable_channel>> getUsableChannels(
+        uint32_t band_mask, uint32_t iface_mode_mask);
+
    private:
     // Retrieve interface handles for all the available interfaces.
     wifi_error retrieveIfaceHandles();
diff --git a/wifi/1.5/default/wifi_legacy_hal_stubs.cpp b/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
index 7ba5d9b..6212960 100644
--- a/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
+++ b/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
@@ -159,6 +159,7 @@
     populateStubFor(&hal_fn->wifi_twt_get_stats);
     populateStubFor(&hal_fn->wifi_twt_clear_stats);
     populateStubFor(&hal_fn->wifi_set_dtim_config);
+    populateStubFor(&hal_fn->wifi_get_usable_channels);
     return true;
 }
 }  // namespace legacy_hal
diff --git a/wifi/1.5/types.hal b/wifi/1.5/types.hal
index 9fa5c80..4dff774 100644
--- a/wifi/1.5/types.hal
+++ b/wifi/1.5/types.hal
@@ -24,6 +24,8 @@
 import @1.0::NanCapabilities;
 import @1.2::NanConfigRequestSupplemental;
 import @1.3::StaLinkLayerRadioStats;
+import @1.0::WifiChannelInMhz;
+import @1.0::WifiChannelWidthInMhz;
 
 /**
  * Wifi bands defined in 80211 spec.
@@ -44,6 +46,64 @@
 };
 
 /**
+ * Interface operating modes.
+ */
+enum WifiIfaceMode : uint32_t {
+    /**
+     * Interface operation mode is client.
+     */
+    IFACE_MODE_STA = 1 << 0,
+    /**
+     * Interface operation mode is Hotspot.
+     */
+    IFACE_MODE_SOFTAP = 1 << 1,
+    /**
+     * Interface operation mode is Ad-Hoc network.
+     */
+    IFACE_MODE_IBSS = 1 << 2,
+    /**
+     * Interface operation mode is Wifi Direct Client.
+     */
+    IFACE_MODE_P2P_CLIENT = 1 << 3,
+    /**
+     * Interface operation mode is Wifi Direct Group Owner.
+     */
+    IFACE_MODE_P2P_GO = 1 << 4,
+    /**
+     * Interface operation mode is Aware.
+     */
+    IFACE_MODE_NAN = 1 << 5,
+    /**
+     * Interface operation mode is Mesh network.
+     */
+    IFACE_MODE_MESH = 1 << 6,
+    /**
+     * Interface operation mode is Tunneled Direct Link Setup.
+     */
+    IFACE_MODE_TDLS = 1 << 7,
+};
+
+/**
+ * Wifi usable channel information.
+ */
+struct WifiUsableChannel {
+    /**
+     * Wifi channel freqeuncy in MHz.
+     */
+    WifiChannelInMhz channel;
+
+    /**
+     * Wifi channel bandwidth in MHz.
+     */
+    WifiChannelWidthInMhz channelBandwidth;
+
+    /**
+     * Iface modes feasible on this channel.
+     */
+    bitfield<WifiIfaceMode> ifaceModeMask;
+};
+
+/**
  * NAN configuration request parameters added in the 1.2 HAL. These are supplemental to previous
  * versions.
  */
diff --git a/wifi/1.5/vts/functional/wifi_ap_iface_hidl_test.cpp b/wifi/1.5/vts/functional/wifi_ap_iface_hidl_test.cpp
index e47b14d..424f934 100644
--- a/wifi/1.5/vts/functional/wifi_ap_iface_hidl_test.cpp
+++ b/wifi/1.5/vts/functional/wifi_ap_iface_hidl_test.cpp
@@ -67,8 +67,8 @@
     std::string GetInstanceName() { return GetParam(); }
 };
 
-/*
- * resetToFactoryMacAddress
+/**
+ * resetToFactoryMacAddress in bridged AP mode.
  */
 TEST_P(WifiApIfaceHidlTest, resetToFactoryMacAddressInBridgedModeTest) {
     if (!isBridgedSupport_) GTEST_SKIP() << "Missing Bridged AP support";
@@ -79,8 +79,8 @@
     EXPECT_EQ(WifiStatusCode::SUCCESS, status.code);
 }
 
-/*
- * resetToFactoryMacAddress
+/**
+ * resetToFactoryMacAddress in non-bridged mode
  */
 TEST_P(WifiApIfaceHidlTest, resetToFactoryMacAddressTest) {
     sp<IWifiApIface> wifi_ap_iface = getWifiApIface_1_5(GetInstanceName());
@@ -89,6 +89,34 @@
     EXPECT_EQ(WifiStatusCode::SUCCESS, status.code);
 }
 
+/**
+ * getBridgedInstances in non-bridged mode
+ */
+TEST_P(WifiApIfaceHidlTest, getBridgedInstancesTest) {
+    sp<IWifiApIface> wifi_ap_iface = getWifiApIface_1_5(GetInstanceName());
+    ASSERT_NE(nullptr, wifi_ap_iface.get());
+    const auto& status_and_instances =
+        HIDL_INVOKE(wifi_ap_iface, getBridgedInstances);
+    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_instances.first.code);
+    const auto& instances = status_and_instances.second;
+    EXPECT_EQ(0, instances.size());
+}
+
+/**
+ * getBridgedInstances in bridged AP mode.
+ */
+TEST_P(WifiApIfaceHidlTest, getBridgedInstancesInBridgedModeTest) {
+    if (!isBridgedSupport_) GTEST_SKIP() << "Missing Bridged AP support";
+    sp<IWifiApIface> wifi_ap_iface =
+        getBridgedWifiApIface_1_5(GetInstanceName());
+    ASSERT_NE(nullptr, wifi_ap_iface.get());
+    const auto& status_and_instances =
+        HIDL_INVOKE(wifi_ap_iface, getBridgedInstances);
+    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_instances.first.code);
+    const auto& instances = status_and_instances.second;
+    EXPECT_EQ(2, instances.size());
+}
+
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiApIfaceHidlTest);
 INSTANTIATE_TEST_SUITE_P(
     PerInstance, WifiApIfaceHidlTest,
diff --git a/wifi/1.5/vts/functional/wifi_chip_hidl_ap_test.cpp b/wifi/1.5/vts/functional/wifi_chip_hidl_ap_test.cpp
index 922c9a7..d6a0408 100644
--- a/wifi/1.5/vts/functional/wifi_chip_hidl_ap_test.cpp
+++ b/wifi/1.5/vts/functional/wifi_chip_hidl_ap_test.cpp
@@ -101,14 +101,23 @@
     ASSERT_NE(nullptr, wifi_ap_iface.get());
     const auto& status_and_name = HIDL_INVOKE(wifi_ap_iface, getName);
     EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_name.first.code);
-    // TODO: b/173999527, add API to get instance name to replace it.
-    std::string br_name = status_and_name.second;  // ap_br_ is the pre-fix
-    std::string instance_name =
-        br_name.substr(6, br_name.length());  // remove the pre-fex
+    std::string br_name = status_and_name.second;
+    const auto& status_and_instances =
+        HIDL_INVOKE(wifi_ap_iface, getBridgedInstances);
+    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_instances.first.code);
+    const auto& instances = status_and_instances.second;
+    EXPECT_EQ(2, instances.size());
     const auto& status_code =
         HIDL_INVOKE(wifi_chip_, removeIfaceInstanceFromBridgedApIface, br_name,
-                    instance_name);
+                    instances[0]);
     EXPECT_EQ(WifiStatusCode::SUCCESS, status_code.code);
+    const auto& status_and_instances_after_remove =
+        HIDL_INVOKE(wifi_ap_iface, getBridgedInstances);
+    EXPECT_EQ(WifiStatusCode::SUCCESS,
+              status_and_instances_after_remove.first.code);
+    const auto& instances_after_remove =
+        status_and_instances_after_remove.second;
+    EXPECT_EQ(1, instances_after_remove.size());
 }
 
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiChipHidlTest);
diff --git a/wifi/1.5/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.5/vts/functional/wifi_chip_hidl_test.cpp
index 36a8448..509f1bd 100644
--- a/wifi/1.5/vts/functional/wifi_chip_hidl_test.cpp
+++ b/wifi/1.5/vts/functional/wifi_chip_hidl_test.cpp
@@ -45,6 +45,7 @@
 using ::android::hardware::wifi::V1_4::IWifiChipEventCallback;
 using ::android::hardware::wifi::V1_5::IWifiChip;
 using ::android::hardware::wifi::V1_5::WifiBand;
+using ::android::hardware::wifi::V1_5::WifiIfaceMode;
 
 /**
  * Fixture to use for all Wifi chip HIDL interface tests.
@@ -187,6 +188,23 @@
               HIDL_INVOKE(wifi_chip_, setCountryCode, kCountryCode).code);
 }
 
+/* getUsableChannels:
+ * Ensure that a call to getUsableChannels will return with a success
+ * status for valid inputs.
+ */
+TEST_P(WifiChipHidlTest, getUsableChannels) {
+    uint32_t ifaceModeMask =
+        WifiIfaceMode::IFACE_MODE_P2P_CLIENT | WifiIfaceMode::IFACE_MODE_P2P_GO;
+    configureChipForIfaceType(IfaceType::STA, true);
+    WifiBand band = WifiBand::BAND_24GHZ_5GHZ_6GHZ;
+    const auto& statusNonEmpty =
+        HIDL_INVOKE(wifi_chip_, getUsableChannels, band, ifaceModeMask);
+    if (statusNonEmpty.first.code != WifiStatusCode::SUCCESS) {
+        EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED,
+                  statusNonEmpty.first.code);
+    }
+}
+
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiChipHidlTest);
 INSTANTIATE_TEST_SUITE_P(
     PerInstance, WifiChipHidlTest,