Merge "Add wake reason to OperationContext."
diff --git a/audio/aidl/common/include/Utils.h b/audio/aidl/common/include/Utils.h
index 2aaa781..d87bbd4 100644
--- a/audio/aidl/common/include/Utils.h
+++ b/audio/aidl/common/include/Utils.h
@@ -104,6 +104,30 @@
            device == ::aidl::android::media::audio::common::AudioDeviceType::OUT_TELEPHONY_TX;
 }
 
+constexpr bool isUsbInputDeviceType(::aidl::android::media::audio::common::AudioDeviceType type) {
+    switch (type) {
+        case ::aidl::android::media::audio::common::AudioDeviceType::IN_DOCK:
+        case ::aidl::android::media::audio::common::AudioDeviceType::IN_ACCESSORY:
+        case ::aidl::android::media::audio::common::AudioDeviceType::IN_DEVICE:
+        case ::aidl::android::media::audio::common::AudioDeviceType::IN_HEADSET:
+            return true;
+        default:
+            return false;
+    }
+}
+
+constexpr bool isUsbOutputtDeviceType(::aidl::android::media::audio::common::AudioDeviceType type) {
+    switch (type) {
+        case ::aidl::android::media::audio::common::AudioDeviceType::OUT_DOCK:
+        case ::aidl::android::media::audio::common::AudioDeviceType::OUT_ACCESSORY:
+        case ::aidl::android::media::audio::common::AudioDeviceType::OUT_DEVICE:
+        case ::aidl::android::media::audio::common::AudioDeviceType::OUT_HEADSET:
+            return true;
+        default:
+            return false;
+    }
+}
+
 constexpr bool isValidAudioMode(::aidl::android::media::audio::common::AudioMode mode) {
     return std::find(kValidAudioModes.begin(), kValidAudioModes.end(), mode) !=
            kValidAudioModes.end();
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index 856f83f..21616be 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -11,12 +11,14 @@
     name: "aidlaudioservice_defaults",
     vendor: true,
     shared_libs: [
+        "libalsautilsv2",
         "libaudioaidlcommon",
         "libbase",
         "libbinder_ndk",
         "libcutils",
         "libfmq",
         "libstagefright_foundation",
+        "libtinyalsav2",
         "libutils",
         "libxml2",
         "android.hardware.common-V2-ndk",
@@ -71,6 +73,9 @@
         "Stream.cpp",
         "StreamStub.cpp",
         "Telephony.cpp",
+        "usb/ModuleUsb.cpp",
+        "usb/StreamUsb.cpp",
+        "usb/UsbAlsaUtils.cpp",
     ],
     generated_sources: [
         "audio_policy_configuration_aidl_default",
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 905ff2c..2f6ab2f 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -27,8 +27,10 @@
 
 #include "core-impl/Bluetooth.h"
 #include "core-impl/Module.h"
+#include "core-impl/ModuleUsb.h"
 #include "core-impl/SoundDose.h"
 #include "core-impl/StreamStub.h"
+#include "core-impl/StreamUsb.h"
 #include "core-impl/Telephony.h"
 #include "core-impl/utils.h"
 
@@ -104,6 +106,42 @@
 
 }  // namespace
 
+// static
+std::shared_ptr<Module> Module::createInstance(Type type) {
+    switch (type) {
+        case Module::Type::USB:
+            return ndk::SharedRefBase::make<ModuleUsb>(type);
+        case Type::DEFAULT:
+        case Type::R_SUBMIX:
+        default:
+            return ndk::SharedRefBase::make<Module>(type);
+    }
+}
+
+// static
+StreamIn::CreateInstance Module::getStreamInCreator(Type type) {
+    switch (type) {
+        case Type::USB:
+            return StreamInUsb::createInstance;
+        case Type::DEFAULT:
+        case Type::R_SUBMIX:
+        default:
+            return StreamInStub::createInstance;
+    }
+}
+
+// static
+StreamOut::CreateInstance Module::getStreamOutCreator(Type type) {
+    switch (type) {
+        case Type::USB:
+            return StreamOutUsb::createInstance;
+        case Type::DEFAULT:
+        case Type::R_SUBMIX:
+        default:
+            return StreamOutStub::createInstance;
+    }
+}
+
 void Module::cleanUpPatch(int32_t patchId) {
     erase_all_values(mPatches, std::set<int32_t>{patchId});
 }
@@ -153,6 +191,7 @@
                 std::make_unique<StreamContext::CommandMQ>(1, true /*configureEventFlagWord*/),
                 std::make_unique<StreamContext::ReplyMQ>(1, true /*configureEventFlagWord*/),
                 portConfigIt->format.value(), portConfigIt->channelMask.value(),
+                portConfigIt->sampleRate.value().value,
                 std::make_unique<StreamContext::DataMQ>(frameSize * in_bufferSizeFrames),
                 asyncCallback, outEventCallback, params);
         if (temp.isValid()) {
@@ -261,6 +300,7 @@
                 break;
             case Type::USB:
                 mConfig = std::move(internal::getUsbConfiguration());
+                break;
         }
     }
     return *mConfig;
@@ -401,6 +441,8 @@
     if (!mDebug.simulateDeviceConnections) {
         // In a real HAL here we would attempt querying the profiles from the device.
         LOG(ERROR) << __func__ << ": failed to query supported device profiles";
+        // TODO: Check the return value when it is ready for actual devices.
+        populateConnectedDevicePort(&connectedPort);
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
     }
 
@@ -560,10 +602,9 @@
     }
     context.fillDescriptor(&_aidl_return->desc);
     std::shared_ptr<StreamIn> stream;
-    // TODO: Add a mapping from module instance names to a corresponding 'createInstance'.
-    if (auto status = StreamInStub::createInstance(in_args.sinkMetadata, std::move(context),
-                                                   mConfig->microphones, &stream);
-        !status.isOk()) {
+    ndk::ScopedAStatus status = getStreamInCreator(mType)(in_args.sinkMetadata, std::move(context),
+                                                          mConfig->microphones, &stream);
+    if (!status.isOk()) {
         return status;
     }
     StreamWrapper streamWrapper(stream);
@@ -615,10 +656,9 @@
     }
     context.fillDescriptor(&_aidl_return->desc);
     std::shared_ptr<StreamOut> stream;
-    // TODO: Add a mapping from module instance names to a corresponding 'createInstance'.
-    if (auto status = StreamOutStub::createInstance(in_args.sourceMetadata, std::move(context),
-                                                    in_args.offloadInfo, &stream);
-        !status.isOk()) {
+    ndk::ScopedAStatus status = getStreamOutCreator(mType)(
+            in_args.sourceMetadata, std::move(context), in_args.offloadInfo, &stream);
+    if (!status.isOk()) {
         return status;
     }
     StreamWrapper streamWrapper(stream);
@@ -696,6 +736,10 @@
         }
     }
 
+    if (auto status = checkAudioPatchEndpointsMatch(sources, sinks); !status.isOk()) {
+        return status;
+    }
+
     auto& patches = getConfig().patches;
     auto existing = patches.end();
     std::optional<decltype(mPatches)> patchesBackup;
@@ -1190,4 +1234,16 @@
     return mIsMmapSupported.value();
 }
 
+ndk::ScopedAStatus Module::populateConnectedDevicePort(AudioPort* audioPort __unused) {
+    LOG(DEBUG) << __func__ << ": do nothing and return ok";
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::checkAudioPatchEndpointsMatch(
+        const std::vector<AudioPortConfig*>& sources __unused,
+        const std::vector<AudioPortConfig*>& sinks __unused) {
+    LOG(DEBUG) << __func__ << ": do nothing and return ok";
+    return ndk::ScopedAStatus::ok();
+}
+
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp
index 25814e4..d62ca1d 100644
--- a/audio/aidl/default/Stream.cpp
+++ b/audio/aidl/default/Stream.cpp
@@ -135,10 +135,16 @@
         mState = StreamDescriptor::State::ERROR;
         return Status::ABORT;
     }
-    LOG(DEBUG) << __func__ << ": received command " << command.toString() << " in " << kThreadName;
+    using Tag = StreamDescriptor::Command::Tag;
+    using LogSeverity = ::android::base::LogSeverity;
+    const LogSeverity severity =
+            command.getTag() == Tag::burst || command.getTag() == Tag::getStatus
+                    ? LogSeverity::VERBOSE
+                    : LogSeverity::DEBUG;
+    LOG(severity) << __func__ << ": received command " << command.toString() << " in "
+                  << kThreadName;
     StreamDescriptor::Reply reply{};
     reply.status = STATUS_BAD_VALUE;
