Merge "Support P010 with Gralloc2 on Gralloc1 passthrough"
diff --git a/audio/aidl/common/include/Utils.h b/audio/aidl/common/include/Utils.h
index 74549d4..1026134 100644
--- a/audio/aidl/common/include/Utils.h
+++ b/audio/aidl/common/include/Utils.h
@@ -16,8 +16,13 @@
 
 #pragma once
 
+#include <initializer_list>
+#include <type_traits>
+
 #include <aidl/android/media/audio/common/AudioChannelLayout.h>
 #include <aidl/android/media/audio/common/AudioFormatDescription.h>
+#include <aidl/android/media/audio/common/AudioInputFlags.h>
+#include <aidl/android/media/audio/common/AudioOutputFlags.h>
 #include <aidl/android/media/audio/common/PcmType.h>
 
 namespace android::hardware::audio::common {
@@ -78,4 +83,34 @@
     return 0;
 }
 
+// The helper functions defined below are only applicable to the case when an enum type
+// specifies zero-based bit positions, not bit masks themselves. This is why instantiation
+// is restricted to certain enum types.
+template <typename E>
+using is_bit_position_enum = std::integral_constant<
+        bool, std::is_same_v<E, ::aidl::android::media::audio::common::AudioInputFlags> ||
+                      std::is_same_v<E, ::aidl::android::media::audio::common::AudioOutputFlags>>;
+
+template <typename E, typename U = std::underlying_type_t<E>,
+          typename = std::enable_if_t<is_bit_position_enum<E>::value>>
+constexpr U makeBitPositionFlagMask(E flag) {
+    return 1 << static_cast<U>(flag);
+}
+
+template <typename E, typename U = std::underlying_type_t<E>,
+          typename = std::enable_if_t<is_bit_position_enum<E>::value>>
+constexpr bool isBitPositionFlagSet(U mask, E flag) {
+    return (mask & makeBitPositionFlagMask(flag)) != 0;
+}
+
+template <typename E, typename U = std::underlying_type_t<E>,
+          typename = std::enable_if_t<is_bit_position_enum<E>::value>>
+constexpr U makeBitPositionFlagMask(std::initializer_list<E> flags) {
+    U result = 0;
+    for (const auto flag : flags) {
+        result |= makeBitPositionFlagMask(flag);
+    }
+    return result;
+}
+
 }  // namespace android::hardware::audio::common
diff --git a/audio/aidl/default/Configuration.cpp b/audio/aidl/default/Configuration.cpp
index f5d679b..a3e5ff7 100644
--- a/audio/aidl/default/Configuration.cpp
+++ b/audio/aidl/default/Configuration.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <Utils.h>
 #include <aidl/android/media/audio/common/AudioChannelLayout.h>
 #include <aidl/android/media/audio/common/AudioDeviceType.h>
 #include <aidl/android/media/audio/common/AudioFormatDescription.h>
@@ -40,6 +41,7 @@
 using aidl::android::media::audio::common::AudioProfile;
 using aidl::android::media::audio::common::Int;
 using aidl::android::media::audio::common::PcmType;