-    using Tag = StreamDescriptor::Command::Tag;
     switch (command.getTag()) {
         case Tag::halReservedExit:
             if (const int32_t cookie = command.get<Tag::halReservedExit>();
@@ -166,8 +172,8 @@
             break;
         case Tag::burst:
             if (const int32_t fmqByteCount = command.get<Tag::burst>(); fmqByteCount >= 0) {
-                LOG(DEBUG) << __func__ << ": '" << toString(command.getTag()) << "' command for "
-                           << fmqByteCount << " bytes";
+                LOG(VERBOSE) << __func__ << ": '" << toString(command.getTag()) << "' command for "
+                             << fmqByteCount << " bytes";
                 if (mState == StreamDescriptor::State::IDLE ||
                     mState == StreamDescriptor::State::ACTIVE ||
                     mState == StreamDescriptor::State::PAUSED ||
@@ -253,7 +259,7 @@
             break;
     }
     reply.state = mState;
-    LOG(DEBUG) << __func__ << ": writing reply " << reply.toString();
+    LOG(severity) << __func__ << ": writing reply " << reply.toString();
     if (!mReplyMQ->writeBlocking(&reply, 1)) {
         LOG(ERROR) << __func__ << ": writing of reply " << reply.toString() << " to MQ failed";
         mState = StreamDescriptor::State::ERROR;
@@ -284,8 +290,8 @@
     if (bool success =
                 actualByteCount > 0 ? mDataMQ->write(&mDataBuffer[0], actualByteCount) : true;
         success) {
-        LOG(DEBUG) << __func__ << ": writing of " << actualByteCount << " bytes into data MQ"
-                   << " succeeded; connected? " << isConnected;
+        LOG(VERBOSE) << __func__ << ": writing of " << actualByteCount << " bytes into data MQ"
+                     << " succeeded; connected? " << isConnected;
         // Frames are provided and counted regardless of connection status.
         reply->fmqByteCount += actualByteCount;
         mFrameCount += actualFrameCount;
@@ -340,7 +346,14 @@
         mState = StreamDescriptor::State::ERROR;
         return Status::ABORT;
     }
-    LOG(DEBUG) << __func__ << ": received command " << command.toString() << " in " << kThreadName;
+    using Tag = StreamDescriptor::Command::Tag;
+    using LogSeverity = ::android::base::LogSeverity;
+    const LogSeverity severity =
+            command.getTag() == Tag::burst || command.getTag() == Tag::getStatus
+                    ? LogSeverity::VERBOSE
+                    : LogSeverity::DEBUG;
+    LOG(severity) << __func__ << ": received command " << command.toString() << " in "
+                  << kThreadName;
     StreamDescriptor::Reply reply{};
     reply.status = STATUS_BAD_VALUE;
     using Tag = StreamDescriptor::Command::Tag;
@@ -383,8 +396,8 @@
         } break;
         case Tag::burst:
             if (const int32_t fmqByteCount = command.get<Tag::burst>(); fmqByteCount >= 0) {
-                LOG(DEBUG) << __func__ << ": '" << toString(command.getTag()) << "' command for "
-                           << fmqByteCount << " bytes";
+                LOG(VERBOSE) << __func__ << ": '" << toString(command.getTag()) << "' command for "
+                             << fmqByteCount << " bytes";
                 if (mState != StreamDescriptor::State::ERROR &&
                     mState != StreamDescriptor::State::TRANSFERRING &&
                     mState != StreamDescriptor::State::TRANSFER_PAUSED) {
@@ -499,7 +512,7 @@
             break;
     }
     reply.state = mState;
-    LOG(DEBUG) << __func__ << ": writing reply " << reply.toString();
+    LOG(severity) << __func__ << ": writing reply " << reply.toString();
     if (!mReplyMQ->writeBlocking(&reply, 1)) {
         LOG(ERROR) << __func__ << ": writing of reply " << reply.toString() << " to MQ failed";
         mState = StreamDescriptor::State::ERROR;
@@ -514,8 +527,8 @@
     int32_t latency = Module::kLatencyMs;
     if (bool success = readByteCount > 0 ? mDataMQ->read(&mDataBuffer[0], readByteCount) : true) {
         const bool isConnected = mIsConnected;
-        LOG(DEBUG) << __func__ << ": reading of " << readByteCount << " bytes from data MQ"
-                   << " succeeded; connected? " << isConnected;
+        LOG(VERBOSE) << __func__ << ": reading of " << readByteCount << " bytes from data MQ"
+                     << " succeeded; connected? " << isConnected;
         // Amount of data that the HAL module is going to actually use.
         size_t byteCount = std::min({clientSize, readByteCount, mDataBufferSize});
         if (byteCount >= mFrameSize && mForceTransientBurst) {
diff --git a/audio/aidl/default/StreamStub.cpp b/audio/aidl/default/StreamStub.cpp
index 5442179..85d1e16 100644
--- a/audio/aidl/default/StreamStub.cpp
+++ b/audio/aidl/default/StreamStub.cpp
@@ -22,6 +22,7 @@
 
 using aidl::android::hardware::audio::common::SinkMetadata;
 using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::media::audio::common::AudioDevice;
 using aidl::android::media::audio::common::AudioOffloadInfo;
 
 namespace aidl::android::hardware::audio::core {
@@ -68,6 +69,11 @@
     return ::android::OK;
 }
 
+::android::status_t DriverStub::setConnectedDevices(
+        const std::vector<AudioDevice>& connectedDevices __unused) {
+    return ::android::OK;
+}
+
 // static
 ndk::ScopedAStatus StreamInStub::createInstance(const SinkMetadata& sinkMetadata,
                                                 StreamContext&& context,
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index 80a22dc..fab1c14 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -35,6 +35,10 @@
 
     explicit Module(Type type) : mType(type) {}
 
+    static std::shared_ptr<Module> createInstance(Type type);
+    static StreamIn::CreateInstance getStreamInCreator(Type type);
+    static StreamOut::CreateInstance getStreamOutCreator(Type type);
+
   private:
     struct VendorDebug {
         static const std::string kForceTransientBurstName;
@@ -163,6 +167,17 @@
     std::shared_ptr<sounddose::ISoundDose> mSoundDose;
     ndk::SpAIBinder mSoundDoseBinder;
     std::optional<bool> mIsMmapSupported;
+
+  protected:
+    // If the module is unable to populate the connected device port correctly, the returned error
+    // code must correspond to the errors of `IModule.connectedExternalDevice` method.
+    virtual ndk::ScopedAStatus populateConnectedDevicePort(
+            ::aidl::android::media::audio::common::AudioPort* audioPort);
+    // If the module finds that the patch endpoints configurations are not matched, the returned
+    // error code must correspond to the errors of `IModule.setAudioPatch` method.
+    virtual ndk::ScopedAStatus checkAudioPatchEndpointsMatch(
+            const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sources,
+            const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sinks);
 };
 
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/ModuleUsb.h b/audio/aidl/default/include/core-impl/ModuleUsb.h
new file mode 100644
index 0000000..7b177e8
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/ModuleUsb.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2023 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 "core-impl/Module.h"
+
+namespace aidl::android::hardware::audio::core {
+
+class ModuleUsb : public Module {
+  public:
+    explicit ModuleUsb(Module::Type type) : Module(type) {}
+
+  private:
+    // IModule interfaces
+    ndk::ScopedAStatus getTelephony(std::shared_ptr<ITelephony>* _aidl_return) override;
+    ndk::ScopedAStatus getBluetooth(std::shared_ptr<IBluetooth>* _aidl_return) override;
+    ndk::ScopedAStatus getMasterMute(bool* _aidl_return) override;
+    ndk::ScopedAStatus setMasterMute(bool in_mute) override;
+    ndk::ScopedAStatus getMasterVolume(float* _aidl_return) override;
+    ndk::ScopedAStatus setMasterVolume(float in_volume) override;
+    ndk::ScopedAStatus getMicMute(bool* _aidl_return) override;
+    ndk::ScopedAStatus setMicMute(bool in_mute) override;
+
+    // Module interfaces
+    ndk::ScopedAStatus populateConnectedDevicePort(
+            ::aidl::android::media::audio::common::AudioPort* audioPort) override;
+    ndk::ScopedAStatus checkAudioPatchEndpointsMatch(
+            const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sources,
+            const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sinks)
+            override;
+};
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
index 7cd4259..f8c12e6 100644
--- a/audio/aidl/default/include/core-impl/Stream.h
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -77,7 +77,8 @@
     StreamContext(std::unique_ptr<CommandMQ> commandMQ, std::unique_ptr<ReplyMQ> replyMQ,
                   const ::aidl::android::media::audio::common::AudioFormatDescription& format,
                   const ::aidl::android::media::audio::common::AudioChannelLayout& channelLayout,
-                  std::unique_ptr<DataMQ> dataMQ, std::shared_ptr<IStreamCallback> asyncCallback,
+                  int sampleRate, std::unique_ptr<DataMQ> dataMQ,
+                  std::shared_ptr<IStreamCallback> asyncCallback,
                   std::shared_ptr<IStreamOutEventCallback> outEventCallback,
                   DebugParameters debugParameters)
         : mCommandMQ(std::move(commandMQ)),
@@ -85,6 +86,7 @@
           mReplyMQ(std::move(replyMQ)),
           mFormat(format),
           mChannelLayout(channelLayout),
+          mSampleRate(sampleRate),
           mDataMQ(std::move(dataMQ)),
           mAsyncCallback(asyncCallback),
           mOutEventCallback(outEventCallback),
@@ -95,6 +97,7 @@
           mReplyMQ(std::move(other.mReplyMQ)),
           mFormat(other.mFormat),
           mChannelLayout(other.mChannelLayout),
+          mSampleRate(other.mSampleRate),
           mDataMQ(std::move(other.mDataMQ)),
           mAsyncCallback(std::move(other.mAsyncCallback)),
           mOutEventCallback(std::move(other.mOutEventCallback)),
@@ -105,6 +108,7 @@
         mReplyMQ = std::move(other.mReplyMQ);
         mFormat = std::move(other.mFormat);
         mChannelLayout = std::move(other.mChannelLayout);
+        mSampleRate = other.mSampleRate;
         mDataMQ = std::move(other.mDataMQ);
         mAsyncCallback = std::move(other.mAsyncCallback);
         mOutEventCallback = std::move(other.mOutEventCallback);
@@ -131,6 +135,7 @@
     }
     ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); }
     int getTransientStateDelayMs() const { return mDebugParameters.transientStateDelayMs; }
+    int getSampleRate() const { return mSampleRate; }
     bool isValid() const;
     void reset();
 
@@ -140,6 +145,7 @@
     std::unique_ptr<ReplyMQ> mReplyMQ;
     ::aidl::android::media::audio::common::AudioFormatDescription mFormat;
     ::aidl::android::media::audio::common::AudioChannelLayout mChannelLayout;
+    int mSampleRate;
     std::unique_ptr<DataMQ> mDataMQ;
     std::shared_ptr<IStreamCallback> mAsyncCallback;
     std::shared_ptr<IStreamOutEventCallback> mOutEventCallback;  // Only used by output streams
@@ -151,6 +157,11 @@
     virtual ~DriverInterface() = default;
     // This function is called once, on the main thread, before starting the worker thread.
     virtual ::android::status_t init() = 0;
+    // This function is called from Binder pool thread. It must be done in a thread-safe manner
+    // if this method and other methods in this interface share data.
+    virtual ::android::status_t setConnectedDevices(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>&
+                    connectedDevices) = 0;
     // All the functions below are called on the worker thread.
     virtual ::android::status_t drain(StreamDescriptor::DrainMode mode) = 0;
     virtual ::android::status_t flush() = 0;
@@ -370,6 +381,7 @@
             const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
         mWorker->setIsConnected(!devices.empty());
         mConnectedDevices = devices;
+        mDriver->setConnectedDevices(devices);
     }
     ndk::ScopedAStatus updateMetadata(const Metadata& metadata);
 
diff --git a/audio/aidl/default/include/core-impl/StreamStub.h b/audio/aidl/default/include/core-impl/StreamStub.h
index 98a062a..aea9da5 100644
--- a/audio/aidl/default/include/core-impl/StreamStub.h
+++ b/audio/aidl/default/include/core-impl/StreamStub.h
@@ -24,6 +24,9 @@
   public:
     DriverStub(const StreamContext& context, bool isInput);
     ::android::status_t init() override;
+    ::android::status_t setConnectedDevices(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>& connectedDevices)
+            override;
     ::android::status_t drain(StreamDescriptor::DrainMode) override;
     ::android::status_t flush() override;
     ::android::status_t pause() override;
diff --git a/audio/aidl/default/include/core-impl/StreamUsb.h b/audio/aidl/default/include/core-impl/StreamUsb.h
new file mode 100644
index 0000000..8ac1f34
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/StreamUsb.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2023 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 <mutex>
+
+#include <aidl/android/media/audio/common/AudioChannelLayout.h>
+
+#include "core-impl/Stream.h"
+
+extern "C" {
+#include <tinyalsa/pcm.h>
+#include "alsa_device_proxy.h"
+}
+
+namespace aidl::android::hardware::audio::core {
+
+class DriverUsb : public DriverInterface {
+  public:
+    DriverUsb(const StreamContext& context, bool isInput);
+    ::android::status_t init() override;
+    ::android::status_t setConnectedDevices(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>& connectedDevices)
+            override;
+    ::android::status_t drain(StreamDescriptor::DrainMode) override;
+    ::android::status_t flush() override;
+    ::android::status_t pause() override;
+    ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
+                                 int32_t* latencyMs) override;
+    ::android::status_t standby() override;
+
+  private:
+    ::android::status_t exitStandby();
+
+    std::mutex mLock;
+
+    const size_t mFrameSizeBytes;
+    std::optional<struct pcm_config> mConfig;
+    const bool mIsInput;
+    // Cached device addresses for connected devices.
+    std::vector<::aidl::android::media::audio::common::AudioDeviceAddress> mConnectedDevices
+            GUARDED_BY(mLock);
+    std::vector<std::shared_ptr<alsa_device_proxy>> mAlsaDeviceProxies GUARDED_BY(mLock);
+    bool mIsStandby = false;
+};
+
+class StreamInUsb final : public StreamIn {
+    ndk::ScopedAStatus getActiveMicrophones(
+            std::vector<MicrophoneDynamicInfo>* _aidl_return) override;
+
+  public:
+    static ndk::ScopedAStatus createInstance(
+            const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+            StreamContext&& context, const std::vector<MicrophoneInfo>& microphones,
+            std::shared_ptr<StreamIn>* result);
+
+  private:
+    friend class ndk::SharedRefBase;
+    StreamInUsb(const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+                StreamContext&& context, const std::vector<MicrophoneInfo>& microphones);
+};
+
+class StreamOutUsb final : public StreamOut {
+  public:
+    static ndk::ScopedAStatus createInstance(
+            const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+            StreamContext&& context,
+            const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+                    offloadInfo,
+            std::shared_ptr<StreamOut>* result);
+
+  private:
+    friend class ndk::SharedRefBase;
+    StreamOutUsb(const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+                 StreamContext&& context,
+                 const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+                         offloadInfo);
+};
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/utils.h b/audio/aidl/default/include/core-impl/utils.h
index 9d06f08..ae33227 100644
--- a/audio/aidl/default/include/core-impl/utils.h
+++ b/audio/aidl/default/include/core-impl/utils.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <algorithm>
+#include <map>
 #include <set>
 #include <vector>
 
@@ -101,4 +102,21 @@
     return result;
 }
 
+// Assuming that M is a map whose keys' type is K and values' type is V,
+// return the corresponding value of the given key from the map or default
+// value if the key is not found.
+template <typename M, typename K, typename V>
+auto findValueOrDefault(const M& m, const K& key, V defaultValue) {
+    auto it = m.find(key);
+    return it == m.end() ? defaultValue : it->second;
+}
+
+// Assuming that M is a map whose keys' type is K, return the given key if it
+// is found from the map or default value.
+template <typename M, typename K>
+auto findKeyOrDefault(const M& m, const K& key, K defaultValue) {
+    auto it = m.find(key);
+    return it == m.end() ? defaultValue : key;
+}
+
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/main.cpp b/audio/aidl/default/main.cpp
index 1933509..a861f9d 100644
--- a/audio/aidl/default/main.cpp
+++ b/audio/aidl/default/main.cpp
@@ -25,9 +25,11 @@
 
 #include "core-impl/Config.h"
 #include "core-impl/Module.h"
+#include "core-impl/ModuleUsb.h"
 
 using aidl::android::hardware::audio::core::Config;
 using aidl::android::hardware::audio::core::Module;
+using aidl::android::hardware::audio::core::ModuleUsb;
 
 int main() {
     // Random values are used in the implementation.
@@ -35,6 +37,8 @@
 
     // This is a debug implementation, always enable debug logging.
     android::base::SetMinimumLogSeverity(::android::base::DEBUG);
+    // For more logs, use VERBOSE, however this may hinder performance.
+    // android::base::SetMinimumLogSeverity(::android::base::VERBOSE);
     ABinderProcess_setThreadPoolMaxThreadCount(16);
 
     // Make the default config service
@@ -46,7 +50,7 @@
 
     // Make modules
     auto createModule = [](Module::Type type, const std::string& instance) {
-        auto module = ndk::SharedRefBase::make<Module>(type);
+        auto module = Module::createInstance(type);
         ndk::SpAIBinder moduleBinder = module->asBinder();
         const std::string moduleName = std::string(Module::descriptor).append("/").append(instance);
         AIBinder_setMinSchedulerPolicy(moduleBinder.get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
diff --git a/audio/aidl/default/usb/ModuleUsb.cpp b/audio/aidl/default/usb/ModuleUsb.cpp
new file mode 100644
index 0000000..e803420
--- /dev/null
+++ b/audio/aidl/default/usb/ModuleUsb.cpp
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2023 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 "AHAL_ModuleUsb"
+
+#include <vector>
+
+#include <Utils.h>
+#include <android-base/logging.h>
+#include <tinyalsa/asoundlib.h>
+
+#include "UsbAlsaUtils.h"
+#include "core-impl/ModuleUsb.h"
+
+extern "C" {
+#include "alsa_device_profile.h"
+}
+
+using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioDeviceAddress;
+using aidl::android::media::audio::common::AudioDeviceDescription;
+using aidl::android::media::audio::common::AudioDeviceType;
+using aidl::android::media::audio::common::AudioFormatDescription;
+using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::AudioPort;
+using aidl::android::media::audio::common::AudioPortConfig;
+using aidl::android::media::audio::common::AudioPortExt;
+using aidl::android::media::audio::common::AudioProfile;
+using android::hardware::audio::common::isUsbInputDeviceType;
+
+namespace aidl::android::hardware::audio::core {
+
+namespace {
+
+std::vector<AudioChannelLayout> populateChannelMasksFromProfile(const alsa_device_profile* profile,
+                                                                bool isInput) {
+    std::vector<AudioChannelLayout> channels;
+    for (size_t i = 0; i < AUDIO_PORT_MAX_CHANNEL_MASKS && profile->channel_counts[i] != 0; ++i) {
+        auto layoutMask =
+                usb::getChannelLayoutMaskFromChannelCount(profile->channel_counts[i], isInput);
+        if (layoutMask.getTag() == AudioChannelLayout::Tag::layoutMask) {
+            channels.push_back(layoutMask);
+        }
+        auto indexMask = usb::getChannelIndexMaskFromChannelCount(profile->channel_counts[i]);
+        if (indexMask.getTag() == AudioChannelLayout::Tag::indexMask) {
+            channels.push_back(indexMask);
+        }
+    }
+    return channels;
+}
+
+std::vector<int> populateSampleRatesFromProfile(const alsa_device_profile* profile) {
+    std::vector<int> sampleRates;
+    for (int i = 0; i < std::min(MAX_PROFILE_SAMPLE_RATES, AUDIO_PORT_MAX_SAMPLING_RATES) &&
+                    profile->sample_rates[i] != 0;
+         i++) {
+        sampleRates.push_back(profile->sample_rates[i]);
+    }
+    return sampleRates;
+}
+
+}  // namespace
+
+ndk::ScopedAStatus ModuleUsb::getTelephony(std::shared_ptr<ITelephony>* _aidl_return) {
+    *_aidl_return = nullptr;
+    LOG(DEBUG) << __func__ << ": returning null";
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ModuleUsb::getBluetooth(std::shared_ptr<IBluetooth>* _aidl_return) {
+    *_aidl_return = nullptr;
+    LOG(DEBUG) << __func__ << ": returning null";
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ModuleUsb::getMasterMute(bool* _aidl_return __unused) {
+    LOG(DEBUG) << __func__ << ": is not supported";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus ModuleUsb::setMasterMute(bool in_mute __unused) {
+    LOG(DEBUG) << __func__ << ": is not supported";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus ModuleUsb::getMasterVolume(float* _aidl_return __unused) {
+    LOG(DEBUG) << __func__ << ": is not supported";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus ModuleUsb::setMasterVolume(float in_volume __unused) {
+    LOG(DEBUG) << __func__ << ": is not supported";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus ModuleUsb::getMicMute(bool* _aidl_return __unused) {
+    LOG(DEBUG) << __func__ << ": is not supported";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus ModuleUsb::setMicMute(bool in_mute __unused) {
+    LOG(DEBUG) << __func__ << ": is not supported";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus ModuleUsb::populateConnectedDevicePort(AudioPort* audioPort) {
+    if (audioPort->ext.getTag() != AudioPortExt::Tag::device) {
+        LOG(ERROR) << __func__ << ": port id " << audioPort->id << " is not a device port";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    auto& devicePort = audioPort->ext.get<AudioPortExt::Tag::device>();
+    if (devicePort.device.type.connection != AudioDeviceDescription::CONNECTION_USB) {
+        LOG(ERROR) << __func__ << ": port id " << audioPort->id << " is not a usb device port";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    if (devicePort.device.address.getTag() != AudioDeviceAddress::Tag::alsa) {
+        LOG(ERROR) << __func__ << ": port id " << audioPort->id << " is not using alsa address";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    auto& alsaAddress = devicePort.device.address.get<AudioDeviceAddress::Tag::alsa>();
+    if (alsaAddress.size() != 2 || alsaAddress[0] < 0 || alsaAddress[1] < 0) {
+        LOG(ERROR) << __func__ << ": port id " << audioPort->id << " invalid alsa address";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+
+    const bool isInput = isUsbInputDeviceType(devicePort.device.type.type);
+    alsa_device_profile profile;
+    profile_init(&profile, isInput ? PCM_IN : PCM_OUT);
+    if (!profile_read_device_info(&profile)) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+
+    std::vector<AudioChannelLayout> channels = populateChannelMasksFromProfile(&profile, isInput);
+    std::vector<int> sampleRates = populateSampleRatesFromProfile(&profile);
+
+    for (size_t i = 0; i < std::min(MAX_PROFILE_FORMATS, AUDIO_PORT_MAX_AUDIO_PROFILES) &&
+                       profile.formats[i] != 0;
+         ++i) {
+        auto audioFormatDescription =
+                usb::legacy2aidl_pcm_format_AudioFormatDescription(profile.formats[i]);
+        if (audioFormatDescription.type == AudioFormatType::DEFAULT) {
+            LOG(WARNING) << __func__ << ": unknown pcm type=" << profile.formats[i];
+            continue;
+        }
+        AudioProfile audioProfile = {.format = audioFormatDescription,
+                                     .channelMasks = channels,
+                                     .sampleRates = sampleRates};
+        audioPort->profiles.push_back(std::move(audioProfile));
+    }
+
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ModuleUsb::checkAudioPatchEndpointsMatch(
+        const std::vector<AudioPortConfig*>& sources, const std::vector<AudioPortConfig*>& sinks) {
+    for (const auto& source : sources) {
+        for (const auto& sink : sinks) {
+            if (source->sampleRate != sink->sampleRate ||
+                source->channelMask != sink->channelMask || source->format != sink->format) {
+                LOG(ERROR) << __func__
+                           << ": mismatch port configuration, source=" << source->toString()
+                           << ", sink=" << sink->toString();
+                return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+            }
+        }
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/usb/StreamUsb.cpp b/audio/aidl/default/usb/StreamUsb.cpp
new file mode 100644
index 0000000..22e36ac
--- /dev/null
+++ b/audio/aidl/default/usb/StreamUsb.cpp
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2023 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 "AHAL_StreamUsb"
+#include <android-base/logging.h>
+
+#include "UsbAlsaUtils.h"
+#include "core-impl/Module.h"
+#include "core-impl/StreamUsb.h"
+
+extern "C" {
+#include "alsa_device_profile.h"
+}
+
+using aidl::android::hardware::audio::common::SinkMetadata;
+using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioDeviceAddress;
+using aidl::android::media::audio::common::AudioOffloadInfo;
+
+namespace aidl::android::hardware::audio::core {
+
+DriverUsb::DriverUsb(const StreamContext& context, bool isInput)
+    : mFrameSizeBytes(context.getFrameSize()), mIsInput(isInput) {
+    struct pcm_config config;
+    config.channels = usb::getChannelCountFromChannelMask(context.getChannelLayout(), isInput);
+    if (config.channels == 0) {
+        LOG(ERROR) << __func__ << ": invalid channel=" << context.getChannelLayout().toString();
+        return;
+    }
+    config.format = usb::aidl2legacy_AudioFormatDescription_pcm_format(context.getFormat());
+    if (config.format == PCM_FORMAT_INVALID) {
+        LOG(ERROR) << __func__ << ": invalid format=" << context.getFormat().toString();
+        return;
+    }
+    config.rate = context.getSampleRate();
+    if (config.rate == 0) {
+        LOG(ERROR) << __func__ << ": invalid sample rate=" << config.rate;
+        return;
+    }
+    mConfig = config;
+}
+
+::android::status_t DriverUsb::init() {
+    return mConfig.has_value() ? ::android::OK : ::android::NO_INIT;
+}
+
+::android::status_t DriverUsb::setConnectedDevices(
+        const std::vector<AudioDevice>& connectedDevices) {
+    if (mIsInput && connectedDevices.size() > 1) {
+        LOG(ERROR) << __func__ << ": wrong device size(" << connectedDevices.size()
+                   << ") for input stream";
+        return ::android::BAD_VALUE;
+    }
+    for (const auto& connectedDevice : connectedDevices) {
+        if (connectedDevice.address.getTag() != AudioDeviceAddress::alsa) {
+            LOG(ERROR) << __func__ << ": bad device address" << connectedDevice.address.toString();
+            return ::android::BAD_VALUE;
+        }
+    }
+    std::lock_guard guard(mLock);
+    mAlsaDeviceProxies.clear();
+    mConnectedDevices.clear();
+    for (const auto& connectedDevice : connectedDevices) {
+        mConnectedDevices.push_back(connectedDevice.address);
+    }
+    return ::android::OK;
+}
+
+::android::status_t DriverUsb::drain(StreamDescriptor::DrainMode) {
+    usleep(1000);
+    return ::android::OK;
+}
+
+::android::status_t DriverUsb::flush() {
+    usleep(1000);
+    return ::android::OK;
+}
+
+::android::status_t DriverUsb::pause() {
+    usleep(1000);
+    return ::android::OK;
+}
+
+::android::status_t DriverUsb::transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
+                                        int32_t* latencyMs) {
+    if (!mConfig.has_value() || mConnectedDevices.empty()) {
+        return ::android::NO_INIT;
+    }
+    if (mIsStandby) {
+        if (::android::status_t status = exitStandby(); status != ::android::OK) {
+            return status;
+        }
+    }
+    std::vector<std::shared_ptr<alsa_device_proxy>> alsaDeviceProxies;
+    {
+        std::lock_guard guard(mLock);
+        alsaDeviceProxies = mAlsaDeviceProxies;
+    }
+    const size_t bytesToTransfer = frameCount * mFrameSizeBytes;
+    if (mIsInput) {
+        // For input case, only support single device.
+        proxy_read(alsaDeviceProxies[0].get(), buffer, bytesToTransfer);
+    } else {
+        for (auto& proxy : alsaDeviceProxies) {
+            proxy_write(proxy.get(), buffer, bytesToTransfer);
+        }
+    }
+    *actualFrameCount = frameCount;
+    *latencyMs = Module::kLatencyMs;
+    return ::android::OK;
+}
+
+::android::status_t DriverUsb::standby() {
+    if (!mIsStandby) {
+        std::lock_guard guard(mLock);
+        mAlsaDeviceProxies.clear();
+        mIsStandby = true;
+    }
+    return ::android::OK;
+}
+
+::android::status_t DriverUsb::exitStandby() {
+    std::vector<AudioDeviceAddress> connectedDevices;
+    {
+        std::lock_guard guard(mLock);
+        connectedDevices = mConnectedDevices;
+    }
+    std::vector<std::shared_ptr<alsa_device_proxy>> alsaDeviceProxies;
+    for (const auto& device : connectedDevices) {
+        alsa_device_profile profile;
+        profile.card = device.get<AudioDeviceAddress::alsa>()[0];
+        profile.device = device.get<AudioDeviceAddress::alsa>()[1];
+        if (!profile_read_device_info(&profile)) {
+            LOG(ERROR) << __func__
+                       << ": unable to read device info, device address=" << device.toString();
+            return ::android::UNKNOWN_ERROR;
+        }
+
+        auto proxy = std::shared_ptr<alsa_device_proxy>(new alsa_device_proxy(),
+                                                        [](alsa_device_proxy* proxy) {
+                                                            proxy_close(proxy);
+                                                            free(proxy);
+                                                        });
+        // Always ask for alsa configure as required since the configuration should be supported
+        // by the connected device. That is guaranteed by `setAudioPortConfig` and
+        // `setAudioPatch`.
+        if (int err =
+                    proxy_prepare(proxy.get(), &profile, &mConfig.value(), true /*is_bit_perfect*/);
+            err != 0) {
+            LOG(ERROR) << __func__ << ": fail to prepare for device address=" << device.toString()
+                       << " error=" << err;
+            return ::android::UNKNOWN_ERROR;
+        }
+        alsaDeviceProxies.push_back(std::move(proxy));
+    }
+    {
+        std::lock_guard guard(mLock);
+        mAlsaDeviceProxies = alsaDeviceProxies;
+    }
+    mIsStandby = false;
+    return ::android::OK;
+}
+
+// static
+ndk::ScopedAStatus StreamInUsb::createInstance(const SinkMetadata& sinkMetadata,
+                                               StreamContext&& context,
+                                               const std::vector<MicrophoneInfo>& microphones,
+                                               std::shared_ptr<StreamIn>* result) {
+    std::shared_ptr<StreamIn> stream =
+            ndk::SharedRefBase::make<StreamInUsb>(sinkMetadata, std::move(context), microphones);
+    if (auto status = initInstance(stream); !status.isOk()) {
+        return status;
+    }
+    *result = std::move(stream);
+    return ndk::ScopedAStatus::ok();
+}
+
+StreamInUsb::StreamInUsb(const SinkMetadata& sinkMetadata, StreamContext&& context,
+                         const std::vector<MicrophoneInfo>& microphones)
+    : StreamIn(
+              sinkMetadata, std::move(context),
+              [](const StreamContext& ctx) -> DriverInterface* {
+                  return new DriverUsb(ctx, true /*isInput*/);
+              },
+              [](const StreamContext& ctx, DriverInterface* driver) -> StreamWorkerInterface* {
+                  // The default worker implementation is used.
+                  return new StreamInWorker(ctx, driver);
+              },
+              microphones) {}
+
+ndk::ScopedAStatus StreamInUsb::getActiveMicrophones(
+        std::vector<MicrophoneDynamicInfo>* _aidl_return __unused) {
+    LOG(DEBUG) << __func__ << ": not supported";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+// static
+ndk::ScopedAStatus StreamOutUsb::createInstance(const SourceMetadata& sourceMetadata,
+                                                StreamContext&& context,
+                                                const std::optional<AudioOffloadInfo>& offloadInfo,
+                                                std::shared_ptr<StreamOut>* result) {
+    if (offloadInfo.has_value()) {
+        LOG(ERROR) << __func__ << ": offload is not supported";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    std::shared_ptr<StreamOut> stream =
+            ndk::SharedRefBase::make<StreamOutUsb>(sourceMetadata, std::move(context), offloadInfo);
+    if (auto status = initInstance(stream); !status.isOk()) {
+        return status;
+    }
+    *result = std::move(stream);
+    return ndk::ScopedAStatus::ok();
+}
+
+StreamOutUsb::StreamOutUsb(const SourceMetadata& sourceMetadata, StreamContext&& context,
+                           const std::optional<AudioOffloadInfo>& offloadInfo)
+    : StreamOut(
+              sourceMetadata, std::move(context),
+              [](const StreamContext& ctx) -> DriverInterface* {
+                  return new DriverUsb(ctx, false /*isInput*/);
+              },
+              [](const StreamContext& ctx, DriverInterface* driver) -> StreamWorkerInterface* {
+                  // The default worker implementation is used.
+                  return new StreamOutWorker(ctx, driver);
+              },
+              offloadInfo) {}
+
+}  // namespace aidl::android::hardware::audio::core
\ No newline at end of file
diff --git a/audio/aidl/default/usb/UsbAlsaUtils.cpp b/audio/aidl/default/usb/UsbAlsaUtils.cpp
new file mode 100644
index 0000000..3c79e1d
--- /dev/null
+++ b/audio/aidl/default/usb/UsbAlsaUtils.cpp
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2023 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 <map>
+#include <set>
+
+#include <Utils.h>
+#include <aidl/android/media/audio/common/AudioFormatType.h>
+#include <aidl/android/media/audio/common/PcmType.h>
+
+#include "UsbAlsaUtils.h"
+#include "core-impl/utils.h"
+
+using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioFormatDescription;
+using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::PcmType;
+using android::hardware::audio::common::getChannelCount;
+
+namespace aidl::android::hardware::audio::core::usb {
+
+namespace {
+
+using AudioChannelCountToMaskMap = std::map<unsigned int, AudioChannelLayout>;
+using AudioFormatDescToPcmFormatMap = std::map<AudioFormatDescription, enum pcm_format>;
+using PcmFormatToAudioFormatDescMap = std::map<enum pcm_format, AudioFormatDescription>;
+
+static const AudioChannelLayout INVALID_CHANNEL_LAYOUT =
+        AudioChannelLayout::make<AudioChannelLayout::Tag::invalid>(0);
+
+#define DEFINE_CHANNEL_LAYOUT_MASK(n) \
+    AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(AudioChannelLayout::LAYOUT_##n)
+
+static const std::set<AudioChannelLayout> SUPPORTED_OUT_CHANNEL_LAYOUTS = {
+        DEFINE_CHANNEL_LAYOUT_MASK(MONO),          DEFINE_CHANNEL_LAYOUT_MASK(STEREO),
+        DEFINE_CHANNEL_LAYOUT_MASK(2POINT1),       DEFINE_CHANNEL_LAYOUT_MASK(QUAD),
+        DEFINE_CHANNEL_LAYOUT_MASK(PENTA),         DEFINE_CHANNEL_LAYOUT_MASK(5POINT1),
+        DEFINE_CHANNEL_LAYOUT_MASK(6POINT1),       DEFINE_CHANNEL_LAYOUT_MASK(7POINT1),
+        DEFINE_CHANNEL_LAYOUT_MASK(7POINT1POINT4), DEFINE_CHANNEL_LAYOUT_MASK(22POINT2),
+};
+
+static const std::set<AudioChannelLayout> SUPPORTED_IN_CHANNEL_LAYOUTS = {
+        DEFINE_CHANNEL_LAYOUT_MASK(MONO),
+        DEFINE_CHANNEL_LAYOUT_MASK(STEREO),
+};
+
+#define DEFINE_CHANNEL_INDEX_MASK(n) \
+    AudioChannelLayout::make<AudioChannelLayout::Tag::indexMask>(AudioChannelLayout::INDEX_MASK_##n)
+
+static const std::set<AudioChannelLayout> SUPPORTED_INDEX_CHANNEL_LAYOUTS = {
+        DEFINE_CHANNEL_INDEX_MASK(1),  DEFINE_CHANNEL_INDEX_MASK(2),  DEFINE_CHANNEL_INDEX_MASK(3),
+        DEFINE_CHANNEL_INDEX_MASK(4),  DEFINE_CHANNEL_INDEX_MASK(5),  DEFINE_CHANNEL_INDEX_MASK(6),
+        DEFINE_CHANNEL_INDEX_MASK(7),  DEFINE_CHANNEL_INDEX_MASK(8),  DEFINE_CHANNEL_INDEX_MASK(9),
+        DEFINE_CHANNEL_INDEX_MASK(10), DEFINE_CHANNEL_INDEX_MASK(11), DEFINE_CHANNEL_INDEX_MASK(12),
+        DEFINE_CHANNEL_INDEX_MASK(13), DEFINE_CHANNEL_INDEX_MASK(14), DEFINE_CHANNEL_INDEX_MASK(15),
+        DEFINE_CHANNEL_INDEX_MASK(16), DEFINE_CHANNEL_INDEX_MASK(17), DEFINE_CHANNEL_INDEX_MASK(18),
+        DEFINE_CHANNEL_INDEX_MASK(19), DEFINE_CHANNEL_INDEX_MASK(20), DEFINE_CHANNEL_INDEX_MASK(21),
+        DEFINE_CHANNEL_INDEX_MASK(22), DEFINE_CHANNEL_INDEX_MASK(23), DEFINE_CHANNEL_INDEX_MASK(24),
+};
+
+static AudioChannelCountToMaskMap make_ChannelCountToMaskMap(
+        const std::set<AudioChannelLayout>& channelMasks) {
+    AudioChannelCountToMaskMap channelMaskToCountMap;
+    for (const auto& channelMask : channelMasks) {
+        channelMaskToCountMap.emplace(getChannelCount(channelMask), channelMask);
+    }
+    return channelMaskToCountMap;
+}
+
+const AudioChannelCountToMaskMap& getSupportedChannelOutLayoutMap() {
+    static const AudioChannelCountToMaskMap outLayouts =
+            make_ChannelCountToMaskMap(SUPPORTED_OUT_CHANNEL_LAYOUTS);
+    return outLayouts;
+}
+
+const AudioChannelCountToMaskMap& getSupportedChannelInLayoutMap() {
+    static const AudioChannelCountToMaskMap inLayouts =
+            make_ChannelCountToMaskMap(SUPPORTED_IN_CHANNEL_LAYOUTS);
+    return inLayouts;
+}
+
+const AudioChannelCountToMaskMap& getSupportedChannelIndexLayoutMap() {
+    static const AudioChannelCountToMaskMap indexLayouts =
+            make_ChannelCountToMaskMap(SUPPORTED_INDEX_CHANNEL_LAYOUTS);
+    return indexLayouts;
+}
+
+AudioFormatDescription make_AudioFormatDescription(AudioFormatType type) {
+    AudioFormatDescription result;
+    result.type = type;
+    return result;
+}
+
+AudioFormatDescription make_AudioFormatDescription(PcmType pcm) {
+    auto result = make_AudioFormatDescription(AudioFormatType::PCM);
+    result.pcm = pcm;
+    return result;
+}
+
+const AudioFormatDescToPcmFormatMap& getAudioFormatDescriptorToPcmFormatMap() {
+    static const AudioFormatDescToPcmFormatMap formatDescToPcmFormatMap = {
+            {make_AudioFormatDescription(PcmType::UINT_8_BIT), PCM_FORMAT_S8},
+            {make_AudioFormatDescription(PcmType::INT_16_BIT), PCM_FORMAT_S16_LE},
+            {make_AudioFormatDescription(PcmType::INT_24_BIT), PCM_FORMAT_S24_LE},
+            {make_AudioFormatDescription(PcmType::FIXED_Q_8_24), PCM_FORMAT_S24_3LE},
+            {make_AudioFormatDescription(PcmType::INT_32_BIT), PCM_FORMAT_S32_LE},
+            {make_AudioFormatDescription(PcmType::FLOAT_32_BIT), PCM_FORMAT_FLOAT_LE},
+    };
+    return formatDescToPcmFormatMap;
+}
+
+static PcmFormatToAudioFormatDescMap make_PcmFormatToAudioFormatDescMap(
+        const AudioFormatDescToPcmFormatMap& formatDescToPcmFormatMap) {
+    PcmFormatToAudioFormatDescMap result;
+    for (const auto& formatPair : formatDescToPcmFormatMap) {
+        result.emplace(formatPair.second, formatPair.first);
+    }
+    return result;
+}
+
+const PcmFormatToAudioFormatDescMap& getPcmFormatToAudioFormatDescMap() {
+    static const PcmFormatToAudioFormatDescMap pcmFormatToFormatDescMap =
+            make_PcmFormatToAudioFormatDescMap(getAudioFormatDescriptorToPcmFormatMap());
+    return pcmFormatToFormatDescMap;
+}
+
+}  // namespace
+
+AudioChannelLayout getChannelLayoutMaskFromChannelCount(unsigned int channelCount, int isInput) {
+    return findValueOrDefault(
+            isInput ? getSupportedChannelInLayoutMap() : getSupportedChannelOutLayoutMap(),
+            channelCount, INVALID_CHANNEL_LAYOUT);
+}
+
+AudioChannelLayout getChannelIndexMaskFromChannelCount(unsigned int channelCount) {
+    return findValueOrDefault(getSupportedChannelIndexLayoutMap(), channelCount,
+                              INVALID_CHANNEL_LAYOUT);
+}
+
+unsigned int getChannelCountFromChannelMask(const AudioChannelLayout& channelMask, bool isInput) {
+    switch (channelMask.getTag()) {
+        case AudioChannelLayout::Tag::layoutMask: {
+            return findKeyOrDefault(
+                    isInput ? getSupportedChannelInLayoutMap() : getSupportedChannelOutLayoutMap(),
+                    (unsigned int)getChannelCount(channelMask), 0u /*defaultValue*/);
+        }
+        case AudioChannelLayout::Tag::indexMask: {
+            return findKeyOrDefault(getSupportedChannelIndexLayoutMap(),
+                                    (unsigned int)getChannelCount(channelMask),
+                                    0u /*defaultValue*/);
+        }
+        case AudioChannelLayout::Tag::none:
+        case AudioChannelLayout::Tag::invalid:
+        case AudioChannelLayout::Tag::voiceMask:
+        default:
+            return 0;
+    }
+}
+
+AudioFormatDescription legacy2aidl_pcm_format_AudioFormatDescription(enum pcm_format legacy) {
+    return findValueOrDefault(getPcmFormatToAudioFormatDescMap(), legacy, AudioFormatDescription());
+}
+
+pcm_format aidl2legacy_AudioFormatDescription_pcm_format(const AudioFormatDescription& aidl) {
+    return findValueOrDefault(getAudioFormatDescriptorToPcmFormatMap(), aidl, PCM_FORMAT_INVALID);
+}
+
+}  // namespace aidl::android::hardware::audio::core::usb
\ No newline at end of file
diff --git a/audio/aidl/default/usb/UsbAlsaUtils.h b/audio/aidl/default/usb/UsbAlsaUtils.h
new file mode 100644
index 0000000..2d2f0f4
--- /dev/null
+++ b/audio/aidl/default/usb/UsbAlsaUtils.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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/media/audio/common/AudioChannelLayout.h>
+#include <aidl/android/media/audio/common/AudioFormatDescription.h>
+
+extern "C" {
+#include <tinyalsa/pcm.h>
+}
+
+namespace aidl::android::hardware::audio::core::usb {
+
+::aidl::android::media::audio::common::AudioChannelLayout getChannelLayoutMaskFromChannelCount(
+        unsigned int channelCount, int isInput);
+::aidl::android::media::audio::common::AudioChannelLayout getChannelIndexMaskFromChannelCount(
+        unsigned int channelCount);
+unsigned int getChannelCountFromChannelMask(
+        const ::aidl::android::media::audio::common::AudioChannelLayout& channelMask, bool isInput);
+::aidl::android::media::audio::common::AudioFormatDescription
+legacy2aidl_pcm_format_AudioFormatDescription(enum pcm_format legacy);
+pcm_format aidl2legacy_AudioFormatDescription_pcm_format(
+        const ::aidl::android::media::audio::common::AudioFormatDescription& aidl);
+
+}  // namespace aidl::android::hardware::audio::core::usb
\ No newline at end of file
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/StatusCode.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/StatusCode.aidl
index 9b72412..f7e8c5a 100644
--- a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/StatusCode.aidl
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/StatusCode.aidl
@@ -40,4 +40,9 @@
   NOT_AVAILABLE = 3,
   ACCESS_DENIED = 4,
   INTERNAL_ERROR = 5,
+  NOT_AVAILABLE_DISABLED = 6,
+  NOT_AVAILABLE_SPEED_LOW = 7,
+  NOT_AVAILABLE_SPEED_HIGH = 8,
+  NOT_AVAILABLE_POOR_VISIBILITY = 9,
+  NOT_AVAILABLE_SAFETY = 10,
 }
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/StatusCode.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/StatusCode.aidl
index 35080db..8ac6506 100644
--- a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/StatusCode.aidl
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/StatusCode.aidl
@@ -62,4 +62,35 @@
      * Something unexpected has happened in Vehicle HAL
      */
     INTERNAL_ERROR = 5,
+
+    /**
+     * The following error codes were added in version 2 of this interface.
+     */
+
+    /**
+     * For features that are not available because the underlying feature is
+     * disabled.
+     */
+    NOT_AVAILABLE_DISABLED = 6,
+    /**
+     * For features that are not available because the vehicle speed is too low.
+     */
+    NOT_AVAILABLE_SPEED_LOW = 7,
+    /**
+     * For features that are not available because the vehicle speed is too
+     * high.
+     */
+    NOT_AVAILABLE_SPEED_HIGH = 8,
+    /**
+     * For features that are not available because of bad camera or sensor
+     * visibility. Examples might be bird poop blocking the camera or a bumper
+     * cover blocking an ultrasonic sensor.
+     */
+    NOT_AVAILABLE_POOR_VISIBILITY = 9,
+    /**
+     * The feature cannot be accessed due to safety reasons. Eg. System could be
+     * in a faulty state, an object or person could be blocking the requested
+     * operation such as closing a trunk door, etc.
+     */
+    NOT_AVAILABLE_SAFETY = 10,
 }
diff --git a/bluetooth/aidl/android/hardware/bluetooth/IBluetoothHci.aidl b/bluetooth/aidl/android/hardware/bluetooth/IBluetoothHci.aidl
index db12986..ff1f735 100644
--- a/bluetooth/aidl/android/hardware/bluetooth/IBluetoothHci.aidl
+++ b/bluetooth/aidl/android/hardware/bluetooth/IBluetoothHci.aidl
@@ -35,6 +35,9 @@
 
     /**
      * Initialize the Bluetooth interface and set the callbacks.
+     * Only one client can initialize the interface at a time.  When a
+     * call to initialize fails, the Status parameter of the callback
+     * will indicate the reason for the failure.
      */
     void initialize(in IBluetoothHciCallbacks callback);
 
diff --git a/bluetooth/aidl/android/hardware/bluetooth/IBluetoothHciCallbacks.aidl b/bluetooth/aidl/android/hardware/bluetooth/IBluetoothHciCallbacks.aidl
index 000333e..0148c6f 100644
--- a/bluetooth/aidl/android/hardware/bluetooth/IBluetoothHciCallbacks.aidl
+++ b/bluetooth/aidl/android/hardware/bluetooth/IBluetoothHciCallbacks.aidl
@@ -39,6 +39,8 @@
     /**
      * Invoked when the Bluetooth controller initialization has been
      * completed.
+     * @param status contains a return code indicating success, or the
+     *               reason the initialization failed.
      */
     void initializationComplete(in Status status);
 
diff --git a/bluetooth/aidl/vts/VtsHalBluetoothTargetTest.cpp b/bluetooth/aidl/vts/VtsHalBluetoothTargetTest.cpp
index 7b9e211..3704c3d 100644
--- a/bluetooth/aidl/vts/VtsHalBluetoothTargetTest.cpp
+++ b/bluetooth/aidl/vts/VtsHalBluetoothTargetTest.cpp
@@ -867,6 +867,48 @@
   wait_for_command_complete_event(set_event_mask);
 }
 
+// Call initialize twice, second one should fail.
+TEST_P(BluetoothAidlTest, CallInitializeTwice) {
+  class SecondCb
+      : public aidl::android::hardware::bluetooth::BnBluetoothHciCallbacks {
+   public:
+    ndk::ScopedAStatus initializationComplete(Status status) {
+      EXPECT_EQ(status, Status::ALREADY_INITIALIZED);
+      init_promise.set_value();
+      return ScopedAStatus::ok();
+    };
+
+    ndk::ScopedAStatus hciEventReceived(const std::vector<uint8_t>& /*event*/) {
+      ADD_FAILURE();
+      return ScopedAStatus::ok();
+    };
+
+    ndk::ScopedAStatus aclDataReceived(const std::vector<uint8_t>& /*data*/) {
+      ADD_FAILURE();
+      return ScopedAStatus::ok();
+    };
+
+    ndk::ScopedAStatus scoDataReceived(const std::vector<uint8_t>& /*data*/) {
+      ADD_FAILURE();
+      return ScopedAStatus::ok();
+    };
+
+    ndk::ScopedAStatus isoDataReceived(const std::vector<uint8_t>& /*data*/) {
+      ADD_FAILURE();
+      return ScopedAStatus::ok();
+    };
+    std::promise<void> init_promise;
+  };
+
+  std::shared_ptr<SecondCb> second_cb = ndk::SharedRefBase::make<SecondCb>();
+  ASSERT_NE(second_cb, nullptr);
+
+  auto future = second_cb->init_promise.get_future();
+  ASSERT_TRUE(hci->initialize(second_cb).isOk());
+  auto status = future.wait_for(std::chrono::seconds(1));
+  ASSERT_EQ(status, std::future_status::ready);
+}
+
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BluetoothAidlTest);
 INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAidlTest,
                          testing::ValuesIn(android::getAidlHalInstanceNames(
diff --git a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
index e9b74b7..128ef61 100644
--- a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
+++ b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
@@ -1566,6 +1566,7 @@
   };
 
   for (auto& lc3_config : lc3_codec_configs) {
+    le_audio_broadcast_config.streamMap.resize(1);
     le_audio_broadcast_config.streamMap[0]
         .leAudioCodecConfig.set<LeAudioCodecConfiguration::lc3Config>(
             lc3_config);
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
index 1dec900..0a804bb 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
@@ -200,13 +200,21 @@
         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};
+
+    if (scenario.hasBroadcast()) {
+      broadcast_capability = GetBroadcastCapability(scenario.getBroadcast());
+    }
+
+    // At least one capability should be valid
+    if (unicast_encode_capability.codecType == CodecType::UNKNOWN &&
+        unicast_decode_capability.codecType == CodecType::UNKNOWN &&
+        broadcast_capability.codecType == CodecType::UNKNOWN) {
+      LOG(ERROR) << __func__ << ": None of the capability is valid.";
+      continue;
+    }
+
     le_audio_codec_capabilities.push_back(
         {.unicastEncodeCapability = unicast_encode_capability,
          .unicastDecodeCapability = unicast_decode_capability,
@@ -252,6 +260,54 @@
   return {.codecType = CodecType::UNKNOWN};
 }
 
+BroadcastCapability BluetoothLeAudioCodecsProvider::GetBroadcastCapability(
+    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());
+  std::vector<std::optional<Lc3Capabilities>> bcastLc3Cap(
+      1, std::optional(ComposeLc3Capability(codec_configuration_iter->second)));
+
+  if (codec_type == CodecType::LC3) {
+    return ComposeBroadcastCapability(
+        codec_type,
+        GetAudioLocation(
+            strategy_configuration_iter->second.getAudioLocation()),
+        strategy_configuration_iter->second.getChannelCount(), bcastLc3Cap);
+  }
+  return {.codecType = CodecType::UNKNOWN};
+}
+
+template <class T>
+BroadcastCapability BluetoothLeAudioCodecsProvider::ComposeBroadcastCapability(
+    const CodecType& codec_type, const AudioLocation& audio_location,
+    const uint8_t& channel_count, const std::vector<T>& capability) {
+  return {.codecType = codec_type,
+          .supportedChannel = audio_location,
+          .channelCountPerStream = channel_count,
+          .leAudioCodecCapabilities = std::optional(capability)};
+}
+
 template <class T>
 UnicastCapability BluetoothLeAudioCodecsProvider::ComposeUnicastCapability(
     const CodecType& codec_type, const AudioLocation& audio_location,
@@ -322,6 +378,10 @@
       // 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.getConnectedDevice() == 0 &&
+               strategy_configuration.getChannelCount() == 2) {
+      // Broadcast
+      return true;
     }
   } else if (strategy_configuration.getAudioLocation() ==
              setting::AudioLocation::MONO) {
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h
index e879984..06e4595 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h
@@ -20,6 +20,7 @@
 #include <android-base/logging.h>
 
 #include <unordered_map>
+#include <vector>
 
 #include "aidl_android_hardware_bluetooth_audio_setting.h"
 
@@ -66,12 +67,20 @@
 
   static UnicastCapability GetUnicastCapability(
       const std::string& coding_direction);
+  static BroadcastCapability GetBroadcastCapability(
+      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);
 
+  template <class T>
+  static inline BroadcastCapability ComposeBroadcastCapability(
+      const CodecType& codec_type, const AudioLocation& audio_location,
+      const uint8_t& channel_count, const std::vector<T>& capability);
+
   static inline Lc3Capabilities ComposeLc3Capability(
       const setting::CodecConfiguration& codec_configuration);
 
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp
index 5393cd7..dba2749 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp
@@ -46,7 +46,11 @@
 // Define valid components for each list
 // Scenario
 static const Scenario kValidScenario(std::make_optional("OneChanStereo_16_1"),
-                                     std::make_optional("OneChanStereo_16_1"));
+                                     std::make_optional("OneChanStereo_16_1"),
+                                     std::nullopt);
+static const Scenario kValidBroadcastScenario(
+    std::nullopt, std::nullopt, std::make_optional("BcastStereo_16_2"));
+
 // Configuration
 static const Configuration kValidConfigOneChanStereo_16_1(
     std::make_optional("OneChanStereo_16_1"), std::make_optional("LC3_16k_1"),
@@ -69,11 +73,15 @@
     std::make_optional("MONO_ONE_CIS_PER_DEVICE"),
     std::make_optional(AudioLocation::MONO), std::make_optional(1),
     std::make_optional(1));
+static const StrategyConfiguration kValidStrategyBroadcastStereo(
+    std::make_optional("BROADCAST_STEREO"),
+    std::make_optional(AudioLocation::STEREO), std::make_optional(0),
+    std::make_optional(2));
 
 // Define valid test list built from above valid components
 // Scenario, Configuration, CodecConfiguration, StrategyConfiguration
-static const std::vector<ScenarioList> kValidScenarioList = {
-    ScenarioList(std::vector<Scenario>{kValidScenario})};
+static const std::vector<ScenarioList> kValidScenarioList = {ScenarioList(
+    std::vector<Scenario>{kValidScenario, kValidBroadcastScenario})};
 static const std::vector<ConfigurationList> kValidConfigurationList = {
     ConfigurationList(
         std::vector<Configuration>{kValidConfigOneChanStereo_16_1})};
@@ -84,7 +92,7 @@
     kValidStrategyConfigurationList = {
         StrategyConfigurationList(std::vector<StrategyConfiguration>{
             kValidStrategyStereoOneCis, kValidStrategyStereoTwoCis,
-            kValidStrategyMonoOneCis})};
+            kValidStrategyMonoOneCis, kValidStrategyBroadcastStereo})};
 
 class BluetoothLeAudioCodecsProviderTest
     : public ::testing::TestWithParam<OffloadSetting> {
@@ -151,13 +159,15 @@
   static std::vector<ScenarioList> CreateInvalidScenarios() {
     std::vector<ScenarioList> invalid_scenario_test_cases;
     invalid_scenario_test_cases.push_back(ScenarioList(std::vector<Scenario>{
-        Scenario(std::nullopt, std::make_optional("OneChanStereo_16_1"))}));
-
-    invalid_scenario_test_cases.push_back(ScenarioList(std::vector<Scenario>{
-        Scenario(std::make_optional("OneChanStereo_16_1"), std::nullopt)}));
+        Scenario(std::nullopt, std::make_optional("OneChanStereo_16_1"),
+                 std::nullopt)}));
 
     invalid_scenario_test_cases.push_back(ScenarioList(
-        std::vector<Scenario>{Scenario(std::nullopt, std::nullopt)}));
+        std::vector<Scenario>{Scenario(std::make_optional("OneChanStereo_16_1"),
+                                       std::nullopt, std::nullopt)}));
+
+    invalid_scenario_test_cases.push_back(ScenarioList(std::vector<Scenario>{
+        Scenario(std::nullopt, std::nullopt, std::nullopt)}));
 
     invalid_scenario_test_cases.push_back(
         ScenarioList(std::vector<Scenario>{}));
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
index c7904b3..c8d1af0 100644
--- 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
@@ -40,6 +40,8 @@
     <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"/>
+    <!-- broadcast -->
+    <scenario encode="invalid" decode="invalid" broadcast="BcastStereo_16_2"/>
   </scenarioList>
   <configurationList>
     <configuration name="OneChanMono_16_1" codecConfiguration="LC3_16k_1" strategyConfiguration="MONO_ONE_CIS_PER_DEVICE"/>
@@ -48,6 +50,7 @@
     <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"/>
+    <configuration name="BcastStereo_16_2" codecConfiguration="LC3_16k_2" strategyConfiguration="BROADCAST_STEREO"/>
   </configurationList>
   <codecConfigurationList>
     <codecConfiguration name="LC3_16k_1" codec="LC3" samplingFrequency="16000" frameDurationUs="7500" octetsPerCodecFrame="30"/>
@@ -57,5 +60,6 @@
     <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"/>
+    <strategyConfiguration name="BROADCAST_STEREO" audioLocation="STEREO" connectedDevice="0" channelCount="2"/>
   </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
index 213e597..8c2d6a1 100644
--- 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
@@ -32,6 +32,7 @@
     <xs:complexType>
       <xs:attribute name="encode" type="xs:string"/>
       <xs:attribute name="decode" type="xs:string"/>
+      <xs:attribute name="broadcast" type="xs:string"/>
     </xs:complexType>
   </xs:element>
   <xs:element name="configuration">
diff --git a/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt b/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt
index 06aa21a..886350e 100644
--- a/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt
+++ b/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt
@@ -64,8 +64,10 @@
 
   public class Scenario {
     ctor public Scenario();
+    method public String getBroadcast();
     method public String getDecode();
     method public String getEncode();
+    method public void setBroadcast(String);
     method public void setDecode(String);
     method public void setEncode(String);
   }
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICas.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICas.aidl
index 28c9eb0..903ab92 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICas.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICas.aidl
@@ -36,6 +36,7 @@
 @VintfStability
 interface ICas {
   void closeSession(in byte[] sessionId);
+  byte[] openSessionDefault();
   byte[] openSession(in android.hardware.cas.SessionIntent intent, in android.hardware.cas.ScramblingMode mode);
   void processEcm(in byte[] sessionId, in byte[] ecm);
   void processEmm(in byte[] emm);
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ScramblingMode.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ScramblingMode.aidl
index a0b08c9..9d542cc 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ScramblingMode.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ScramblingMode.aidl
@@ -36,18 +36,18 @@
 @Backing(type="int") @VintfStability
 enum ScramblingMode {
   RESERVED = 0,
-  DVB_CSA1 = 1,
-  DVB_CSA2 = 2,
-  DVB_CSA3_STANDARD = 3,
-  DVB_CSA3_MINIMAL = 4,
-  DVB_CSA3_ENHANCE = 5,
-  DVB_CISSA_V1 = 6,
-  DVB_IDSA = 7,
-  MULTI2 = 8,
-  AES128 = 9,
-  AES_ECB = 10,
-  AES_SCTE52 = 11,
-  TDES_ECB = 12,
-  TDES_SCTE52 = 13,
-  AES_CBC = 14,
+  DVB_CSA1,
+  DVB_CSA2,
+  DVB_CSA3_STANDARD,
+  DVB_CSA3_MINIMAL,
+  DVB_CSA3_ENHANCE,
+  DVB_CISSA_V1,
+  DVB_IDSA,
+  MULTI2,
+  AES128,
+  AES_ECB,
+  AES_SCTE52,
+  TDES_ECB,
+  TDES_SCTE52,
+  AES_CBC,
 }
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SessionIntent.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SessionIntent.aidl
index ade3001..00a2fd7 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SessionIntent.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SessionIntent.aidl
@@ -35,8 +35,8 @@
 /* @hide */
 @Backing(type="int") @VintfStability
 enum SessionIntent {
-  LIVE = 0,
-  PLAYBACK = 1,
-  RECORD = 2,
-  TIMESHIFT = 3,
+  LIVE,
+  PLAYBACK,
+  RECORD,
+  TIMESHIFT,
 }
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/Status.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/Status.aidl
index 343c810..3691009 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/Status.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/Status.aidl
@@ -36,25 +36,25 @@
 @VintfStability
 parcelable Status {
   const int OK = 0;
-  const int ERROR_CAS_NO_LICENSE = -1;
-  const int ERROR_CAS_LICENSE_EXPIRED = -2;
-  const int ERROR_CAS_SESSION_NOT_OPENED = -3;
-  const int ERROR_CAS_CANNOT_HANDLE = -4;
-  const int ERROR_CAS_INVALID_STATE = -5;
-  const int BAD_VALUE = -6;
-  const int ERROR_CAS_NOT_PROVISIONED = -7;
-  const int ERROR_CAS_RESOURCE_BUSY = -8;
-  const int ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION = -9;
-  const int ERROR_CAS_TAMPER_DETECTED = -10;
-  const int ERROR_CAS_DEVICE_REVOKED = -11;
-  const int ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED = -12;
-  const int ERROR_CAS_DECRYPT = -13;
-  const int ERROR_CAS_UNKNOWN = -14;
-  const int ERROR_CAS_NEED_ACTIVATION = -15;
-  const int ERROR_CAS_NEED_PAIRING = -16;
-  const int ERROR_CAS_NO_CARD = -17;
-  const int ERROR_CAS_CARD_MUTE = -18;
-  const int ERROR_CAS_CARD_INVALID = -19;
-  const int ERROR_CAS_BLACKOUT = -20;
-  const int ERROR_CAS_REBOOTING = -21;
+  const int ERROR_CAS_NO_LICENSE = 1;
+  const int ERROR_CAS_LICENSE_EXPIRED = 2;
+  const int ERROR_CAS_SESSION_NOT_OPENED = 3;
+  const int ERROR_CAS_CANNOT_HANDLE = 4;
+  const int ERROR_CAS_INVALID_STATE = 5;
+  const int BAD_VALUE = 6;
+  const int ERROR_CAS_NOT_PROVISIONED = 7;
+  const int ERROR_CAS_RESOURCE_BUSY = 8;
+  const int ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION = 9;
+  const int ERROR_CAS_TAMPER_DETECTED = 10;
+  const int ERROR_CAS_DEVICE_REVOKED = 11;
+  const int ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED = 12;
+  const int ERROR_CAS_DECRYPT = 13;
+  const int ERROR_CAS_UNKNOWN = 14;
+  const int ERROR_CAS_NEED_ACTIVATION = 15;
+  const int ERROR_CAS_NEED_PAIRING = 16;
+  const int ERROR_CAS_NO_CARD = 17;
+  const int ERROR_CAS_CARD_MUTE = 18;
+  const int ERROR_CAS_CARD_INVALID = 19;
+  const int ERROR_CAS_BLACKOUT = 20;
+  const int ERROR_CAS_REBOOTING = 21;
 }
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/StatusEvent.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/StatusEvent.aidl
index 165c0d4..0cf37dd 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/StatusEvent.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/StatusEvent.aidl
@@ -35,6 +35,6 @@
 /* @hide */
 @Backing(type="byte") @VintfStability
 enum StatusEvent {
-  PLUGIN_PHYSICAL_MODULE_CHANGED = 0,
-  PLUGIN_SESSION_NUMBER_CHANGED = 1,
+  PLUGIN_PHYSICAL_MODULE_CHANGED,
+  PLUGIN_SESSION_NUMBER_CHANGED,
 }
diff --git a/cas/aidl/android/hardware/cas/ICas.aidl b/cas/aidl/android/hardware/cas/ICas.aidl
index e6494ae..272cb10 100644
--- a/cas/aidl/android/hardware/cas/ICas.aidl
+++ b/cas/aidl/android/hardware/cas/ICas.aidl
@@ -35,6 +35,14 @@
     void closeSession(in byte[] sessionId);
 
     /**
+     * Open a session to descramble one or more streams without specifying intention
+     * and scrambling mode.
+     *
+     * @return sessionId The id of the newly opened session.
+     */
+    byte[] openSessionDefault();
+
+    /**
      * Open a session to descramble one or more streams by specifying intention
      * and scrambling mode.
      *
diff --git a/cas/aidl/android/hardware/cas/Status.aidl b/cas/aidl/android/hardware/cas/Status.aidl
index e7ae8ff..ba0bd65 100644
--- a/cas/aidl/android/hardware/cas/Status.aidl
+++ b/cas/aidl/android/hardware/cas/Status.aidl
@@ -31,50 +31,50 @@
      * The CAS plugin must return ERROR_CAS_NO_LICENSE, when descrambling is
      * attempted and no license keys have been provided.
      */
-    const int ERROR_CAS_NO_LICENSE = -1;
+    const int ERROR_CAS_NO_LICENSE = 1;
 
     /**
      * ERROR_CAS_LICENSE_EXPIRED must be returned when an attempt is made
      * to use a license and the keys in that license have expired.
      */
-    const int ERROR_CAS_LICENSE_EXPIRED = -2;
+    const int ERROR_CAS_LICENSE_EXPIRED = 2;
 
     /**
      * The CAS plugin must return ERROR_CAS_SESSION_NOT_OPENED when an
      * attempt is made to use a session that has not been opened.
      */
-    const int ERROR_CAS_SESSION_NOT_OPENED = -3;
+    const int ERROR_CAS_SESSION_NOT_OPENED = 3;
 
     /**
      * The CAS plugin must return ERROR_CAS_CANNOT_HANDLE when an unsupported
      * data format or operation is attempted.
      */
-    const int ERROR_CAS_CANNOT_HANDLE = -4;
+    const int ERROR_CAS_CANNOT_HANDLE = 4;
 
     /**
      * ERROR_CAS_INVALID_STATE must be returned when the device is in a state
      * where it is not able to perform descrambling.
      */
-    const int ERROR_CAS_INVALID_STATE = -5;
+    const int ERROR_CAS_INVALID_STATE = 5;
 
     /**
      * The CAS plugin must return BAD_VALUE whenever an illegal parameter is
      * passed to one of the interface functions.
      */
-    const int BAD_VALUE = -6;
+    const int BAD_VALUE = 6;
 
     /**
      * The CAS plugin must return ERROR_CAS_NOT_PROVISIONED when the device
      * has not yet been provisioned.
      */
-    const int ERROR_CAS_NOT_PROVISIONED = -7;
+    const int ERROR_CAS_NOT_PROVISIONED = 7;
 
     /**
      * ERROR_CAS_RESOURCE_BUSY must be returned when resources, such as CAS
      * sessions or secure buffers are not available to perform a requested
      * operation because they are already in use.
      */
-    const int ERROR_CAS_RESOURCE_BUSY = -8;
+    const int ERROR_CAS_RESOURCE_BUSY = 8;
 
     /**
      * The CAS Plugin must return ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION
@@ -82,72 +82,72 @@
      * sufficient to meet the requirements in the license policy. HDCP is an
      * example of a form of output protection.
      */
-    const int ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION = -9;
+    const int ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION = 9;
 
     /**
      * The CAS Plugin must return ERROR_CAS_TAMPER_DETECTED if an attempt to
      * tamper with the CAS system is detected.
      */
-    const int ERROR_CAS_TAMPER_DETECTED = -10;
+    const int ERROR_CAS_TAMPER_DETECTED = 10;
 
     /**
      * The CAS Plugin must return ERROR_CAS_DEVICE_REVOKED if the response
      * indicates that the device has been revoked. Device revocation means
      * that the device is no longer permitted to play content.
      */
-    const int ERROR_CAS_DEVICE_REVOKED = -11;
+    const int ERROR_CAS_DEVICE_REVOKED = 11;
 
     /**
      * The CAS plugin must return ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED when
      * descrambling is failing because the session is not initialized properly.
      */
-    const int ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED = -12;
+    const int ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED = 12;
 
     /**
      * The CAS Plugin must return ERROR_CAS_DECRYPT if the DescramblerPlugin's
      * descramble operation fails.
      */
-    const int ERROR_CAS_DECRYPT = -13;
+    const int ERROR_CAS_DECRYPT = 13;
 
     /**
      * ERROR_CAS_UNKNOWN must be returned when a fatal failure occurs and no
      * other defined error is appropriate.
      */
-    const int ERROR_CAS_UNKNOWN = -14;
+    const int ERROR_CAS_UNKNOWN = 14;
 
     /**
      * ERROR_CAS_NEED_ACTIVATION is used to trigger device activation process.
      */
-    const int ERROR_CAS_NEED_ACTIVATION = -15;
+    const int ERROR_CAS_NEED_ACTIVATION = 15;
 
     /**
      * ERROR_CAS_NEED_PAIRING is used to trigger pairing process.
      */
-    const int ERROR_CAS_NEED_PAIRING = -16;
+    const int ERROR_CAS_NEED_PAIRING = 16;
 
     /**
      * ERROR_CAS_NO_CARD is used to report no smart card for descrambling.
      */
-    const int ERROR_CAS_NO_CARD = -17;
+    const int ERROR_CAS_NO_CARD = 17;
 
     /**
      * ERROR_CAS_CARD_MUTE is used to report smart card is muted for
      * descrambling.
      */
-    const int ERROR_CAS_CARD_MUTE = -18;
+    const int ERROR_CAS_CARD_MUTE = 18;
 
     /**
      *  ERROR_CAS_CARD_INVALID is used to report smart card isn't valid.
      */
-    const int ERROR_CAS_CARD_INVALID = -19;
+    const int ERROR_CAS_CARD_INVALID = 19;
 
     /**
      *  ERROR_CAS_BLACKOUT is used to report geographical blackout.
      */
-    const int ERROR_CAS_BLACKOUT = -20;
+    const int ERROR_CAS_BLACKOUT = 20;
 
     /**
      * ERROR_CAS_REBOOTING is used to report CAS is during rebooting.
      */
-    const int ERROR_CAS_REBOOTING = -21;
+    const int ERROR_CAS_REBOOTING = 21;
 }
diff --git a/cas/aidl/default/CasImpl.cpp b/cas/aidl/default/CasImpl.cpp
index 2d31b35..f08fcc0 100755
--- a/cas/aidl/default/CasImpl.cpp
+++ b/cas/aidl/default/CasImpl.cpp
@@ -128,6 +128,19 @@
     return toStatus(holder->setPrivateData(pvtData));
 }
 
+ScopedAStatus CasImpl::openSessionDefault(vector<uint8_t>* sessionId) {
+    ALOGV("%s", __FUNCTION__);
+
+    shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
+    status_t err = INVALID_OPERATION;
+    if (holder.get() != nullptr) {
+        err = holder->openSession(sessionId);
+        holder.reset();
+    }
+
+    return toStatus(err);
+}
+
 ScopedAStatus CasImpl::openSession(SessionIntent intent, ScramblingMode mode,
                                    vector<uint8_t>* sessionId) {
     ALOGV("%s", __FUNCTION__);
diff --git a/cas/aidl/default/CasImpl.h b/cas/aidl/default/CasImpl.h
index 84a8115..2488a7f 100755
--- a/cas/aidl/default/CasImpl.h
+++ b/cas/aidl/default/CasImpl.h
@@ -53,6 +53,8 @@
 
     virtual ScopedAStatus setPrivateData(const vector<uint8_t>& pvtData) override;
 
+    virtual ScopedAStatus openSessionDefault(vector<uint8_t>* sessionId) override;
+
     virtual ScopedAStatus openSession(SessionIntent intent, ScramblingMode mode,
                                       vector<uint8_t>* sessionId) override;
 
diff --git a/cas/aidl/vts/functional/VtsHalCasAidlTargetTest.cpp b/cas/aidl/vts/functional/VtsHalCasAidlTargetTest.cpp
index 266b55d..4c904a8 100644
--- a/cas/aidl/vts/functional/VtsHalCasAidlTargetTest.cpp
+++ b/cas/aidl/vts/functional/VtsHalCasAidlTargetTest.cpp
@@ -286,6 +286,7 @@
     } OobInputTestParams;
 
     AssertionResult createCasPlugin(int32_t caSystemId);
+    AssertionResult openCasSessionDefault(vector<uint8_t>* sessionId);
     AssertionResult openCasSession(vector<uint8_t>* sessionId, SessionIntent intent,
                                    ScramblingMode mode);
     AssertionResult descrambleTestInputBuffer(const shared_ptr<IDescrambler>& descrambler,
@@ -331,6 +332,10 @@
     return AssertionResult(mDescrambler != nullptr);
 }
 
+AssertionResult MediaCasAidlTest::openCasSessionDefault(vector<uint8_t>* sessionId) {
+    return AssertionResult(mMediaCas->openSessionDefault(sessionId).isOk());
+}
+
 AssertionResult MediaCasAidlTest::openCasSession(vector<uint8_t>* sessionId, SessionIntent intent,
                                                  ScramblingMode mode) {
     return AssertionResult(mMediaCas->openSession(intent, mode, sessionId).isOk());
@@ -485,6 +490,32 @@
     ADD_FAILURE() << "ClearKey plugin not installed";
 }
 
+TEST_P(MediaCasAidlTest, TestClearKeyDefaultSessionClosedAfterRelease) {
+    description("Test that all sessions are closed after a MediaCas object is released");
+
+    ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
+
+    EXPECT_TRUE(mMediaCas->provision(PROVISION_STR).isOk());
+
+    vector<uint8_t> sessionId;
+    ASSERT_TRUE(openCasSessionDefault(&sessionId));
+
+    vector<uint8_t> streamSessionId;
+    ASSERT_TRUE(openCasSessionDefault(&streamSessionId));
+
+    EXPECT_TRUE(mMediaCas->release().isOk());
+
+    if (mDescrambler != nullptr) {
+        auto status = mDescrambler->setMediaCasSession(sessionId);
+        EXPECT_FALSE(status.isOk());
+        EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, status.getServiceSpecificError());
+
+        status = mDescrambler->setMediaCasSession(streamSessionId);
+        EXPECT_FALSE(status.isOk());
+        EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, status.getServiceSpecificError());
+    }
+}
+
 TEST_P(MediaCasAidlTest, TestClearKeySessionClosedAfterRelease) {
     description("Test that all sessions are closed after a MediaCas object is released");
 
diff --git a/compatibility_matrices/compatibility_matrix.8.xml b/compatibility_matrices/compatibility_matrix.8.xml
index 6977813..56ae51a 100644
--- a/compatibility_matrices/compatibility_matrix.8.xml
+++ b/compatibility_matrices/compatibility_matrix.8.xml
@@ -673,14 +673,6 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
-        <name>android.hardware.usb.gadget</name>
-        <version>1.0-2</version>
-        <interface>
-            <name>IUsbGadget</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.usb.gadget</name>
         <interface>
diff --git a/health/aidl/OWNERS b/health/aidl/OWNERS
index fcad499..9bbcef8 100644
--- a/health/aidl/OWNERS
+++ b/health/aidl/OWNERS
@@ -1,4 +1,4 @@
 # Bug component: 30545
 elsk@google.com
 smoreland@google.com
-stayfan@google.com
+wjack@google.com
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
index b0b984c..8f357a0 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
@@ -232,7 +232,8 @@
     EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial);
     ALOGI("setPreferredNetworkTypeBitmap, rspInfo.error = %s\n",
           toString(radioRsp_v1_4->rspInfo.error).c_str());
-    EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error);
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error,
+                                 {RadioError::NONE, RadioError::MODE_NOT_SUPPORTED}));
     if (radioRsp_v1_4->rspInfo.error == RadioError::NONE) {
          // give some time for modem to set the value.
         sleep(3);
diff --git a/secure_element/aidl/default/main.cpp b/secure_element/aidl/default/main.cpp
index 6149eae..0822402 100644
--- a/secure_element/aidl/default/main.cpp
+++ b/secure_element/aidl/default/main.cpp
@@ -586,7 +586,7 @@
 
         // The selected basic or logical channel is not opened.
         if (channel_number >= channels_.size() || !channels_[channel_number].opened) {
-            return ScopedAStatus::ok();
+            return ScopedAStatus::fromServiceSpecificError(FAILED);
         }
 
         // TODO(b/123254068) - this is not an implementation of the OMAPI protocol
diff --git a/secure_element/aidl/vts/VtsHalSecureElementTargetTest.cpp b/secure_element/aidl/vts/VtsHalSecureElementTargetTest.cpp
index c265579..37ff1b2 100644
--- a/secure_element/aidl/vts/VtsHalSecureElementTargetTest.cpp
+++ b/secure_element/aidl/vts/VtsHalSecureElementTargetTest.cpp
@@ -109,6 +109,7 @@
     }
 
     void TearDown() override {
+        EXPECT_OK(secure_element_->reset());
         secure_element_ = nullptr;
         secure_element_callback_ = nullptr;
     }
@@ -232,10 +233,10 @@
     std::vector<uint8_t> basic_channel_response;
     LogicalChannelResponse logical_channel_response;
 
-    // closeChannel called on non-existing basic or logical channel is a no-op
-    // and shall succeed.
-    EXPECT_OK(secure_element_->closeChannel(0));
-    EXPECT_OK(secure_element_->closeChannel(1));
+    // closeChannel called on non-existing basic or logical channel
+    // shall fail.
+    EXPECT_ERR(secure_element_->closeChannel(0));
+    EXPECT_ERR(secure_element_->closeChannel(1));
 
     // closeChannel called on basic channel closes the basic channel.
     EXPECT_OK(secure_element_->openBasicChannel(kSelectableAid, 0x00, &basic_channel_response));
diff --git a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
index 99d2510..e46aeee 100644
--- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
@@ -86,7 +86,17 @@
 }  // namespace
 
 class AttestKeyTest : public KeyMintAidlTestBase {
+  public:
+    void SetUp() override {
+        check_skip_test();
+        KeyMintAidlTestBase::SetUp();
+    }
+
   protected:
+    const string FEATURE_KEYSTORE_APP_ATTEST_KEY = "android.hardware.keystore.app_attest_key";
+
+    const string FEATURE_STRONGBOX_KEYSTORE = "android.hardware.strongbox_keystore";
+
     ErrorCode GenerateAttestKey(const AuthorizationSet& key_desc,
                                 const optional<AttestationKey>& attest_key,
                                 vector<uint8_t>* key_blob,
@@ -111,6 +121,59 @@
         }
         return GenerateKey(key_desc, attest_key, key_blob, key_characteristics, cert_chain);
     }
+
+    // Check if ATTEST_KEY feature is disabled
+    bool is_attest_key_feature_disabled(void) const {
+        if (!check_feature(FEATURE_KEYSTORE_APP_ATTEST_KEY)) {
+            GTEST_LOG_(INFO) << "Feature " + FEATURE_KEYSTORE_APP_ATTEST_KEY + " is disabled";
+            return true;
+        }
+
+        return false;
+    }
+
+    // Check if StrongBox KeyStore is enabled
+    bool is_strongbox_enabled(void) const {
+        if (check_feature(FEATURE_STRONGBOX_KEYSTORE)) {
+            GTEST_LOG_(INFO) << "Feature " + FEATURE_STRONGBOX_KEYSTORE + " is enabled";
+            return true;
+        }
+
+        return false;
+    }
+
+    // Check if chipset has received a waiver allowing it to be launched with
+    // Android S (or later) with Keymaster 4.0 in StrongBox
+    bool is_chipset_allowed_km4_strongbox(void) const {
+        std::array<char, PROPERTY_VALUE_MAX> buffer;
+
+        auto res = property_get("ro.vendor.qti.soc_model", buffer.data(), nullptr);
+        if (res <= 0) return false;
+
+        const string allowed_soc_models[] = {"SM8450", "SM8475", "SM8550", "SXR2230P"};
+
+        for (const string model : allowed_soc_models) {
+            if (model.compare(buffer.data()) == 0) {
+                GTEST_LOG_(INFO) << "QTI SOC Model " + model + " is allowed SB KM 4.0";
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    // Skip the test if all the following conditions hold:
+    // 1. ATTEST_KEY feature is disabled
+    // 2. STRONGBOX is enabled
+    // 3. The device is running one of the chipsets that have received a waiver
+    //     allowing it to be launched with Android S (or later) with Keymaster 4.0
+    //     in StrongBox
+    void check_skip_test(void) const {
+        if (is_attest_key_feature_disabled() && is_strongbox_enabled() &&
+            is_chipset_allowed_km4_strongbox()) {
+            GTEST_SKIP() << "Test is not applicable";
+        }
+    }
 };
 
 /*
diff --git a/sensors/aidl/multihal/android.hardware.sensors-service-multihal.rc b/sensors/aidl/multihal/android.hardware.sensors-service-multihal.rc
index 1edfbec..5aecc54 100644
--- a/sensors/aidl/multihal/android.hardware.sensors-service-multihal.rc
+++ b/sensors/aidl/multihal/android.hardware.sensors-service-multihal.rc
@@ -1,7 +1,7 @@
 service vendor.sensors-hal-multihal /vendor/bin/hw/android.hardware.sensors-service.multihal
     class hal
     user system
-    group system wakelock context_hub input
+    group system wakelock context_hub input uhid
     task_profiles ServiceCapacityLow
     capabilities BLOCK_SUSPEND
-    rlimit rtprio 10 10
\ No newline at end of file
+    rlimit rtprio 10 10
diff --git a/staging/threadnetwork/OWNERS b/staging/threadnetwork/OWNERS
new file mode 100644
index 0000000..037215d
--- /dev/null
+++ b/staging/threadnetwork/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 1203089
+
+wgtdkp@google.com
+xyk@google.com
+zhanglongxia@google.com
diff --git a/staging/threadnetwork/README.md b/staging/threadnetwork/README.md
new file mode 100644
index 0000000..12104e5
--- /dev/null
+++ b/staging/threadnetwork/README.md
@@ -0,0 +1,12 @@
+# Staging threadnetwork HAL interface
+
+The directory includes the unstable/unreleased version of `hardware/interfaces/threadnetwork`
+code which should **NOT** be used in production. But vendors may start verifying their hardware
+with the HAL interface.
+
+This directory will be cleaned up when the stable Thread HAL interface is added in
+`hardware/interfaces/threadnetwork` by version `V` or later.
+
+More information about _Thread_:
+- https://www.threadgroup.org
+- https://openthread.io
diff --git a/tetheroffload/aidl/android/hardware/tetheroffload/IOffload.aidl b/tetheroffload/aidl/android/hardware/tetheroffload/IOffload.aidl
index 30b2c8d..984f2a5 100644
--- a/tetheroffload/aidl/android/hardware/tetheroffload/IOffload.aidl
+++ b/tetheroffload/aidl/android/hardware/tetheroffload/IOffload.aidl
@@ -32,8 +32,7 @@
     /**
      * Indicates intent to start offload for tethering in immediate future.
      *
-     * This API must be called exactly once the first time that Tethering is requested by
-     * the user.
+     * This API must be called exactly once when Tethering is requested by the user.
      *
      * If this API is called multiple times without first calling stopOffload, then the subsequent
      * calls must fail without changing the state of the server.
@@ -168,7 +167,6 @@
      *           or negative number of bytes).
      *         - EX_ILLEGAL_STATE if this method is called before initOffload(), or if this method
      *           is called after stopOffload().
-     *         - EX_UNSUPPORTED_OPERATION if it is not supported.
      *         - EX_SERVICE_SPECIFIC with the error message set to a human-readable reason for the
      *           error.
      */
@@ -269,7 +267,7 @@
      * This API may only be called after initOffload and before stopOffload.
      *
      * @param iface  Downstream interface
-     * @param prefix Downstream prefix depicting address that must no longer be offloaded
+     * @param prefix Downstream prefix depicting prefix that must no longer be offloaded
      *               For e.g. 192.168.1.0/24 or 2001:4860:684::/64)
      *
      * @throws:
diff --git a/tetheroffload/aidl/android/hardware/tetheroffload/OffloadCallbackEvent.aidl b/tetheroffload/aidl/android/hardware/tetheroffload/OffloadCallbackEvent.aidl
index a95f674..15a1f93 100644
--- a/tetheroffload/aidl/android/hardware/tetheroffload/OffloadCallbackEvent.aidl
+++ b/tetheroffload/aidl/android/hardware/tetheroffload/OffloadCallbackEvent.aidl
@@ -55,7 +55,7 @@
      */
     OFFLOAD_STOPPED_LIMIT_REACHED = 5,
     /**
-     * This event is fired when the quota, applied in setDataWarning, has expired. It is
+     * This event is fired when the quota, applied in setDataWarningAndLimit, has expired. It is
      * recommended that the client query for statistics immediately after receiving this event.
      * Any offloaded traffic will continue to be offloaded until offload is stopped or
      * OFFLOAD_STOPPED_LIMIT_REACHED is sent.
diff --git a/tetheroffload/aidl/vts/functional/VtsHalTetheroffloadTargetTest.cpp b/tetheroffload/aidl/vts/functional/VtsHalTetheroffloadTargetTest.cpp
index fc8abbd..f46c9ab 100644
--- a/tetheroffload/aidl/vts/functional/VtsHalTetheroffloadTargetTest.cpp
+++ b/tetheroffload/aidl/vts/functional/VtsHalTetheroffloadTargetTest.cpp
@@ -152,15 +152,13 @@
     void initOffload(const bool expectedResult) {
         unique_fd ufd1(netlinkSocket(kFd1Groups));
         if (ufd1.get() < 0) {
-            ALOGE("Unable to create conntrack sockets: %d/%s", errno, strerror(errno));
-            FAIL();
+            FAIL() << "Unable to create conntrack sockets: " << strerror(errno);
         }
         ndk::ScopedFileDescriptor fd1 = ndk::ScopedFileDescriptor(ufd1.release());
 
         unique_fd ufd2(netlinkSocket(kFd2Groups));
         if (ufd2.get() < 0) {
-            ALOGE("Unable to create conntrack sockets: %d/%s", errno, strerror(errno));
-            FAIL();
+            FAIL() << "Unable to create conntrack sockets: " << strerror(errno);
         }
         ndk::ScopedFileDescriptor fd2 = ndk::ScopedFileDescriptor(ufd2.release());
 
@@ -214,8 +212,7 @@
     ndk::ScopedFileDescriptor fd1 = ndk::ScopedFileDescriptor(-1);
     unique_fd ufd2(netlinkSocket(kFd2Groups));
     if (ufd2.get() < 0) {
-        ALOGE("Unable to create conntrack sockets: %d/%s", errno, strerror(errno));
-        FAIL();
+        FAIL() << "Unable to create conntrack sockets: " << strerror(errno);
     }
     ndk::ScopedFileDescriptor fd2 = ndk::ScopedFileDescriptor(ufd2.release());
     mTetheringOffloadCallback = ndk::SharedRefBase::make<TetheringOffloadCallback>();
@@ -229,8 +226,7 @@
 TEST_P(TetheroffloadAidlPreInitTest, TestInitOffloadInvalidFd2ReturnsError) {
     unique_fd ufd1(netlinkSocket(kFd1Groups));
     if (ufd1.get() < 0) {
-        ALOGE("Unable to create conntrack sockets: %d/%s", errno, strerror(errno));
-        FAIL();
+        FAIL() << "Unable to create conntrack sockets: " << strerror(errno);
     }
     ndk::ScopedFileDescriptor fd1 = ndk::ScopedFileDescriptor(ufd1.release());
     ndk::ScopedFileDescriptor fd2 = ndk::ScopedFileDescriptor(-1);
@@ -264,7 +260,8 @@
     const std::string v4Addr("192.0.0.2");
     const std::string v4Gw("192.0.0.1");
     const std::vector<std::string> v6Gws{std::string("fe80::db8:1"), std::string("fe80::db8:2")};
-    EXPECT_TRUE(mOffload->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws).isOk());
+    auto ret = mOffload->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws);
+    EXPECT_TRUE(ret.isOk()) << ret;
     if (!interfaceIsUp(TEST_IFACE)) {
         return;
     }
@@ -279,7 +276,7 @@
 // Check that calling setLocalPrefixes() without first having called initOffload() returns error.
 TEST_P(TetheroffloadAidlPreInitTest, SetLocalPrefixesWithoutInitReturnsError) {
     const std::vector<std::string> prefixes{std::string("2001:db8::/64")};
-    EXPECT_EQ(mOffload->setLocalPrefixes(prefixes).getExceptionCode(), EX_ILLEGAL_STATE);
+    EXPECT_EQ(EX_ILLEGAL_STATE, mOffload->setLocalPrefixes(prefixes).getExceptionCode());
 }
 
 // Check that calling getForwardedStats() without first having called initOffload()
@@ -287,9 +284,10 @@
 TEST_P(TetheroffloadAidlPreInitTest, GetForwardedStatsWithoutInitReturnsZeroValues) {
     const std::string upstream(TEST_IFACE);
     ForwardedStats stats;
-    EXPECT_TRUE(mOffload->getForwardedStats(upstream, &stats).isOk());
-    EXPECT_EQ(stats.rxBytes, 0ULL);
-    EXPECT_EQ(stats.txBytes, 0ULL);
+    auto ret = mOffload->getForwardedStats(upstream, &stats);
+    EXPECT_TRUE(ret.isOk()) << ret;
+    EXPECT_EQ(0ULL, stats.rxBytes);
+    EXPECT_EQ(0ULL, stats.txBytes);
 }
 
 // Check that calling setDataWarningAndLimit() without first having called initOffload() returns
@@ -298,8 +296,8 @@
     const std::string upstream(TEST_IFACE);
     const int64_t warning = 5000LL;
     const int64_t limit = 5000LL;
-    EXPECT_EQ(mOffload->setDataWarningAndLimit(upstream, warning, limit).getExceptionCode(),
-              EX_ILLEGAL_STATE);
+    EXPECT_EQ(EX_ILLEGAL_STATE,
+              mOffload->setDataWarningAndLimit(upstream, warning, limit).getExceptionCode());
 }
 
 // Check that calling setUpstreamParameters() without first having called initOffload()
@@ -309,8 +307,8 @@
     const std::string v4Addr("192.0.2.0/24");
     const std::string v4Gw("192.0.2.1");
     const std::vector<std::string> v6Gws{std::string("fe80::db8:1")};
-    EXPECT_EQ(mOffload->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws).getExceptionCode(),
-              EX_ILLEGAL_STATE);
+    EXPECT_EQ(EX_ILLEGAL_STATE,
+              mOffload->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws).getExceptionCode());
 }
 
 // Check that calling addDownstream() with an IPv4 prefix without first having called
@@ -318,7 +316,7 @@
 TEST_P(TetheroffloadAidlPreInitTest, AddIPv4DownstreamWithoutInitReturnsError) {
     const std::string iface(TEST_IFACE);
     const std::string prefix("192.0.2.0/24");
-    EXPECT_EQ(mOffload->addDownstream(iface, prefix).getExceptionCode(), EX_ILLEGAL_STATE);
+    EXPECT_EQ(EX_ILLEGAL_STATE, mOffload->addDownstream(iface, prefix).getExceptionCode());
 }
 
 // Check that calling addDownstream() with an IPv6 prefix without first having called
@@ -326,7 +324,7 @@
 TEST_P(TetheroffloadAidlPreInitTest, AddIPv6DownstreamWithoutInitReturnsError) {
     const std::string iface(TEST_IFACE);
     const std::string prefix("2001:db8::/64");
-    EXPECT_EQ(mOffload->addDownstream(iface, prefix).getExceptionCode(), EX_ILLEGAL_STATE);
+    EXPECT_EQ(EX_ILLEGAL_STATE, mOffload->addDownstream(iface, prefix).getExceptionCode());
 }
 
 // Check that calling removeDownstream() with an IPv4 prefix without first having called
@@ -334,7 +332,7 @@
 TEST_P(TetheroffloadAidlPreInitTest, RemoveIPv4DownstreamWithoutInitReturnsError) {
     const std::string iface(TEST_IFACE);
     const std::string prefix("192.0.2.0/24");
-    EXPECT_EQ(mOffload->removeDownstream(iface, prefix).getExceptionCode(), EX_ILLEGAL_STATE);
+    EXPECT_EQ(EX_ILLEGAL_STATE, mOffload->removeDownstream(iface, prefix).getExceptionCode());
 }
 
 // Check that calling removeDownstream() with an IPv6 prefix without first having called
@@ -342,7 +340,7 @@
 TEST_P(TetheroffloadAidlPreInitTest, RemoveIPv6DownstreamWithoutInitReturnsError) {
     const std::string iface(TEST_IFACE);
     const std::string prefix("2001:db8::/64");
-    EXPECT_EQ(mOffload->removeDownstream(iface, prefix).getExceptionCode(), EX_ILLEGAL_STATE);
+    EXPECT_EQ(EX_ILLEGAL_STATE, mOffload->removeDownstream(iface, prefix).getExceptionCode());
 }
 
 /*
@@ -352,19 +350,20 @@
 // Test setLocalPrefixes() rejects an IPv4 address.
 TEST_P(TetheroffloadAidlGeneralTest, SetLocalPrefixesIPv4AddressFails) {
     const std::vector<std::string> prefixes{std::string("192.0.2.1")};
-    EXPECT_EQ(mOffload->setLocalPrefixes(prefixes).getExceptionCode(), EX_ILLEGAL_ARGUMENT);
+    EXPECT_EQ(EX_ILLEGAL_ARGUMENT, mOffload->setLocalPrefixes(prefixes).getExceptionCode());
 }
 
 // Test setLocalPrefixes() rejects an IPv6 address.
 TEST_P(TetheroffloadAidlGeneralTest, SetLocalPrefixesIPv6AddressFails) {
     const std::vector<std::string> prefixes{std::string("fe80::1")};
-    EXPECT_EQ(mOffload->setLocalPrefixes(prefixes).getExceptionCode(), EX_ILLEGAL_ARGUMENT);
+    EXPECT_EQ(EX_ILLEGAL_ARGUMENT, mOffload->setLocalPrefixes(prefixes).getExceptionCode());
 }
 
 // Test setLocalPrefixes() accepts both IPv4 and IPv6 prefixes.
 TEST_P(TetheroffloadAidlGeneralTest, SetLocalPrefixesIPv4v6PrefixesOk) {
     const std::vector<std::string> prefixes{std::string("192.0.2.0/24"), std::string("fe80::/64")};
-    EXPECT_TRUE(mOffload->setLocalPrefixes(prefixes).isOk());
+    auto ret = mOffload->setLocalPrefixes(prefixes);
+    EXPECT_TRUE(ret.isOk()) << ret;
 }
 
 // Test that setLocalPrefixes() fails given empty input. There is always
@@ -372,13 +371,13 @@
 // we still apply {127.0.0.0/8, ::1/128, fe80::/64} here.
 TEST_P(TetheroffloadAidlGeneralTest, SetLocalPrefixesEmptyFails) {
     const std::vector<std::string> prefixes{};
-    EXPECT_EQ(mOffload->setLocalPrefixes(prefixes).getExceptionCode(), EX_ILLEGAL_ARGUMENT);
+    EXPECT_EQ(EX_ILLEGAL_ARGUMENT, mOffload->setLocalPrefixes(prefixes).getExceptionCode());
 }
 
 // Test setLocalPrefixes() fails on incorrectly formed input strings.
 TEST_P(TetheroffloadAidlGeneralTest, SetLocalPrefixesInvalidFails) {
     const std::vector<std::string> prefixes{std::string("192.0.2.0/24"), std::string("invalid")};
-    EXPECT_EQ(mOffload->setLocalPrefixes(prefixes).getExceptionCode(), EX_ILLEGAL_ARGUMENT);
+    EXPECT_EQ(EX_ILLEGAL_ARGUMENT, mOffload->setLocalPrefixes(prefixes).getExceptionCode());
 }
 
 /*
@@ -389,9 +388,10 @@
 TEST_P(TetheroffloadAidlGeneralTest, GetForwardedStatsInvalidUpstreamIface) {
     const std::string upstream("invalid");
     ForwardedStats stats;
-    EXPECT_TRUE(mOffload->getForwardedStats(upstream, &stats).isOk());
-    EXPECT_EQ(stats.rxBytes, 0ULL);
-    EXPECT_EQ(stats.txBytes, 0ULL);
+    auto ret = mOffload->getForwardedStats(upstream, &stats);
+    EXPECT_TRUE(ret.isOk()) << ret;
+    EXPECT_EQ(0ULL, stats.rxBytes);
+    EXPECT_EQ(0ULL, stats.txBytes);
 }
 
 // TEST_IFACE is presumed to exist on the device and be up. No packets
@@ -399,9 +399,10 @@
 TEST_P(TetheroffloadAidlGeneralTest, GetForwardedStatsDummyIface) {
     const std::string upstream(TEST_IFACE);
     ForwardedStats stats;
-    EXPECT_TRUE(mOffload->getForwardedStats(upstream, &stats).isOk());
-    EXPECT_EQ(stats.rxBytes, 0ULL);
-    EXPECT_EQ(stats.txBytes, 0ULL);
+    auto ret = mOffload->getForwardedStats(upstream, &stats);
+    EXPECT_TRUE(ret.isOk()) << ret;
+    EXPECT_EQ(0ULL, stats.rxBytes);
+    EXPECT_EQ(0ULL, stats.txBytes);
 }
 
 /*
@@ -413,8 +414,8 @@
     const std::string upstream("");
     const int64_t warning = 12345LL;
     const int64_t limit = 67890LL;
-    EXPECT_THAT(mOffload->setDataWarningAndLimit(upstream, warning, limit).getExceptionCode(),
-                AnyOf(Eq(EX_ILLEGAL_ARGUMENT), Eq(EX_UNSUPPORTED_OPERATION)));
+    EXPECT_EQ(EX_ILLEGAL_ARGUMENT,
+              mOffload->setDataWarningAndLimit(upstream, warning, limit).getExceptionCode());
 }
 
 // TEST_IFACE is presumed to exist on the device and be up. No packets
@@ -423,8 +424,8 @@
     const std::string upstream(TEST_IFACE);
     const int64_t warning = 4000LL;
     const int64_t limit = 5000LL;
-    EXPECT_THAT(mOffload->setDataWarningAndLimit(upstream, warning, limit).getExceptionCode(),
-                AnyOf(Eq(EX_NONE), Eq(EX_UNSUPPORTED_OPERATION)));
+    auto ret = mOffload->setDataWarningAndLimit(upstream, warning, limit);
+    EXPECT_TRUE(ret.isOk()) << ret;
 }
 
 // TEST_IFACE is presumed to exist on the device and be up. No packets
@@ -433,8 +434,8 @@
     const std::string upstream(TEST_IFACE);
     const int64_t warning = 0LL;
     const int64_t limit = 0LL;
-    EXPECT_THAT(mOffload->setDataWarningAndLimit(upstream, warning, limit).getExceptionCode(),
-                AnyOf(Eq(EX_NONE), Eq(EX_UNSUPPORTED_OPERATION)));
+    auto ret = mOffload->setDataWarningAndLimit(upstream, warning, limit);
+    EXPECT_TRUE(ret.isOk()) << ret;
 }
 
 // TEST_IFACE is presumed to exist on the device and be up. No packets
@@ -443,7 +444,8 @@
     const std::string upstream(TEST_IFACE);
     const int64_t warning = LLONG_MAX;
     const int64_t limit = 5000LL;
-    EXPECT_TRUE(mOffload->setDataWarningAndLimit(upstream, warning, limit).isOk());
+    auto ret = mOffload->setDataWarningAndLimit(upstream, warning, limit);
+    EXPECT_TRUE(ret.isOk()) << ret;
 }
 
 // Test that setDataWarningAndLimit() with negative thresholds fails.
@@ -451,8 +453,8 @@
     const std::string upstream(TEST_IFACE);
     const int64_t warning = -1LL;
     const int64_t limit = -1LL;
-    EXPECT_THAT(mOffload->setDataWarningAndLimit(upstream, warning, limit).getExceptionCode(),
-                AnyOf(Eq(EX_ILLEGAL_ARGUMENT), Eq(EX_UNSUPPORTED_OPERATION)));
+    EXPECT_EQ(EX_ILLEGAL_ARGUMENT,
+              mOffload->setDataWarningAndLimit(upstream, warning, limit).getExceptionCode());
 }
 
 /*
@@ -466,7 +468,8 @@
     const std::string v4Addr("");
     const std::string v4Gw("");
     const std::vector<std::string> v6Gws{std::string("fe80::db8:1"), std::string("fe80::db8:2")};
-    EXPECT_TRUE(mOffload->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws).isOk());
+    auto ret = mOffload->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws);
+    EXPECT_TRUE(ret.isOk()) << ret;
 }
 
 // TEST_IFACE is presumed to exist on the device and be up. No packets
@@ -476,7 +479,8 @@
     const std::string v4Addr("");
     const std::string v4Gw("");
     const std::vector<std::string> v6Gws{std::string("fe80::db8:1"), std::string("fe80::db8:3")};
-    EXPECT_TRUE(mOffload->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws).isOk());
+    auto ret = mOffload->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws);
+    EXPECT_TRUE(ret.isOk()) << ret;
 }
 
 // TEST_IFACE is presumed to exist on the device and be up. No packets
@@ -486,7 +490,8 @@
     const std::string v4Addr("192.0.2.2");
     const std::string v4Gw("192.0.2.1");
     const std::vector<std::string> v6Gws{};
-    EXPECT_TRUE(mOffload->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws).isOk());
+    auto ret = mOffload->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws);
+    EXPECT_TRUE(ret.isOk()) << ret;
 }
 
 // TEST_IFACE is presumed to exist on the device and be up. No packets
@@ -496,7 +501,8 @@
     const std::string v4Addr("192.0.2.2");
     const std::string v4Gw("192.0.2.1");
     const std::vector<std::string> v6Gws{std::string("fe80::db8:1"), std::string("fe80::db8:2")};
-    EXPECT_TRUE(mOffload->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws).isOk());
+    auto ret = mOffload->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws);
+    EXPECT_TRUE(ret.isOk()) << ret;
 }
 
 // Test that setUpstreamParameters() fails when all parameters are empty.
@@ -505,8 +511,8 @@
     const std::string v4Addr("");
     const std::string v4Gw("");
     const std::vector<std::string> v6Gws{};
-    EXPECT_EQ(mOffload->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws).getExceptionCode(),
-              EX_ILLEGAL_ARGUMENT);
+    EXPECT_EQ(EX_ILLEGAL_ARGUMENT,
+              mOffload->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws).getExceptionCode());
 }
 
 // Test that setUpstreamParameters() fails when given empty or non-existent interface names.
@@ -517,8 +523,8 @@
     for (const auto& bogus : {"", "invalid"}) {
         SCOPED_TRACE(testing::Message() << "upstream: " << bogus);
         const std::string iface(bogus);
-        EXPECT_EQ(mOffload->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws).getExceptionCode(),
-                  EX_ILLEGAL_ARGUMENT);
+        EXPECT_EQ(EX_ILLEGAL_ARGUMENT,
+                  mOffload->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws).getExceptionCode());
     }
 }
 
@@ -530,8 +536,8 @@
     for (const auto& bogus : {"invalid", "192.0.2"}) {
         SCOPED_TRACE(testing::Message() << "v4addr: " << bogus);
         const std::string v4Addr(bogus);
-        EXPECT_EQ(mOffload->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws).getExceptionCode(),
-                  EX_ILLEGAL_ARGUMENT);
+        EXPECT_EQ(EX_ILLEGAL_ARGUMENT,
+                  mOffload->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws).getExceptionCode());
     }
 }
 
@@ -543,8 +549,8 @@
     for (const auto& bogus : {"invalid", "192.0.2"}) {
         SCOPED_TRACE(testing::Message() << "v4gateway: " << bogus);
         const std::string v4Gw(bogus);
-        EXPECT_EQ(mOffload->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws).getExceptionCode(),
-                  EX_ILLEGAL_ARGUMENT);
+        EXPECT_EQ(EX_ILLEGAL_ARGUMENT,
+                  mOffload->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws).getExceptionCode());
     }
 }
 
@@ -556,8 +562,8 @@
     for (const auto& bogus : {"", "invalid", "fe80::bogus", "192.0.2.66"}) {
         SCOPED_TRACE(testing::Message() << "v6gateway: " << bogus);
         const std::vector<std::string> v6Gws{std::string("fe80::1"), std::string(bogus)};
-        EXPECT_EQ(mOffload->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws).getExceptionCode(),
-                  EX_ILLEGAL_ARGUMENT);
+        EXPECT_EQ(EX_ILLEGAL_ARGUMENT,
+                  mOffload->setUpstreamParameters(iface, v4Addr, v4Gw, v6Gws).getExceptionCode());
     }
 }
 
@@ -569,21 +575,23 @@
 TEST_P(TetheroffloadAidlGeneralTest, AddDownstreamIPv4) {
     const std::string iface("dummy0");
     const std::string prefix("192.0.2.0/24");
-    EXPECT_TRUE(mOffload->addDownstream(iface, prefix).isOk());
+    auto ret = mOffload->addDownstream(iface, prefix);
+    EXPECT_TRUE(ret.isOk()) << ret;
 }
 
 // Test addDownstream() works given an IPv6 prefix.
 TEST_P(TetheroffloadAidlGeneralTest, AddDownstreamIPv6) {
     const std::string iface("dummy0");
     const std::string prefix("2001:db8::/64");
-    EXPECT_TRUE(mOffload->addDownstream(iface, prefix).isOk());
+    auto ret = mOffload->addDownstream(iface, prefix);
+    EXPECT_TRUE(ret.isOk()) << ret;
 }
 
 // Test addDownstream() fails given all empty parameters.
 TEST_P(TetheroffloadAidlGeneralTest, AddDownstreamEmptyFails) {
     const std::string iface("");
     const std::string prefix("");
-    EXPECT_EQ(mOffload->addDownstream(iface, prefix).getExceptionCode(), EX_ILLEGAL_ARGUMENT);
+    EXPECT_EQ(EX_ILLEGAL_ARGUMENT, mOffload->addDownstream(iface, prefix).getExceptionCode());
 }
 
 // Test addDownstream() fails given empty or non-existent interface names.
@@ -592,7 +600,7 @@
     for (const auto& bogus : {"", "invalid"}) {
         SCOPED_TRACE(testing::Message() << "iface: " << bogus);
         const std::string iface(bogus);
-        EXPECT_EQ(mOffload->addDownstream(iface, prefix).getExceptionCode(), EX_ILLEGAL_ARGUMENT);
+        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, mOffload->addDownstream(iface, prefix).getExceptionCode());
     }
 }
 
@@ -602,7 +610,7 @@
     for (const auto& bogus : {"", "192.0.2/24", "2001:db8/64"}) {
         SCOPED_TRACE(testing::Message() << "prefix: " << bogus);
         const std::string prefix(bogus);
-        EXPECT_EQ(mOffload->addDownstream(iface, prefix).getExceptionCode(), EX_ILLEGAL_ARGUMENT);
+        EXPECT_EQ(EX_ILLEGAL_ARGUMENT, mOffload->addDownstream(iface, prefix).getExceptionCode());
     }
 }
 
@@ -616,8 +624,10 @@
     const std::string prefix("192.0.2.0/24");
     // First add the downstream, otherwise removeDownstream logic can reasonably
     // return error for downstreams not previously added.
-    EXPECT_TRUE(mOffload->addDownstream(iface, prefix).isOk());
-    EXPECT_TRUE(mOffload->removeDownstream(iface, prefix).isOk());
+    auto ret = mOffload->addDownstream(iface, prefix);
+    EXPECT_TRUE(ret.isOk()) << ret;
+    ret = mOffload->removeDownstream(iface, prefix);
+    EXPECT_TRUE(ret.isOk()) << ret;
 }
 
 // Test removeDownstream() works given an IPv6 prefix.
@@ -626,15 +636,17 @@
     const std::string prefix("2001:db8::/64");
     // First add the downstream, otherwise removeDownstream logic can reasonably
     // return error for downstreams not previously added.
-    EXPECT_TRUE(mOffload->addDownstream(iface, prefix).isOk());
-    EXPECT_TRUE(mOffload->removeDownstream(iface, prefix).isOk());
+    auto ret = mOffload->addDownstream(iface, prefix);
+    EXPECT_TRUE(ret.isOk()) << ret;
+    ret = mOffload->removeDownstream(iface, prefix);
+    EXPECT_TRUE(ret.isOk()) << ret;
 }
 
 // Test removeDownstream() fails given all empty parameters.
 TEST_P(TetheroffloadAidlGeneralTest, RemoveDownstreamEmptyFails) {
     const std::string iface("");
     const std::string prefix("");
-    EXPECT_EQ(mOffload->removeDownstream(iface, prefix).getExceptionCode(), EX_ILLEGAL_ARGUMENT);
+    EXPECT_EQ(EX_ILLEGAL_ARGUMENT, mOffload->removeDownstream(iface, prefix).getExceptionCode());
 }
 
 // Test removeDownstream() fails given empty or non-existent interface names.
@@ -643,8 +655,8 @@
     for (const auto& bogus : {"", "invalid"}) {
         SCOPED_TRACE(testing::Message() << "iface: " << bogus);
         const std::string iface(bogus);
-        EXPECT_EQ(mOffload->removeDownstream(iface, prefix).getExceptionCode(),
-                  EX_ILLEGAL_ARGUMENT);
+        EXPECT_EQ(EX_ILLEGAL_ARGUMENT,
+                  mOffload->removeDownstream(iface, prefix).getExceptionCode());
     }
 }
 
@@ -654,8 +666,8 @@
     for (const auto& bogus : {"", "192.0.2/24", "2001:db8/64"}) {
         SCOPED_TRACE(testing::Message() << "prefix: " << bogus);
         const std::string prefix(bogus);
-        EXPECT_EQ(mOffload->removeDownstream(iface, prefix).getExceptionCode(),
-                  EX_ILLEGAL_ARGUMENT);
+        EXPECT_EQ(EX_ILLEGAL_ARGUMENT,
+                  mOffload->removeDownstream(iface, prefix).getExceptionCode());
     }
 }
 
diff --git a/usb/gadget/aidl/aidl_api/android.hardware.usb.gadget/current/android/hardware/usb/gadget/GadgetFunction.aidl b/usb/gadget/aidl/aidl_api/android.hardware.usb.gadget/current/android/hardware/usb/gadget/GadgetFunction.aidl
index c3f26d5..78b79e4 100644
--- a/usb/gadget/aidl/aidl_api/android.hardware.usb.gadget/current/android/hardware/usb/gadget/GadgetFunction.aidl
+++ b/usb/gadget/aidl/aidl_api/android.hardware.usb.gadget/current/android/hardware/usb/gadget/GadgetFunction.aidl
@@ -36,11 +36,12 @@
 parcelable GadgetFunction {
   const long NONE = 0;
   const long ADB = 1;
-  const long ACCESSORY = 2;
-  const long MTP = 4;
-  const long MIDI = 8;
-  const long PTP = 16;
-  const long RNDIS = 32;
-  const long AUDIO_SOURCE = 64;
-  const long NCM = 1024;
+  const long ACCESSORY = (1 << 1);
+  const long MTP = (1 << 2);
+  const long MIDI = (1 << 3);
+  const long PTP = (1 << 4);
+  const long RNDIS = (1 << 5);
+  const long AUDIO_SOURCE = (1 << 6);
+  const long UVC = (1 << 7);
+  const long NCM = (1 << 10);
 }
diff --git a/usb/gadget/aidl/android/hardware/usb/gadget/GadgetFunction.aidl b/usb/gadget/aidl/android/hardware/usb/gadget/GadgetFunction.aidl
index d82b427..dd7ee37 100644
--- a/usb/gadget/aidl/android/hardware/usb/gadget/GadgetFunction.aidl
+++ b/usb/gadget/aidl/android/hardware/usb/gadget/GadgetFunction.aidl
@@ -51,6 +51,10 @@
      */
     const long AUDIO_SOURCE = 1 << 6;
     /**
+     * UVC - Universal Video Class function.
+     */
+    const long UVC = 1 << 7;
+    /**
      * NCM - NCM function.
      */
     const long NCM = 1 << 10;
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiChipCapabilities.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiChipCapabilities.aidl
index 48dc8e0..f640861 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiChipCapabilities.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiChipCapabilities.aidl
@@ -34,6 +34,6 @@
 package android.hardware.wifi;
 @VintfStability
 parcelable WifiChipCapabilities {
-  int maxMloLinkCount;
+  int maxMloStrLinkCount;
   int maxConcurrentTdlsSessionCount;
 }
diff --git a/wifi/aidl/android/hardware/wifi/WifiChipCapabilities.aidl b/wifi/aidl/android/hardware/wifi/WifiChipCapabilities.aidl
index f65d49a..4e0578b 100644
--- a/wifi/aidl/android/hardware/wifi/WifiChipCapabilities.aidl
+++ b/wifi/aidl/android/hardware/wifi/WifiChipCapabilities.aidl
@@ -22,13 +22,13 @@
 @VintfStability
 parcelable WifiChipCapabilities {
     /**
-     * Maximum number of links used in Multi-Link Operation. The maximum
-     * number of links used for MLO can be different from the number of
-     * radios supported by the chip.
+     * Maximum number of Simultaneous Transmit and Receive (STR) links used
+     * in Multi-Link Operation. The maximum number of STR links used can be
+     * different from the maximum number of radios supported by the chip.
      *
      * This is a static configuration of the chip.
      */
-    int maxMloLinkCount;
+    int maxMloStrLinkCount;
     /**
      * Maximum number of concurrent TDLS sessions that can be enabled
      * by framework via ISupplicantStaIface#initiateTdlsSetup().
diff --git a/wifi/aidl/default/aidl_struct_util.cpp b/wifi/aidl/default/aidl_struct_util.cpp
index 68fe2e6..921b5dc 100644
--- a/wifi/aidl/default/aidl_struct_util.cpp
+++ b/wifi/aidl/default/aidl_struct_util.cpp
@@ -3316,7 +3316,7 @@
 bool convertLegacyWifiChipCapabilitiesToAidl(
         const legacy_hal::wifi_chip_capabilities& legacy_chip_capabilities,
         WifiChipCapabilities& aidl_chip_capabilities) {
-    aidl_chip_capabilities.maxMloLinkCount = legacy_chip_capabilities.max_mlo_link_count;
+    aidl_chip_capabilities.maxMloStrLinkCount = legacy_chip_capabilities.max_mlo_str_link_count;
     aidl_chip_capabilities.maxConcurrentTdlsSessionCount =
             legacy_chip_capabilities.max_concurrent_tdls_session_count;
     return true;