+using android::hardware::audio::common::makeBitPositionFlagMask;
 
 namespace aidl::android::hardware::audio::core::internal {
 
@@ -193,7 +195,7 @@
                                  createDeviceExt(AudioDeviceType::OUT_SPEAKER, 0)));
 
         AudioPort primaryOutMix = createPort(c.nextPortId++, "primary output",
-                                             1 << static_cast<int32_t>(AudioOutputFlags::PRIMARY),
+                                             makeBitPositionFlagMask(AudioOutputFlags::PRIMARY),
                                              false, createPortMixExt(1, 1));
         primaryOutMix.profiles.insert(primaryOutMix.profiles.begin(),
                                       standardPcmAudioProfiles.begin(),
@@ -202,9 +204,9 @@
 
         AudioPort compressedOffloadOutMix =
                 createPort(c.nextPortId++, "compressed offload",
-                           1 << static_cast<int32_t>(AudioOutputFlags::DIRECT) |
-                                   1 << static_cast<int32_t>(AudioOutputFlags::COMPRESS_OFFLOAD) |
-                                   1 << static_cast<int32_t>(AudioOutputFlags::NON_BLOCKING),
+                           makeBitPositionFlagMask({AudioOutputFlags::DIRECT,
+                                                    AudioOutputFlags::COMPRESS_OFFLOAD,
+                                                    AudioOutputFlags::NON_BLOCKING}),
                            false, createPortMixExt(1, 1));
         compressedOffloadOutMix.profiles.push_back(
                 createProfile(::android::MEDIA_MIMETYPE_AUDIO_MPEG,
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index af033d0..deaca49 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -43,6 +43,7 @@
 using aidl::android::media::audio::common::Int;
 using aidl::android::media::audio::common::PcmType;
 using android::hardware::audio::common::getFrameSizeInBytes;
+using android::hardware::audio::common::isBitPositionFlagSet;
 
 namespace aidl::android::hardware::audio::core {
 
@@ -125,11 +126,11 @@
     }
     const auto& flags = portConfigIt->flags.value();
     if ((flags.getTag() == AudioIoFlags::Tag::input &&
-         (flags.get<AudioIoFlags::Tag::input>() &
-          1 << static_cast<int32_t>(AudioInputFlags::MMAP_NOIRQ)) == 0) ||
+         !isBitPositionFlagSet(flags.get<AudioIoFlags::Tag::input>(),
+                               AudioInputFlags::MMAP_NOIRQ)) ||
         (flags.getTag() == AudioIoFlags::Tag::output &&
-         (flags.get<AudioIoFlags::Tag::output>() &
-          1 << static_cast<int32_t>(AudioOutputFlags::MMAP_NOIRQ)) == 0)) {
+         !isBitPositionFlagSet(flags.get<AudioIoFlags::Tag::output>(),
+                               AudioOutputFlags::MMAP_NOIRQ))) {
         StreamContext temp(
                 std::make_unique<StreamContext::CommandMQ>(1, true /*configureEventFlagWord*/),
                 std::make_unique<StreamContext::ReplyMQ>(1, true /*configureEventFlagWord*/),
@@ -478,9 +479,9 @@
                    << " does not correspond to an output mix port";
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
-    if ((port->flags.get<AudioIoFlags::Tag::output>() &
-         1 << static_cast<int32_t>(AudioOutputFlags::COMPRESS_OFFLOAD)) != 0 &&
-        !in_args.offloadInfo.has_value()) {
+    const bool isOffload = isBitPositionFlagSet(port->flags.get<AudioIoFlags::Tag::output>(),
+                                                AudioOutputFlags::COMPRESS_OFFLOAD);
+    if (isOffload && !in_args.offloadInfo.has_value()) {
         LOG(ERROR) << __func__ << ": port id " << port->id
                    << " has COMPRESS_OFFLOAD flag set, requires offload info";
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
index 816cdb1..488edf1 100644
--- a/audio/aidl/default/include/core-impl/Stream.h
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -229,10 +229,9 @@
     }
     void setStreamIsConnected(bool connected) {
         std::visit(
-                [&](auto&& ws) -> bool {
+                [&](auto&& ws) {
                     auto s = ws.lock();
                     if (s) s->setIsConnected(connected);
-                    return !!s;
                 },
                 mStream);
     }
@@ -253,7 +252,7 @@
     }
     void insert(int32_t portId, int32_t portConfigId, StreamWrapper sw) {
         mStreams.insert(std::pair{portConfigId, sw});
-        mStreams.insert(std::pair{portId, sw});
+        mStreams.insert(std::pair{portId, std::move(sw)});
     }
     void setStreamIsConnected(int32_t portConfigId, bool connected) {
         if (auto it = mStreams.find(portConfigId); it != mStreams.end()) {
diff --git a/audio/aidl/vts/ModuleConfig.cpp b/audio/aidl/vts/ModuleConfig.cpp
index e36ab4a..33c5b72 100644
--- a/audio/aidl/vts/ModuleConfig.cpp
+++ b/audio/aidl/vts/ModuleConfig.cpp
@@ -17,6 +17,7 @@
 #include <algorithm>
 #include <chrono>
 
+#include <Utils.h>
 #include <aidl/android/media/audio/common/AudioIoFlags.h>
 #include <aidl/android/media/audio/common/AudioOutputFlags.h>
 
@@ -39,14 +40,15 @@
 using aidl::android::media::audio::common::AudioProfile;
 using aidl::android::media::audio::common::AudioUsage;
 using aidl::android::media::audio::common::Int;
+using android::hardware::audio::common::isBitPositionFlagSet;
 
 // static
 std::optional<AudioOffloadInfo> ModuleConfig::generateOffloadInfoIfNeeded(
         const AudioPortConfig& portConfig) {
     if (portConfig.flags.has_value() &&
         portConfig.flags.value().getTag() == AudioIoFlags::Tag::output &&
-        (portConfig.flags.value().get<AudioIoFlags::Tag::output>() &
-         1 << static_cast<int>(AudioOutputFlags::COMPRESS_OFFLOAD)) != 0) {
+        isBitPositionFlagSet(portConfig.flags.value().get<AudioIoFlags::Tag::output>(),
+                             AudioOutputFlags::COMPRESS_OFFLOAD)) {
         AudioOffloadInfo offloadInfo;
         offloadInfo.base.sampleRate = portConfig.sampleRate.value().value;
         offloadInfo.base.channelMask = portConfig.channelMask.value();
@@ -123,6 +125,23 @@
     return result;
 }
 
+std::vector<AudioPort> ModuleConfig::getOffloadMixPorts(bool attachedOnly, bool singlePort) const {
+    std::vector<AudioPort> result;
+    const auto mixPorts = getMixPorts(false /*isInput*/);
+    auto offloadPortIt = mixPorts.begin();
+    while (offloadPortIt != mixPorts.end()) {
+        offloadPortIt = std::find_if(offloadPortIt, mixPorts.end(), [&](const AudioPort& port) {
+            return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
+                                        AudioOutputFlags::COMPRESS_OFFLOAD) &&
+                   (!attachedOnly || !getAttachedSinkDevicesPortsForMixPort(port).empty());
+        });
+        if (offloadPortIt == mixPorts.end()) break;
+        result.push_back(*offloadPortIt++);
+        if (singlePort) break;
+    }
+    return result;
+}
+
 std::vector<AudioPort> ModuleConfig::getAttachedDevicesPortsForMixPort(
         bool isInput, const AudioPortConfig& mixPortConfig) const {
     const auto mixPortIt = findById<AudioPort>(mPorts, mixPortConfig.portId);
diff --git a/audio/aidl/vts/ModuleConfig.h b/audio/aidl/vts/ModuleConfig.h
index 552f971..dc109a7 100644
--- a/audio/aidl/vts/ModuleConfig.h
+++ b/audio/aidl/vts/ModuleConfig.h
@@ -48,6 +48,8 @@
     std::vector<aidl::android::media::audio::common::AudioPort> getMixPorts(bool isInput) const {
         return isInput ? getInputMixPorts() : getOutputMixPorts();
     }
+    std::vector<aidl::android::media::audio::common::AudioPort> getOffloadMixPorts(
+            bool attachedOnly, bool singlePort) const;
 
     std::vector<aidl::android::media::audio::common::AudioPort> getAttachedDevicesPortsForMixPort(
             bool isInput, const aidl::android::media::audio::common::AudioPort& mixPort) const {
diff --git a/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
index ab70ec4..2659f79 100644
--- a/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
@@ -26,6 +26,7 @@
 #include <android-base/logging.h>
 
 #include <StreamWorker.h>
+#include <Utils.h>
 #include <aidl/Gtest.h>
 #include <aidl/Vintf.h>
 #include <aidl/android/hardware/audio/core/IConfig.h>
@@ -64,6 +65,7 @@
 using aidl::android::media::audio::common::AudioPortExt;
 using aidl::android::media::audio::common::AudioSource;
 using aidl::android::media::audio::common::AudioUsage;
+using android::hardware::audio::common::isBitPositionFlagSet;
 using android::hardware::audio::common::StreamLogic;
 using android::hardware::audio::common::StreamWorker;
 using ndk::ScopedAStatus;
@@ -97,20 +99,6 @@
     return AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>(std::to_string(++nextId));
 }
 
-template <typename T>
-struct IsInput {
-    constexpr operator bool() const;
-};
-
-template <>
-constexpr IsInput<IStreamIn>::operator bool() const {
-    return true;
-}
-template <>
-constexpr IsInput<IStreamOut>::operator bool() const {
-    return false;
-}
-
 // All 'With*' classes are move-only because they are associated with some
 // resource or state of a HAL module.
 class WithDebugFlags {
@@ -864,12 +852,12 @@
         ASSERT_EQ(EX_NONE, status.getExceptionCode()) << status;
     }
     std::optional<int32_t> primaryMixPort;
-    constexpr int primaryOutputFlag = 1 << static_cast<int>(AudioOutputFlags::PRIMARY);
     for (const auto& port : ports) {
         if (port.ext.getTag() != AudioPortExt::Tag::mix) continue;
         const auto& mixPort = port.ext.get<AudioPortExt::Tag::mix>();
         if (port.flags.getTag() == AudioIoFlags::Tag::output &&
-            ((port.flags.get<AudioIoFlags::Tag::output>() & primaryOutputFlag) != 0)) {
+            isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
+                                 AudioOutputFlags::PRIMARY)) {
             EXPECT_FALSE(primaryMixPort.has_value())
                     << "At least two mix ports have PRIMARY flag set: " << primaryMixPort.value()
                     << " and " << port.id;
@@ -1447,14 +1435,15 @@
         EXPECT_NO_FATAL_FAILURE(OpenTwiceSamePortConfigImpl(portConfig.value()));
     }
 
-    void ReadOrWrite(bool useImpl2, bool testObservablePosition) {
+    void ReadOrWrite(bool useSetupSequence2, bool validateObservablePosition) {
         const auto allPortConfigs =
                 moduleConfig->getPortConfigsForMixPorts(IOTraits<Stream>::is_input);
         if (allPortConfigs.empty()) {
             GTEST_SKIP() << "No mix ports have attached devices";
         }
         for (const auto& portConfig : allPortConfigs) {
-            EXPECT_NO_FATAL_FAILURE(ReadOrWriteImpl(portConfig, useImpl2, testObservablePosition))
+            EXPECT_NO_FATAL_FAILURE(
+                    ReadOrWriteImpl(portConfig, useSetupSequence2, validateObservablePosition))
                     << portConfig.toString();
         }
     }
@@ -1510,17 +1499,20 @@
         EXPECT_GT(frames, framesInitial);
     }
 
-    void ReadOrWriteImpl(const AudioPortConfig& portConfig, bool useImpl2,
-                         bool testObservablePosition) {
-        if (!useImpl2) {
-            ASSERT_NO_FATAL_FAILURE(ReadOrWriteImpl1(portConfig, testObservablePosition));
+    void ReadOrWriteImpl(const AudioPortConfig& portConfig, bool useSetupSequence2,
+                         bool validateObservablePosition) {
+        if (!useSetupSequence2) {
+            ASSERT_NO_FATAL_FAILURE(
+                    ReadOrWriteSetupSequence1(portConfig, validateObservablePosition));
         } else {
-            ASSERT_NO_FATAL_FAILURE(ReadOrWriteImpl2(portConfig, testObservablePosition));
+            ASSERT_NO_FATAL_FAILURE(
+                    ReadOrWriteSetupSequence2(portConfig, validateObservablePosition));
         }
     }
 
     // Set up a patch first, then open a stream.
-    void ReadOrWriteImpl1(const AudioPortConfig& portConfig, bool testObservablePosition) {
+    void ReadOrWriteSetupSequence1(const AudioPortConfig& portConfig,
+                                   bool validateObservablePosition) {
         auto devicePorts = moduleConfig->getAttachedDevicesPortsForMixPort(
                 IOTraits<Stream>::is_input, portConfig);
         ASSERT_FALSE(devicePorts.empty());
@@ -1534,13 +1526,14 @@
 
         ASSERT_TRUE(worker.start());
         ASSERT_TRUE(worker.waitForAtLeastOneCycle());
-        if (testObservablePosition) {
+        if (validateObservablePosition) {
             ASSERT_NO_FATAL_FAILURE(WaitForObservablePositionAdvance(worker));
         }
     }
 
     // Open a stream, then set up a patch for it.
-    void ReadOrWriteImpl2(const AudioPortConfig& portConfig, bool testObservablePosition) {
+    void ReadOrWriteSetupSequence2(const AudioPortConfig& portConfig,
+                                   bool validateObservablePosition) {
         WithStream<Stream> stream(portConfig);
         ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
         typename IOTraits<Stream>::Worker worker(*stream.getContext());
@@ -1554,7 +1547,7 @@
 
         ASSERT_TRUE(worker.start());
         ASSERT_TRUE(worker.waitForAtLeastOneCycle());
-        if (testObservablePosition) {
+        if (validateObservablePosition) {
             ASSERT_NO_FATAL_FAILURE(WaitForObservablePositionAdvance(worker));
         }
     }
@@ -1609,19 +1602,24 @@
 TEST_IO_STREAM(OpenInvalidDirection);
 TEST_IO_STREAM(OpenOverMaxCount);
 TEST_IO_STREAM(OpenTwiceSamePortConfig);
-TEST_IO_STREAM_2(ReadOrWrite, false, false);
-TEST_IO_STREAM_2(ReadOrWrite, true, false);
-TEST_IO_STREAM_2(ReadOrWrite, false, true);
-TEST_IO_STREAM_2(ReadOrWrite, true, true);
+// Use of constants makes comprehensible test names.
+constexpr bool SetupSequence1 = false;
+constexpr bool SetupSequence2 = true;
+constexpr bool SetupOnly = false;
+constexpr bool ValidateObservablePosition = true;
+TEST_IO_STREAM_2(ReadOrWrite, SetupSequence1, SetupOnly);
+TEST_IO_STREAM_2(ReadOrWrite, SetupSequence2, SetupOnly);
+TEST_IO_STREAM_2(ReadOrWrite, SetupSequence1, ValidateObservablePosition);
+TEST_IO_STREAM_2(ReadOrWrite, SetupSequence2, ValidateObservablePosition);
 TEST_IO_STREAM(ResetPortConfigWithOpenStream);
 TEST_IO_STREAM(SendInvalidCommand);
 
 TEST_P(AudioStreamOut, OpenTwicePrimary) {
     const auto mixPorts = moduleConfig->getMixPorts(false);
     auto primaryPortIt = std::find_if(mixPorts.begin(), mixPorts.end(), [](const AudioPort& port) {
-        constexpr int primaryOutputFlag = 1 << static_cast<int>(AudioOutputFlags::PRIMARY);
         return port.flags.getTag() == AudioIoFlags::Tag::output &&
-               (port.flags.get<AudioIoFlags::Tag::output>() & primaryOutputFlag) != 0;
+               isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
+                                    AudioOutputFlags::PRIMARY);
     });
     if (primaryPortIt == mixPorts.end()) {
         GTEST_SKIP() << "No primary mix port";
@@ -1635,19 +1633,14 @@
 }
 
 TEST_P(AudioStreamOut, RequireOffloadInfo) {
-    const auto mixPorts = moduleConfig->getMixPorts(false);
-    auto offloadPortIt = std::find_if(mixPorts.begin(), mixPorts.end(), [&](const AudioPort& port) {
-        constexpr int compressOffloadFlag = 1
-                                            << static_cast<int>(AudioOutputFlags::COMPRESS_OFFLOAD);
-        return port.flags.getTag() == AudioIoFlags::Tag::output &&
-               (port.flags.get<AudioIoFlags::Tag::output>() & compressOffloadFlag) != 0 &&
-               !moduleConfig->getAttachedSinkDevicesPortsForMixPort(port).empty();
-    });
-    if (offloadPortIt == mixPorts.end()) {
+    const auto offloadMixPorts =
+            moduleConfig->getOffloadMixPorts(true /*attachedOnly*/, true /*singlePort*/);
+    if (offloadMixPorts.empty()) {
         GTEST_SKIP()
                 << "No mix port for compressed offload that could be routed to attached devices";
     }
-    const auto portConfig = moduleConfig->getSingleConfigForMixPort(false, *offloadPortIt);
+    const auto portConfig =
+            moduleConfig->getSingleConfigForMixPort(false, *offloadMixPorts.begin());
     ASSERT_TRUE(portConfig.has_value())
             << "No profiles specified for the compressed offload mix port";
     StreamDescriptor descriptor;
diff --git a/bluetooth/audio/utils/Android.bp b/bluetooth/audio/utils/Android.bp
index d08cb0a..674dd11 100644
--- a/bluetooth/audio/utils/Android.bp
+++ b/bluetooth/audio/utils/Android.bp
@@ -40,9 +40,13 @@
         "aidl_session/BluetoothAudioCodecs.cpp",
         "aidl_session/BluetoothAudioSession.cpp",
         "aidl_session/HidlToAidlMiddleware.cpp",
+        "aidl_session/BluetoothLeAudioCodecsProvider.cpp",
     ],
     export_include_dirs: ["aidl_session/"],
-    header_libs: ["libhardware_headers"],
+    header_libs: [
+        "libhardware_headers",
+        "libxsdc-utils",
+    ],
     shared_libs: [
         "android.hardware.bluetooth.audio@2.0",
         "android.hardware.bluetooth.audio@2.1",
@@ -53,5 +57,15 @@
         "liblog",
         "android.hardware.bluetooth.audio-V2-ndk",
         "libhidlbase",
+        "libxml2",
     ],
+    generated_sources: ["le_audio_codec_capabilities"],
+    generated_headers: ["le_audio_codec_capabilities"],
+}
+
+xsd_config {
+    name: "le_audio_codec_capabilities",
+    srcs: ["le_audio_codec_capabilities/le_audio_codec_capabilities.xsd"],
+    package_name: "aidl.android.hardware.bluetooth.audio.setting",
+    api_dir: "le_audio_codec_capabilities/schema",
 }
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
index 036d6cd..855dd28 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
@@ -32,6 +32,8 @@
 #include <aidl/android/hardware/bluetooth/audio/SbcChannelMode.h>
 #include <android-base/logging.h>
 
+#include "BluetoothLeAudioCodecsProvider.h"
+
 namespace aidl {
 namespace android {
 namespace hardware {
@@ -96,67 +98,6 @@
 
 std::vector<LeAudioCodecCapabilitiesSetting> kDefaultOffloadLeAudioCapabilities;
 
-static const UnicastCapability kInvalidUnicastCapability = {
-    .codecType = CodecType::UNKNOWN};
-
-static const BroadcastCapability kInvalidBroadcastCapability = {
-    .codecType = CodecType::UNKNOWN};
-
-// Default Supported Codecs
-// LC3 16_1: sample rate: 16 kHz, frame duration: 7.5 ms, octets per frame: 30
-static const Lc3Capabilities kLc3Capability_16_1 = {
-    .samplingFrequencyHz = {16000},
-    .frameDurationUs = {7500},
-    .octetsPerFrame = {30}};
-
-// Default Supported Codecs
-// LC3 16_2: sample rate: 16 kHz, frame duration: 10 ms, octets per frame: 40
-static const Lc3Capabilities kLc3Capability_16_2 = {
-    .samplingFrequencyHz = {16000},
-    .frameDurationUs = {10000},
-    .octetsPerFrame = {40}};
-
-// Default Supported Codecs
-// LC3 24_2: sample rate: 24 kHz, frame duration: 10 ms, octets per frame: 60
-static const Lc3Capabilities kLc3Capability_24_2 = {
-    .samplingFrequencyHz = {24000},
-    .frameDurationUs = {10000},
-    .octetsPerFrame = {60}};
-
-// Default Supported Codecs
-// LC3 32_2: sample rate: 32 kHz, frame duration: 10 ms, octets per frame: 80
-static const Lc3Capabilities kLc3Capability_32_2 = {
-    .samplingFrequencyHz = {32000},
-    .frameDurationUs = {10000},
-    .octetsPerFrame = {80}};
-
-// Default Supported Codecs
-// LC3 48_4: sample rate: 48 kHz, frame duration: 10 ms, octets per frame: 120
-static const Lc3Capabilities kLc3Capability_48_4 = {
-    .samplingFrequencyHz = {48000},
-    .frameDurationUs = {10000},
-    .octetsPerFrame = {120}};
-
-static const std::vector<Lc3Capabilities> supportedLc3CapabilityList = {
-    kLc3Capability_48_4, kLc3Capability_32_2, kLc3Capability_24_2,
-    kLc3Capability_16_2, kLc3Capability_16_1};
-
-static AudioLocation stereoAudio = static_cast<AudioLocation>(
-    static_cast<uint8_t>(AudioLocation::FRONT_LEFT) |
-    static_cast<uint8_t>(AudioLocation::FRONT_RIGHT));
-static AudioLocation monoAudio = AudioLocation::UNKNOWN;
-
-// Stores the supported setting of audio location, connected device, and the
-// channel count for each device
-std::vector<std::tuple<AudioLocation, uint8_t, uint8_t>>
-    supportedDeviceSetting = {
-        // Stereo, two connected device, one for L one for R
-        std::make_tuple(stereoAudio, 2, 1),
-        // Stereo, one connected device for both L and R
-        std::make_tuple(stereoAudio, 1, 2),
-        // Mono
-        std::make_tuple(monoAudio, 1, 1)};
-
 template <class T>
 bool BluetoothAudioCodecs::ContainedInVector(
     const std::vector<T>& vector, const typename identity<T>::type& target) {
@@ -444,19 +385,6 @@
   return false;
 }
 
-UnicastCapability composeUnicastLc3Capability(
-    AudioLocation audioLocation, uint8_t deviceCnt, uint8_t channelCount,
-    const Lc3Capabilities& capability) {
-  return {
-      .codecType = CodecType::LC3,
-      .supportedChannel = audioLocation,
-      .deviceCount = deviceCnt,
-      .channelCountPerDevice = channelCount,
-      .leAudioCodecCapabilities =
-          UnicastCapability::LeAudioCodecCapabilities(capability),
-  };
-}
-
 std::vector<LeAudioCodecCapabilitiesSetting>
 BluetoothAudioCodecs::GetLeAudioOffloadCodecCapabilities(
     const SessionType& session_type) {
@@ -470,41 +398,8 @@
   }
 
   if (kDefaultOffloadLeAudioCapabilities.empty()) {
-    for (auto [audioLocation, deviceCnt, channelCount] :
-         supportedDeviceSetting) {
-      for (auto capability : supportedLc3CapabilityList) {
-        UnicastCapability lc3Capability = composeUnicastLc3Capability(
-            audioLocation, deviceCnt, channelCount, capability);
-        UnicastCapability lc3MonoDecodeCapability =
-            composeUnicastLc3Capability(monoAudio, 1, 1, capability);
-
-        // Adds the capability for encode only
-        kDefaultOffloadLeAudioCapabilities.push_back(
-            {.unicastEncodeCapability = lc3Capability,
-             .unicastDecodeCapability = kInvalidUnicastCapability,
-             .broadcastCapability = kInvalidBroadcastCapability});
-
-        // Adds the capability for decode only
-        kDefaultOffloadLeAudioCapabilities.push_back(
-            {.unicastEncodeCapability = kInvalidUnicastCapability,
-             .unicastDecodeCapability = lc3Capability,
-             .broadcastCapability = kInvalidBroadcastCapability});
-
-        // Adds the capability for the case that encode and decode exist at the
-        // same time(force one active device for decode)
-        kDefaultOffloadLeAudioCapabilities.push_back(
-            {.unicastEncodeCapability = lc3Capability,
-             .unicastDecodeCapability = lc3MonoDecodeCapability,
-             .broadcastCapability = kInvalidBroadcastCapability});
-
-        // Adds the capability for the case that encode and decode exist at the
-        // same time
-        kDefaultOffloadLeAudioCapabilities.push_back(
-            {.unicastEncodeCapability = lc3Capability,
-             .unicastDecodeCapability = lc3Capability,
-             .broadcastCapability = kInvalidBroadcastCapability});
-      }
-    }
+    kDefaultOffloadLeAudioCapabilities =
+        BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities();
   }
 
   return kDefaultOffloadLeAudioCapabilities;
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
new file mode 100644
index 0000000..bf49270
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BTAudioCodecsProviderAidl"
+
+#include "BluetoothLeAudioCodecsProvider.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+static const char* kLeAudioCodecCapabilitiesFile =
+    "/vendor/etc/le_audio_codec_capabilities.xml";
+
+static const AudioLocation kStereoAudio = static_cast<AudioLocation>(
+    static_cast<uint8_t>(AudioLocation::FRONT_LEFT) |
+    static_cast<uint8_t>(AudioLocation::FRONT_RIGHT));
+static const AudioLocation kMonoAudio = AudioLocation::UNKNOWN;
+
+static std::vector<LeAudioCodecCapabilitiesSetting> leAudioCodecCapabilities;
+
+std::vector<LeAudioCodecCapabilitiesSetting>
+BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities() {
+  if (!leAudioCodecCapabilities.empty()) {
+    return leAudioCodecCapabilities;
+  }
+
+  const auto le_audio_offload_setting =
+      setting::readLeAudioOffloadSetting(kLeAudioCodecCapabilitiesFile);
+  if (!le_audio_offload_setting.has_value()) {
+    LOG(ERROR) << __func__ << ": Failed to read "
+               << kLeAudioCodecCapabilitiesFile;
+    return {};
+  }
+
+  std::vector<setting::Scenario> supported_scenarios =
+      GetScenarios(le_audio_offload_setting);
+  if (supported_scenarios.empty()) {
+    LOG(ERROR) << __func__ << ": No scenarios in "
+               << kLeAudioCodecCapabilitiesFile;
+    return {};
+  }
+
+  UpdateConfigurationsToMap(le_audio_offload_setting);
+  if (configuration_map_.empty()) {
+    LOG(ERROR) << __func__ << ": No configurations in "
+               << kLeAudioCodecCapabilitiesFile;
+    return {};
+  }
+
+  UpdateCodecConfigurationsToMap(le_audio_offload_setting);
+  if (codec_configuration_map_.empty()) {
+    LOG(ERROR) << __func__ << ": No codec configurations in "
+               << kLeAudioCodecCapabilitiesFile;
+    return {};
+  }
+
+  UpdateStrategyConfigurationsToMap(le_audio_offload_setting);
+  if (strategy_configuration_map_.empty()) {
+    LOG(ERROR) << __func__ << ": No strategy configurations in "
+               << kLeAudioCodecCapabilitiesFile;
+    return {};
+  }
+
+  leAudioCodecCapabilities =
+      ComposeLeAudioCodecCapabilities(supported_scenarios);
+  return leAudioCodecCapabilities;
+}
+
+std::vector<setting::Scenario> BluetoothLeAudioCodecsProvider::GetScenarios(
+    const std::optional<setting::LeAudioOffloadSetting>&
+        le_audio_offload_setting) {
+  std::vector<setting::Scenario> supported_scenarios;
+  if (le_audio_offload_setting->hasScenarioList()) {
+    for (const auto& scenario_list :
+         le_audio_offload_setting->getScenarioList()) {
+      if (!scenario_list.hasScenario()) {
+        continue;
+      }
+      for (const auto& scenario : scenario_list.getScenario()) {
+        if (scenario.hasEncode() && scenario.hasDecode()) {
+          supported_scenarios.push_back(scenario);
+        }
+      }
+    }
+  }
+  return supported_scenarios;
+}
+
+void BluetoothLeAudioCodecsProvider::UpdateConfigurationsToMap(
+    const std::optional<setting::LeAudioOffloadSetting>&
+        le_audio_offload_setting) {
+  if (le_audio_offload_setting->hasConfigurationList()) {
+    for (const auto& configuration_list :
+         le_audio_offload_setting->getConfigurationList()) {
+      if (!configuration_list.hasConfiguration()) {
+        continue;
+      }
+      for (const auto& configuration : configuration_list.getConfiguration()) {
+        if (configuration.hasName() && configuration.hasCodecConfiguration() &&
+            configuration.hasStrategyConfiguration()) {
+          configuration_map_.insert(
+              make_pair(configuration.getName(), configuration));
+        }
+      }
+    }
+  }
+}
+
+void BluetoothLeAudioCodecsProvider::UpdateCodecConfigurationsToMap(
+    const std::optional<setting::LeAudioOffloadSetting>&
+        le_audio_offload_setting) {
+  if (le_audio_offload_setting->hasCodecConfigurationList()) {
+    for (const auto& codec_configuration_list :
+         le_audio_offload_setting->getCodecConfigurationList()) {
+      if (!codec_configuration_list.hasCodecConfiguration()) {
+        continue;
+      }
+      for (const auto& codec_configuration :
+           codec_configuration_list.getCodecConfiguration()) {
+        if (IsValidCodecConfiguration(codec_configuration)) {
+          codec_configuration_map_.insert(
+              make_pair(codec_configuration.getName(), codec_configuration));
+        }
+      }
+    }
+  }
+}
+
+void BluetoothLeAudioCodecsProvider::UpdateStrategyConfigurationsToMap(
+    const std::optional<setting::LeAudioOffloadSetting>&
+        le_audio_offload_setting) {
+  if (le_audio_offload_setting->hasStrategyConfigurationList()) {
+    for (const auto& strategy_configuration_list :
+         le_audio_offload_setting->getStrategyConfigurationList()) {
+      if (!strategy_configuration_list.hasStrategyConfiguration()) {
+        continue;
+      }
+      for (const auto& strategy_configuration :
+           strategy_configuration_list.getStrategyConfiguration()) {
+        if (IsValidStrategyConfiguration(strategy_configuration)) {
+          strategy_configuration_map_.insert(make_pair(
+              strategy_configuration.getName(), strategy_configuration));
+        }
+      }
+    }
+  }
+}
+
+std::vector<LeAudioCodecCapabilitiesSetting>
+BluetoothLeAudioCodecsProvider::ComposeLeAudioCodecCapabilities(
+    const std::vector<setting::Scenario>& supported_scenarios) {
+  std::vector<LeAudioCodecCapabilitiesSetting> le_audio_codec_capabilities;
+  for (const auto& scenario : supported_scenarios) {
+    UnicastCapability unicast_encode_capability =
+        GetUnicastCapability(scenario.getEncode());
+    UnicastCapability unicast_decode_capability =
+        GetUnicastCapability(scenario.getDecode());
+    // encode and decode cannot be unknown at the same time
+    if (unicast_encode_capability.codecType == CodecType::UNKNOWN &&
+        unicast_decode_capability.codecType == CodecType::UNKNOWN) {
+      continue;
+    }
+    BroadcastCapability broadcast_capability = {.codecType =
+                                                    CodecType::UNKNOWN};
+    le_audio_codec_capabilities.push_back(
+        {.unicastEncodeCapability = unicast_encode_capability,
+         .unicastDecodeCapability = unicast_decode_capability,
+         .broadcastCapability = broadcast_capability});
+  }
+  return le_audio_codec_capabilities;
+}
+
+UnicastCapability BluetoothLeAudioCodecsProvider::GetUnicastCapability(
+    const std::string& coding_direction) {
+  if (coding_direction == "invalid") {
+    return {.codecType = CodecType::UNKNOWN};
+  }
+
+  auto configuration_iter = configuration_map_.find(coding_direction);
+  if (configuration_iter == configuration_map_.end()) {
+    return {.codecType = CodecType::UNKNOWN};
+  }
+
+  auto codec_configuration_iter = codec_configuration_map_.find(
+      configuration_iter->second.getCodecConfiguration());
+  if (codec_configuration_iter == codec_configuration_map_.end()) {
+    return {.codecType = CodecType::UNKNOWN};
+  }
+
+  auto strategy_configuration_iter = strategy_configuration_map_.find(
+      configuration_iter->second.getStrategyConfiguration());
+  if (strategy_configuration_iter == strategy_configuration_map_.end()) {
+    return {.codecType = CodecType::UNKNOWN};
+  }
+
+  CodecType codec_type =
+      GetCodecType(codec_configuration_iter->second.getCodec());
+  if (codec_type == CodecType::LC3) {
+    return ComposeUnicastCapability(
+        codec_type,
+        GetAudioLocation(
+            strategy_configuration_iter->second.getAudioLocation()),
+        strategy_configuration_iter->second.getConnectedDevice(),
+        strategy_configuration_iter->second.getChannelCount(),
+        ComposeLc3Capability(codec_configuration_iter->second));
+  }
+  return {.codecType = CodecType::UNKNOWN};
+}
+
+template <class T>
+UnicastCapability BluetoothLeAudioCodecsProvider::ComposeUnicastCapability(
+    const CodecType& codec_type, const AudioLocation& audio_location,
+    const uint8_t& device_cnt, const uint8_t& channel_count,
+    const T& capability) {
+  return {
+      .codecType = codec_type,
+      .supportedChannel = audio_location,
+      .deviceCount = device_cnt,
+      .channelCountPerDevice = channel_count,
+      .leAudioCodecCapabilities =
+          UnicastCapability::LeAudioCodecCapabilities(capability),
+  };
+}
+
+Lc3Capabilities BluetoothLeAudioCodecsProvider::ComposeLc3Capability(
+    const setting::CodecConfiguration& codec_configuration) {
+  return {.samplingFrequencyHz = {codec_configuration.getSamplingFrequency()},
+          .frameDurationUs = {codec_configuration.getFrameDurationUs()},
+          .octetsPerFrame = {codec_configuration.getOctetsPerCodecFrame()}};
+}
+
+AudioLocation BluetoothLeAudioCodecsProvider::GetAudioLocation(
+    const setting::AudioLocation& audio_location) {
+  switch (audio_location) {
+    case setting::AudioLocation::MONO:
+      return kMonoAudio;
+    case setting::AudioLocation::STEREO:
+      return kStereoAudio;
+    default:
+      return AudioLocation::UNKNOWN;
+  }
+}
+
+CodecType BluetoothLeAudioCodecsProvider::GetCodecType(
+    const setting::CodecType& codec_type) {
+  switch (codec_type) {
+    case setting::CodecType::LC3:
+      return CodecType::LC3;
+    default:
+      return CodecType::UNKNOWN;
+  }
+}
+
+bool BluetoothLeAudioCodecsProvider::IsValidCodecConfiguration(
+    const setting::CodecConfiguration& codec_configuration) {
+  return codec_configuration.hasName() && codec_configuration.hasCodec() &&
+         codec_configuration.hasSamplingFrequency() &&
+         codec_configuration.hasFrameDurationUs() &&
+         codec_configuration.hasOctetsPerCodecFrame();
+}
+
+bool BluetoothLeAudioCodecsProvider::IsValidStrategyConfiguration(
+    const setting::StrategyConfiguration& strategy_configuration) {
+  if (!strategy_configuration.hasName() ||
+      !strategy_configuration.hasAudioLocation() ||
+      !strategy_configuration.hasConnectedDevice() ||
+      !strategy_configuration.hasChannelCount()) {
+    return false;
+  }
+  if (strategy_configuration.getAudioLocation() ==
+      setting::AudioLocation::STEREO) {
+    if ((strategy_configuration.getConnectedDevice() == 2 &&
+         strategy_configuration.getChannelCount() == 1) ||
+        (strategy_configuration.getConnectedDevice() == 1 &&
+         strategy_configuration.getChannelCount() == 2)) {
+      // Stereo
+      // 1. two connected device, one for L one for R
+      // 2. one connected device for both L and R
+      return true;
+    }
+  } else if (strategy_configuration.getAudioLocation() ==
+             setting::AudioLocation::MONO) {
+    if (strategy_configuration.getConnectedDevice() == 1 &&
+        strategy_configuration.getChannelCount() == 1) {
+      // Mono
+      return true;
+    }
+  }
+  return false;
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h
new file mode 100644
index 0000000..402235f
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.h>
+#include <android-base/logging.h>
+
+#include <unordered_map>
+
+#include "aidl_android_hardware_bluetooth_audio_setting.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class BluetoothLeAudioCodecsProvider {
+ public:
+  static std::vector<LeAudioCodecCapabilitiesSetting>
+  GetLeAudioCodecCapabilities();
+
+ private:
+  static inline std::unordered_map<std::string, setting::Configuration>
+      configuration_map_;
+  static inline std::unordered_map<std::string, setting::CodecConfiguration>
+      codec_configuration_map_;
+  static inline std::unordered_map<std::string, setting::StrategyConfiguration>
+      strategy_configuration_map_;
+
+  static std::vector<setting::Scenario> GetScenarios(
+      const std::optional<setting::LeAudioOffloadSetting>&
+          le_audio_offload_setting);
+  static void UpdateConfigurationsToMap(
+      const std::optional<setting::LeAudioOffloadSetting>&
+          le_audio_offload_setting);
+  static void UpdateCodecConfigurationsToMap(
+      const std::optional<setting::LeAudioOffloadSetting>&
+          le_audio_offload_setting);
+  static void UpdateStrategyConfigurationsToMap(
+      const std::optional<setting::LeAudioOffloadSetting>&
+          le_audio_offload_setting);
+
+  static std::vector<LeAudioCodecCapabilitiesSetting>
+  ComposeLeAudioCodecCapabilities(
+      const std::vector<setting::Scenario>& supported_scenarios);
+
+  static UnicastCapability GetUnicastCapability(
+      const std::string& coding_direction);
+  template <class T>
+  static inline UnicastCapability ComposeUnicastCapability(
+      const CodecType& codec_type, const AudioLocation& audio_location,
+      const uint8_t& device_cnt, const uint8_t& channel_count,
+      const T& capability);
+
+  static inline Lc3Capabilities ComposeLc3Capability(
+      const setting::CodecConfiguration& codec_configuration);
+
+  static inline AudioLocation GetAudioLocation(
+      const setting::AudioLocation& audio_location);
+  static inline CodecType GetCodecType(const setting::CodecType& codec_type);
+
+  static inline bool IsValidCodecConfiguration(
+      const setting::CodecConfiguration& codec_configuration);
+  static inline bool IsValidStrategyConfiguration(
+      const setting::StrategyConfiguration& strategy_configuration);
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xml b/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xml
new file mode 100644
index 0000000..c7904b3
--- /dev/null
+++ b/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!---
+  This is an example to configure LE Audio hardware offload supported capability settings
+  In the follow list, there would be only one list in this file. Add element into each list as needed.
+
+  codecConfigurationList:
+    Supported codec capability along with its parameter setting
+
+  strategyConfigurationList:
+     ASE Configuration strategies
+
+  configurationList:
+    For each configuration , there are two attributes
+      - codecConfiguration
+      - strategyConfiguration
+
+  scenarioList:
+    There would be only one `scenarios` group
+    For each scenario, the are two attributes
+      - encode
+      - decode
+    If a scenario is unidirectional, mark another direction as `invalid`
+    The configuration should be chosen from `configurationList`
+-->
+<leAudioOffloadSetting>
+  <scenarioList>
+    <!-- encode only -->
+    <scenario encode="OneChanMono_16_1" decode="invalid"/>
+    <scenario encode="TwoChanStereo_16_1" decode="invalid"/>
+    <scenario encode="OneChanStereo_16_1" decode="invalid"/>
+    <scenario encode="OneChanMono_16_2" decode="invalid"/>
+    <scenario encode="TwoChanStereo_16_2" decode="invalid"/>
+    <scenario encode="OneChanStereo_16_2" decode="invalid"/>
+    <!-- encode and decode -->
+    <scenario encode="OneChanStereo_16_1" decode="OneChanStereo_16_1"/>
+    <scenario encode="OneChanStereo_16_1" decode="OneChanMono_16_1"/>
+    <scenario encode="TwoChanStereo_16_1" decode="OneChanMono_16_1"/>
+    <scenario encode="OneChanMono_16_1" decode="OneChanMono_16_1"/>
+    <scenario encode="OneChanStereo_16_2" decode="OneChanStereo_16_2"/>
+    <scenario encode="OneChanStereo_16_2" decode="OneChanMono_16_2"/>
+    <scenario encode="TwoChanStereo_16_2" decode="OneChanMono_16_2"/>
+    <scenario encode="OneChanMono_16_2" decode="OneChanMono_16_2"/>
+  </scenarioList>
+  <configurationList>
+    <configuration name="OneChanMono_16_1" codecConfiguration="LC3_16k_1" strategyConfiguration="MONO_ONE_CIS_PER_DEVICE"/>
+    <configuration name="TwoChanStereo_16_1" codecConfiguration="LC3_16k_1" strategyConfiguration="STEREO_TWO_CISES_PER_DEVICE"/>
+    <configuration name="OneChanStereo_16_1" codecConfiguration="LC3_16k_1" strategyConfiguration="STEREO_ONE_CIS_PER_DEVICE"/>
+    <configuration name="OneChanMono_16_2" codecConfiguration="LC3_16k_2" strategyConfiguration="MONO_ONE_CIS_PER_DEVICE"/>
+    <configuration name="TwoChanStereo_16_2" codecConfiguration="LC3_16k_2" strategyConfiguration="STEREO_TWO_CISES_PER_DEVICE"/>
+    <configuration name="OneChanStereo_16_2" codecConfiguration="LC3_16k_2" strategyConfiguration="STEREO_ONE_CIS_PER_DEVICE"/>
+  </configurationList>
+  <codecConfigurationList>
+    <codecConfiguration name="LC3_16k_1" codec="LC3" samplingFrequency="16000" frameDurationUs="7500" octetsPerCodecFrame="30"/>
+    <codecConfiguration name="LC3_16k_2" codec="LC3" samplingFrequency="16000" frameDurationUs="10000" octetsPerCodecFrame="40"/>
+  </codecConfigurationList>
+  <strategyConfigurationList>
+    <strategyConfiguration name="STEREO_ONE_CIS_PER_DEVICE" audioLocation="STEREO" connectedDevice="2" channelCount="1"/>
+    <strategyConfiguration name="STEREO_TWO_CISES_PER_DEVICE" audioLocation="STEREO" connectedDevice="1" channelCount="2"/>
+    <strategyConfiguration name="MONO_ONE_CIS_PER_DEVICE" audioLocation="MONO" connectedDevice="1" channelCount="1"/>
+  </strategyConfigurationList>
+</leAudioOffloadSetting>
diff --git a/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xsd b/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xsd
new file mode 100644
index 0000000..213e597
--- /dev/null
+++ b/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xsd
@@ -0,0 +1,74 @@
+<!-- LE Audio Offload Codec Capability Schema -->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+  <xs:element name="leAudioOffloadSetting">
+    <xs:complexType>
+      <xs:element ref="scenarioList" minOccurs="1" maxOccurs="1"/>
+      <xs:element ref="configurationList" minOccurs="1" maxOccurs="1"/>
+      <xs:element ref="codecConfigurationList" minOccurs="1" maxOccurs="1"/>
+      <xs:element ref="strategyConfigurationList" minOccurs="1" maxOccurs="1"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:element name="scenarioList">
+    <xs:complexType>
+      <xs:element ref="scenario" minOccurs="1" maxOccurs="unbounded"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:element name="configurationList">
+    <xs:complexType>
+      <xs:element ref="configuration" minOccurs="1" maxOccurs="unbounded"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:element name="codecConfigurationList">
+    <xs:complexType>
+      <xs:element ref="codecConfiguration" minOccurs="1" maxOccurs="unbounded"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:element name="strategyConfigurationList">
+    <xs:complexType>
+      <xs:element ref="strategyConfiguration" minOccurs="1" maxOccurs="unbounded"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:element name="scenario">
+    <xs:complexType>
+      <xs:attribute name="encode" type="xs:string"/>
+      <xs:attribute name="decode" type="xs:string"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:element name="configuration">
+    <xs:complexType>
+      <xs:attribute name="name" type="xs:string"/>
+      <xs:attribute name="codecConfiguration" type="xs:string"/>
+      <xs:attribute name="strategyConfiguration" type="xs:string"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:element name="codecConfiguration">
+    <xs:complexType>
+      <xs:attribute name="name" type="xs:string"/>
+      <xs:attribute name="codec" type="codecType"/>
+      <xs:attribute name="pcmBitDepth" type="xs:unsignedByte"/>
+      <xs:attribute name="samplingFrequency" type="xs:int"/>
+      <xs:attribute name="frameDurationUs" type="xs:int"/>
+      <xs:attribute name="octetsPerCodecFrame" type="xs:int"/>
+      <xs:attribute name="codecFrameBlocksPerSdu" type="xs:unsignedByte"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:element name="strategyConfiguration">
+    <xs:complexType>
+      <xs:attribute name="name" type="xs:string"/>
+      <xs:attribute name="audioLocation" type="audioLocation"/>
+      <xs:attribute name="connectedDevice" type="xs:unsignedByte"/>
+      <xs:attribute name="channelCount" type="xs:unsignedByte"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:simpleType name="audioLocation">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="MONO"/>
+      <xs:enumeration value="STEREO"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="codecType">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="LC3"/>
+    </xs:restriction>
+  </xs:simpleType>
+</xs:schema>
diff --git a/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt b/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt
new file mode 100644
index 0000000..06aa21a
--- /dev/null
+++ b/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt
@@ -0,0 +1,111 @@
+// Signature format: 2.0
+package aidl.android.hardware.bluetooth.audio.setting {
+
+  public enum AudioLocation {
+    method public String getRawName();
+    enum_constant public static final aidl.android.hardware.bluetooth.audio.setting.AudioLocation MONO;
+    enum_constant public static final aidl.android.hardware.bluetooth.audio.setting.AudioLocation STEREO;
+  }
+
+  public class CodecConfiguration {
+    ctor public CodecConfiguration();
+    method public aidl.android.hardware.bluetooth.audio.setting.CodecType getCodec();
+    method public short getCodecFrameBlocksPerSdu();
+    method public int getFrameDurationUs();
+    method public String getName();
+    method public int getOctetsPerCodecFrame();
+    method public short getPcmBitDepth();
+    method public int getSamplingFrequency();
+    method public void setCodec(aidl.android.hardware.bluetooth.audio.setting.CodecType);
+    method public void setCodecFrameBlocksPerSdu(short);
+    method public void setFrameDurationUs(int);
+    method public void setName(String);
+    method public void setOctetsPerCodecFrame(int);
+    method public void setPcmBitDepth(short);
+    method public void setSamplingFrequency(int);
+  }
+
+  public class CodecConfigurationList {
+    ctor public CodecConfigurationList();
+    method public java.util.List<aidl.android.hardware.bluetooth.audio.setting.CodecConfiguration> getCodecConfiguration();
+  }
+
+  public enum CodecType {
+    method public String getRawName();
+    enum_constant public static final aidl.android.hardware.bluetooth.audio.setting.CodecType LC3;
+  }
+
+  public class Configuration {
+    ctor public Configuration();
+    method public String getCodecConfiguration();
+    method public String getName();
+    method public String getStrategyConfiguration();
+    method public void setCodecConfiguration(String);
+    method public void setName(String);
+    method public void setStrategyConfiguration(String);
+  }
+
+  public class ConfigurationList {
+    ctor public ConfigurationList();
+    method public java.util.List<aidl.android.hardware.bluetooth.audio.setting.Configuration> getConfiguration();
+  }
+
+  public class LeAudioOffloadSetting {
+    ctor public LeAudioOffloadSetting();
+    method public aidl.android.hardware.bluetooth.audio.setting.CodecConfigurationList getCodecConfigurationList();
+    method public aidl.android.hardware.bluetooth.audio.setting.ConfigurationList getConfigurationList();
+    method public aidl.android.hardware.bluetooth.audio.setting.ScenarioList getScenarioList();
+    method public aidl.android.hardware.bluetooth.audio.setting.StrategyConfigurationList getStrategyConfigurationList();
+    method public void setCodecConfigurationList(aidl.android.hardware.bluetooth.audio.setting.CodecConfigurationList);
+    method public void setConfigurationList(aidl.android.hardware.bluetooth.audio.setting.ConfigurationList);
+    method public void setScenarioList(aidl.android.hardware.bluetooth.audio.setting.ScenarioList);
+    method public void setStrategyConfigurationList(aidl.android.hardware.bluetooth.audio.setting.StrategyConfigurationList);
+  }
+
+  public class Scenario {
+    ctor public Scenario();
+    method public String getDecode();
+    method public String getEncode();
+    method public void setDecode(String);
+    method public void setEncode(String);
+  }
+
+  public class ScenarioList {
+    ctor public ScenarioList();
+    method public java.util.List<aidl.android.hardware.bluetooth.audio.setting.Scenario> getScenario();
+  }
+
+  public class StrategyConfiguration {
+    ctor public StrategyConfiguration();
+    method public aidl.android.hardware.bluetooth.audio.setting.AudioLocation getAudioLocation();
+    method public short getChannelCount();
+    method public short getConnectedDevice();
+    method public String getName();
+    method public void setAudioLocation(aidl.android.hardware.bluetooth.audio.setting.AudioLocation);
+    method public void setChannelCount(short);
+    method public void setConnectedDevice(short);
+    method public void setName(String);
+  }
+
+  public class StrategyConfigurationList {
+    ctor public StrategyConfigurationList();
+    method public java.util.List<aidl.android.hardware.bluetooth.audio.setting.StrategyConfiguration> getStrategyConfiguration();
+  }
+
+  public class XmlParser {
+    ctor public XmlParser();
+    method public static aidl.android.hardware.bluetooth.audio.setting.CodecConfiguration readCodecConfiguration(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static aidl.android.hardware.bluetooth.audio.setting.CodecConfigurationList readCodecConfigurationList(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static aidl.android.hardware.bluetooth.audio.setting.Configuration readConfiguration(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static aidl.android.hardware.bluetooth.audio.setting.ConfigurationList readConfigurationList(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static aidl.android.hardware.bluetooth.audio.setting.LeAudioOffloadSetting readLeAudioOffloadSetting(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static aidl.android.hardware.bluetooth.audio.setting.Scenario readScenario(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static aidl.android.hardware.bluetooth.audio.setting.ScenarioList readScenarioList(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static aidl.android.hardware.bluetooth.audio.setting.StrategyConfiguration readStrategyConfiguration(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static aidl.android.hardware.bluetooth.audio.setting.StrategyConfigurationList readStrategyConfigurationList(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+  }
+
+}
+
diff --git a/bluetooth/audio/utils/le_audio_codec_capabilities/schema/last_current.txt b/bluetooth/audio/utils/le_audio_codec_capabilities/schema/last_current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bluetooth/audio/utils/le_audio_codec_capabilities/schema/last_current.txt
diff --git a/bluetooth/audio/utils/le_audio_codec_capabilities/schema/last_removed.txt b/bluetooth/audio/utils/le_audio_codec_capabilities/schema/last_removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bluetooth/audio/utils/le_audio_codec_capabilities/schema/last_removed.txt
diff --git a/bluetooth/audio/utils/le_audio_codec_capabilities/schema/removed.txt b/bluetooth/audio/utils/le_audio_codec_capabilities/schema/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/bluetooth/audio/utils/le_audio_codec_capabilities/schema/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
index f3cbd78..f2c92ae 100644
--- a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
@@ -351,11 +351,11 @@
                   minDelayAverageInterval / 10);
 
         // fastest rate sampling time is close to spec
-        EXPECT_LT(std::abs(minDelayAverageInterval - minSamplingPeriodInNs),
+        EXPECT_LE(std::abs(minDelayAverageInterval - minSamplingPeriodInNs),
                   minSamplingPeriodInNs / 10);
 
         // slowest rate sampling time is close to spec
-        EXPECT_LT(std::abs(maxDelayAverageInterval - maxSamplingPeriodInNs),
+        EXPECT_LE(std::abs(maxDelayAverageInterval - maxSamplingPeriodInNs),
                   maxSamplingPeriodInNs / 10);
     }