aosp aidl bluetooth parameter support

Bug: 228804498
Test: atest VtsHalAudioCoreTargetTest
Change-Id: If1820018d5a6750eed0d0b486e15fc7c717aa11c
diff --git a/audio/aidl/default/Bluetooth.cpp b/audio/aidl/default/Bluetooth.cpp
index c32b538..072b89f 100644
--- a/audio/aidl/default/Bluetooth.cpp
+++ b/audio/aidl/default/Bluetooth.cpp
@@ -82,19 +82,18 @@
 
 ndk::ScopedAStatus BluetoothA2dp::isEnabled(bool* _aidl_return) {
     *_aidl_return = mEnabled;
-    LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus BluetoothA2dp::setEnabled(bool in_enabled) {
     mEnabled = in_enabled;
     LOG(DEBUG) << __func__ << ": " << mEnabled;
+    if (mHandler) return mHandler();
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus BluetoothA2dp::supportsOffloadReconfiguration(bool* _aidl_return) {
-    *_aidl_return = true;
-    LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
+    *_aidl_return = false;
     return ndk::ScopedAStatus::ok();
 }
 
@@ -102,24 +101,22 @@
         const std::vector<::aidl::android::hardware::audio::core::VendorParameter>& in_parameters
                 __unused) {
     LOG(DEBUG) << __func__ << ": " << ::android::internal::ToString(in_parameters);
-    return ndk::ScopedAStatus::ok();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
 }
 
 ndk::ScopedAStatus BluetoothLe::isEnabled(bool* _aidl_return) {
     *_aidl_return = mEnabled;
-    LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus BluetoothLe::setEnabled(bool in_enabled) {
     mEnabled = in_enabled;
-    LOG(DEBUG) << __func__ << ": " << mEnabled;
+    if (mHandler) return mHandler();
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus BluetoothLe::supportsOffloadReconfiguration(bool* _aidl_return) {
-    *_aidl_return = true;
-    LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
+    *_aidl_return = false;
     return ndk::ScopedAStatus::ok();
 }
 
@@ -127,7 +124,7 @@
         const std::vector<::aidl::android::hardware::audio::core::VendorParameter>& in_parameters
                 __unused) {
     LOG(DEBUG) << __func__ << ": " << ::android::internal::ToString(in_parameters);
-    return ndk::ScopedAStatus::ok();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
 }
 
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 5625a44..f81095e 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -1371,4 +1371,13 @@
     return ndk::ScopedAStatus::ok();
 }
 
+Module::BtProfileHandles Module::getBtProfileManagerHandles() {
+    return std::make_tuple(std::weak_ptr<IBluetooth>(), std::weak_ptr<IBluetoothA2dp>(),
+                           std::weak_ptr<IBluetoothLe>());
+}
+
+ndk::ScopedAStatus Module::bluetoothParametersUpdated() {
+    return mStreams.bluetoothParametersUpdated();
+}
+
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp
index d2be48c..c5b25d6 100644
--- a/audio/aidl/default/Stream.cpp
+++ b/audio/aidl/default/Stream.cpp
@@ -723,6 +723,11 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus StreamCommonImpl::bluetoothParametersUpdated() {
+    LOG(DEBUG) << __func__;
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
 namespace {
 static std::map<AudioDevice, std::string> transformMicrophones(
         const std::vector<MicrophoneInfo>& microphones) {
diff --git a/audio/aidl/default/StreamSwitcher.cpp b/audio/aidl/default/StreamSwitcher.cpp
index e00c34b..ed4cc8a 100644
--- a/audio/aidl/default/StreamSwitcher.cpp
+++ b/audio/aidl/default/StreamSwitcher.cpp
@@ -233,8 +233,28 @@
                              << status.getDescription();
             }
         }
+        if (mBluetoothParametersUpdated) {
+            if (auto status = mStream->bluetoothParametersUpdated(); !status.isOk()) {
+                LOG(WARNING) << __func__
+                             << ": error while updating BT parameters for a new stream: "
+                             << status.getDescription();
+            }
+        }
+        mBluetoothParametersUpdated = false;
     }
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus StreamSwitcher::bluetoothParametersUpdated() {
+    if (mStream == nullptr) {
+        LOG(ERROR) << __func__ << ": stream was closed";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    if (mIsStubStream) {
+        mBluetoothParametersUpdated = true;
+        return ndk::ScopedAStatus::ok();
+    }
+    return mStream->bluetoothParametersUpdated();
+}
+
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/bluetooth/DevicePortProxy.cpp b/audio/aidl/default/bluetooth/DevicePortProxy.cpp
index aabf60f..12e204a 100644
--- a/audio/aidl/default/bluetooth/DevicePortProxy.cpp
+++ b/audio/aidl/default/bluetooth/DevicePortProxy.cpp
@@ -302,6 +302,21 @@
     return true;
 }
 
+bool BluetoothAudioPortAidl::standby() {
+    if (!inUse()) {
+        LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+        return false;
+    }
+    std::lock_guard guard(mCvMutex);
+    LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState() << " request";
+    if (mState == BluetoothStreamState::DISABLED) {
+        mState = BluetoothStreamState::STANDBY;
+        LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState() << " done";
+        return true;
+    }
+    return false;
+}
+
 bool BluetoothAudioPortAidl::condWaitState(BluetoothStreamState state) {
     const auto waitTime = std::chrono::milliseconds(kMaxWaitingTimeMs);
     std::unique_lock lock(mCvMutex);
diff --git a/audio/aidl/default/bluetooth/ModuleBluetooth.cpp b/audio/aidl/default/bluetooth/ModuleBluetooth.cpp
index bb11f0a..bfe7ca0 100644
--- a/audio/aidl/default/bluetooth/ModuleBluetooth.cpp
+++ b/audio/aidl/default/bluetooth/ModuleBluetooth.cpp
@@ -28,6 +28,34 @@
 using aidl::android::media::audio::common::AudioOffloadInfo;
 using aidl::android::media::audio::common::MicrophoneInfo;
 
+ndk::ScopedAStatus ModuleBluetooth::getBluetoothA2dp(
+        std::shared_ptr<IBluetoothA2dp>* _aidl_return) {
+    if (!mBluetoothA2dp) {
+        auto handle = ndk::SharedRefBase::make<BluetoothA2dp>();
+        handle->registerHandler(std::bind(&ModuleBluetooth::bluetoothParametersUpdated, this));
+        mBluetoothA2dp = handle;
+    }
+    *_aidl_return = mBluetoothA2dp.getInstance();
+    LOG(DEBUG) << __func__ << ": returning instance of IBluetoothA2dp: " << _aidl_return->get();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ModuleBluetooth::getBluetoothLe(std::shared_ptr<IBluetoothLe>* _aidl_return) {
+    if (!mBluetoothLe) {
+        auto handle = ndk::SharedRefBase::make<BluetoothLe>();
+        handle->registerHandler(std::bind(&ModuleBluetooth::bluetoothParametersUpdated, this));
+        mBluetoothLe = handle;
+    }
+    *_aidl_return = mBluetoothLe.getInstance();
+    LOG(DEBUG) << __func__ << ": returning instance of IBluetoothLe: " << _aidl_return->get();
+    return ndk::ScopedAStatus::ok();
+}
+
+Module::BtProfileHandles ModuleBluetooth::getBtProfileManagerHandles() {
+    return std::make_tuple(std::weak_ptr<IBluetooth>(), mBluetoothA2dp.getInstance(),
+                           mBluetoothLe.getInstance());
+}
+
 ndk::ScopedAStatus ModuleBluetooth::getMicMute(bool* _aidl_return __unused) {
     LOG(DEBUG) << __func__ << ": is not supported";
     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
@@ -42,14 +70,14 @@
         StreamContext&& context, const SinkMetadata& sinkMetadata,
         const std::vector<MicrophoneInfo>& microphones, std::shared_ptr<StreamIn>* result) {
     return createStreamInstance<StreamInBluetooth>(result, std::move(context), sinkMetadata,
-                                                   microphones);
+                                                   microphones, getBtProfileManagerHandles());
 }
 
 ndk::ScopedAStatus ModuleBluetooth::createOutputStream(
         StreamContext&& context, const SourceMetadata& sourceMetadata,
         const std::optional<AudioOffloadInfo>& offloadInfo, std::shared_ptr<StreamOut>* result) {
     return createStreamInstance<StreamOutBluetooth>(result, std::move(context), sourceMetadata,
-                                                    offloadInfo);
+                                                    offloadInfo, getBtProfileManagerHandles());
 }
 
 ndk::ScopedAStatus ModuleBluetooth::onMasterMuteChanged(bool) {
diff --git a/audio/aidl/default/bluetooth/StreamBluetooth.cpp b/audio/aidl/default/bluetooth/StreamBluetooth.cpp
index dfccb0e..8cb93e3 100644
--- a/audio/aidl/default/bluetooth/StreamBluetooth.cpp
+++ b/audio/aidl/default/bluetooth/StreamBluetooth.cpp
@@ -53,13 +53,16 @@
 }
 
 // pcm configuration params are not really used by the module
-StreamBluetooth::StreamBluetooth(StreamContext* context, const Metadata& metadata)
+StreamBluetooth::StreamBluetooth(StreamContext* context, const Metadata& metadata,
+                                 Module::BtProfileHandles&& btHandles)
     : StreamCommonImpl(context, metadata),
       mSampleRate(getContext().getSampleRate()),
       mChannelLayout(getContext().getChannelLayout()),
       mFormat(getContext().getFormat()),
       mFrameSizeBytes(getContext().getFrameSize()),
-      mIsInput(isInput(metadata)) {
+      mIsInput(isInput(metadata)),
+      mBluetoothA2dp(std::move(std::get<Module::BtInterface::BTA2DP>(btHandles))),
+      mBluetoothLe(std::move(std::get<Module::BtInterface::BTLE>(btHandles))) {
     mPreferredDataIntervalUs =
             mIsInput ? kBluetoothDefaultInputBufferMs : kBluetoothDefaultOutputBufferMs;
     mPreferredFrameCount = getFrameCount(mPreferredDataIntervalUs, mSampleRate);
@@ -278,10 +281,46 @@
                 : ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
 }
 
+ndk::ScopedAStatus StreamBluetooth::bluetoothParametersUpdated() {
+    if (mIsInput) {
+        LOG(WARNING) << __func__ << ": not handled";
+        return ndk::ScopedAStatus::ok();
+    }
+    auto applyParam = [](const std::shared_ptr<BluetoothAudioPortAidl>& proxy,
+                         bool isEnabled) -> bool {
+        if (!isEnabled) {
+            if (proxy->suspend()) return proxy->setState(BluetoothStreamState::DISABLED);
+            return false;
+        }
+        return proxy->standby();
+    };
+    bool hasA2dpParam, enableA2dp;
+    auto btA2dp = mBluetoothA2dp.lock();
+    hasA2dpParam = btA2dp != nullptr && btA2dp->isEnabled(&enableA2dp).isOk();
+    bool hasLeParam, enableLe;
+    auto btLe = mBluetoothLe.lock();
+    hasLeParam = btLe != nullptr && btLe->isEnabled(&enableLe).isOk();
+    std::unique_lock lock(mLock);
+    ::android::base::ScopedLockAssertion lock_assertion(mLock);
+    if (!mIsInitialized) {
+        LOG(WARNING) << __func__ << ": init not done";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    for (auto proxy : mBtDeviceProxies) {
+        if ((hasA2dpParam && proxy->isA2dp() && !applyParam(proxy, enableA2dp)) ||
+            (hasLeParam && proxy->isLeAudio() && !applyParam(proxy, enableLe))) {
+            LOG(DEBUG) << __func__ << ": applyParam failed";
+            return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+        }
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
 StreamInBluetooth::StreamInBluetooth(StreamContext&& context, const SinkMetadata& sinkMetadata,
-                                     const std::vector<MicrophoneInfo>& microphones)
+                                     const std::vector<MicrophoneInfo>& microphones,
+                                     Module::BtProfileHandles&& btProfileHandles)
     : StreamIn(std::move(context), microphones),
-      StreamBluetooth(&(StreamIn::mContext), sinkMetadata) {}
+      StreamBluetooth(&(StreamIn::mContext), sinkMetadata, std::move(btProfileHandles)) {}
 
 ndk::ScopedAStatus StreamInBluetooth::getActiveMicrophones(
         std::vector<MicrophoneDynamicInfo>* _aidl_return __unused) {
@@ -291,8 +330,9 @@
 
 StreamOutBluetooth::StreamOutBluetooth(StreamContext&& context,
                                        const SourceMetadata& sourceMetadata,
-                                       const std::optional<AudioOffloadInfo>& offloadInfo)
+                                       const std::optional<AudioOffloadInfo>& offloadInfo,
+                                       Module::BtProfileHandles&& btProfileHandles)
     : StreamOut(std::move(context), offloadInfo),
-      StreamBluetooth(&(StreamOut::mContext), sourceMetadata) {}
+      StreamBluetooth(&(StreamOut::mContext), sourceMetadata, std::move(btProfileHandles)) {}
 
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/Bluetooth.h b/audio/aidl/default/include/core-impl/Bluetooth.h
index 10e9045..44899bc 100644
--- a/audio/aidl/default/include/core-impl/Bluetooth.h
+++ b/audio/aidl/default/include/core-impl/Bluetooth.h
@@ -22,6 +22,15 @@
 
 namespace aidl::android::hardware::audio::core {
 
+class ParamChangeHandler {
+  public:
+    ParamChangeHandler() = default;
+    void registerHandler(std::function<ndk::ScopedAStatus()> handler) { mHandler = handler; }
+
+  protected:
+    std::function<ndk::ScopedAStatus()> mHandler = nullptr;
+};
+
 class Bluetooth : public BnBluetooth {
   public:
     Bluetooth();
@@ -34,7 +43,7 @@
     HfpConfig mHfpConfig;
 };
 
-class BluetoothA2dp : public BnBluetoothA2dp {
+class BluetoothA2dp : public BnBluetoothA2dp, public ParamChangeHandler {
   public:
     BluetoothA2dp() = default;
 
@@ -49,7 +58,7 @@
     bool mEnabled = false;
 };
 
-class BluetoothLe : public BnBluetoothLe {
+class BluetoothLe : public BnBluetoothLe, public ParamChangeHandler {
   public:
     BluetoothLe() = default;
 
diff --git a/audio/aidl/default/include/core-impl/DevicePortProxy.h b/audio/aidl/default/include/core-impl/DevicePortProxy.h
index 72ffaad..13b8c91 100644
--- a/audio/aidl/default/include/core-impl/DevicePortProxy.h
+++ b/audio/aidl/default/include/core-impl/DevicePortProxy.h
@@ -83,8 +83,16 @@
 
     /**
      * When the Audio framework / HAL wants to change the stream state, it invokes
-     * these 3 functions to control the Bluetooth stack (Audio Control Path).
-     * Note: Both start() and suspend() will return true when there are no errors.
+     * these 4 functions to control the Bluetooth stack (Audio Control Path).
+     * Note: standby(), start() and suspend() will return true when there are no errors.
+
+     * Called by Audio framework / HAL to change the state to stand by. When A2DP/LE profile is
+     * disabled, the port is first set to STANDBY by calling suspend and then mState is set to
+     * DISABLED. To reset the state back to STANDBY this method is called.
+     */
+    virtual bool standby() = 0;
+
+    /**
      * Called by Audio framework / HAL to start the stream
      */
     virtual bool start() = 0;
@@ -160,6 +168,7 @@
 
     void forcePcmStereoToMono(bool force) override { mIsStereoToMono = force; }
 
+    bool standby() override;
     bool start() override;
     bool suspend() override;
     void stop() override;
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index e52940e..fb3eef2 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -34,11 +34,16 @@
     // This value is used for all AudioPatches and reported by all streams.
     static constexpr int32_t kLatencyMs = 10;
     enum Type : int { DEFAULT, R_SUBMIX, STUB, USB, BLUETOOTH };
+    enum BtInterface : int { BTCONF, BTA2DP, BTLE };
 
     static std::shared_ptr<Module> createInstance(Type type);
 
     explicit Module(Type type) : mType(type) {}
 
+    typedef std::tuple<std::weak_ptr<IBluetooth>, std::weak_ptr<IBluetoothA2dp>,
+                       std::weak_ptr<IBluetoothLe>>
+            BtProfileHandles;
+
   protected:
     // The vendor extension done via inheritance can override interface methods and augment
     // a call to the base implementation.
@@ -185,6 +190,7 @@
     virtual std::unique_ptr<internal::Configuration> initializeConfig();
 
     // Utility and helper functions accessible to subclasses.
+    ndk::ScopedAStatus bluetoothParametersUpdated();
     void cleanUpPatch(int32_t patchId);
     ndk::ScopedAStatus createStreamContext(
             int32_t in_portConfigId, int64_t in_bufferSizeFrames,
@@ -196,6 +202,7 @@
     std::set<int32_t> findConnectedPortConfigIds(int32_t portConfigId);
     ndk::ScopedAStatus findPortIdForNewStream(
             int32_t in_portConfigId, ::aidl::android::media::audio::common::AudioPort** port);
+    virtual BtProfileHandles getBtProfileManagerHandles();
     internal::Configuration& getConfig();
     const ConnectedDevicePorts& getConnectedDevicePorts() const { return mConnectedDevicePorts; }
     bool getMasterMute() const { return mMasterMute; }
diff --git a/audio/aidl/default/include/core-impl/ModuleBluetooth.h b/audio/aidl/default/include/core-impl/ModuleBluetooth.h
index e20f7a3..68b4e6b 100644
--- a/audio/aidl/default/include/core-impl/ModuleBluetooth.h
+++ b/audio/aidl/default/include/core-impl/ModuleBluetooth.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include "core-impl/Bluetooth.h"
 #include "core-impl/Module.h"
 
 namespace aidl::android::hardware::audio::core {
@@ -25,6 +26,10 @@
     ModuleBluetooth() : Module(Type::BLUETOOTH) {}
 
   private:
+    BtProfileHandles getBtProfileManagerHandles() override;
+
+    ndk::ScopedAStatus getBluetoothA2dp(std::shared_ptr<IBluetoothA2dp>* _aidl_return) override;
+    ndk::ScopedAStatus getBluetoothLe(std::shared_ptr<IBluetoothLe>* _aidl_return) override;
     ndk::ScopedAStatus getMicMute(bool* _aidl_return) override;
     ndk::ScopedAStatus setMicMute(bool in_mute) override;
 
@@ -41,6 +46,9 @@
             std::shared_ptr<StreamOut>* result) override;
     ndk::ScopedAStatus onMasterMuteChanged(bool mute) override;
     ndk::ScopedAStatus onMasterVolumeChanged(float volume) override;
+
+    ChildInterface<IBluetoothA2dp> mBluetoothA2dp;
+    ChildInterface<IBluetoothLe> mBluetoothLe;
 };
 
 }  // namespace aidl::android::hardware::audio::core
\ No newline at end of file
diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
index fa2b760..1ba3520 100644
--- a/audio/aidl/default/include/core-impl/Stream.h
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -354,6 +354,7 @@
     virtual const ConnectedDevices& getConnectedDevices() const = 0;
     virtual ndk::ScopedAStatus setConnectedDevices(
             const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) = 0;
+    virtual ndk::ScopedAStatus bluetoothParametersUpdated() = 0;
 };
 
 // This is equivalent to automatically generated 'IStreamCommonDelegator' but uses
@@ -454,6 +455,7 @@
     ndk::ScopedAStatus setConnectedDevices(
             const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
             override;
+    ndk::ScopedAStatus bluetoothParametersUpdated() override;
 
   protected:
     static StreamWorkerInterface::CreateInstance getDefaultInWorkerCreator() {
@@ -584,6 +586,11 @@
         if (s) return s->setConnectedDevices(devices);
         return ndk::ScopedAStatus::ok();
     }
+    ndk::ScopedAStatus bluetoothParametersUpdated() {
+        auto s = mStream.lock();
+        if (s) return s->bluetoothParametersUpdated();
+        return ndk::ScopedAStatus::ok();
+    }
 
   private:
     std::weak_ptr<StreamCommonInterface> mStream;
@@ -612,6 +619,14 @@
         }
         return ndk::ScopedAStatus::ok();
     }
+    ndk::ScopedAStatus bluetoothParametersUpdated() {
+        bool isOk = true;
+        for (auto& it : mStreams) {
+            if (!it.second.bluetoothParametersUpdated().isOk()) isOk = false;
+        }
+        return isOk ? ndk::ScopedAStatus::ok()
+                    : ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+    }
 
   private:
     // Maps port ids and port config ids to streams. Multimap because a port
diff --git a/audio/aidl/default/include/core-impl/StreamBluetooth.h b/audio/aidl/default/include/core-impl/StreamBluetooth.h
index b9c5ea9..c2f8c1d 100644
--- a/audio/aidl/default/include/core-impl/StreamBluetooth.h
+++ b/audio/aidl/default/include/core-impl/StreamBluetooth.h
@@ -19,15 +19,20 @@
 #include <mutex>
 #include <vector>
 
+#include <aidl/android/hardware/audio/core/IBluetooth.h>
+#include <aidl/android/hardware/audio/core/IBluetoothA2dp.h>
+#include <aidl/android/hardware/audio/core/IBluetoothLe.h>
+
 #include "core-impl/DevicePortProxy.h"
+#include "core-impl/Module.h"
 #include "core-impl/Stream.h"
 
 namespace aidl::android::hardware::audio::core {
 
 class StreamBluetooth : public StreamCommonImpl {
   public:
-    StreamBluetooth(StreamContext* context, const Metadata& metadata);
-
+    StreamBluetooth(StreamContext* context, const Metadata& metadata,
+                    Module::BtProfileHandles&& btHandles);
     // Methods of 'DriverInterface'.
     ::android::status_t init() override;
     ::android::status_t drain(StreamDescriptor::DrainMode) override;
@@ -44,6 +49,7 @@
     ndk::ScopedAStatus prepareToClose() override;
     const ConnectedDevices& getConnectedDevices() const override;
     ndk::ScopedAStatus setConnectedDevices(const ConnectedDevices& devices) override;
+    ndk::ScopedAStatus bluetoothParametersUpdated() override;
 
   private:
     // Audio Pcm Config
@@ -52,7 +58,8 @@
     const ::aidl::android::media::audio::common::AudioFormatDescription mFormat;
     const size_t mFrameSizeBytes;
     const bool mIsInput;
-
+    const std::weak_ptr<IBluetoothA2dp> mBluetoothA2dp;
+    const std::weak_ptr<IBluetoothLe> mBluetoothLe;
     size_t mPreferredDataIntervalUs;
     size_t mPreferredFrameCount;
 
@@ -72,7 +79,8 @@
     StreamInBluetooth(
             StreamContext&& context,
             const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
-            const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
+            const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
+            Module::BtProfileHandles&& btHandles);
 
   private:
     void onClose(StreamDescriptor::State) override { defaultOnClose(); }
@@ -88,7 +96,8 @@
             StreamContext&& context,
             const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
             const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
-                    offloadInfo);
+                    offloadInfo,
+            Module::BtProfileHandles&& btHandles);
 
   private:
     void onClose(StreamDescriptor::State) override { defaultOnClose(); }
diff --git a/audio/aidl/default/include/core-impl/StreamSwitcher.h b/audio/aidl/default/include/core-impl/StreamSwitcher.h
index 2cb8470..3086ef9 100644
--- a/audio/aidl/default/include/core-impl/StreamSwitcher.h
+++ b/audio/aidl/default/include/core-impl/StreamSwitcher.h
@@ -129,6 +129,7 @@
     ndk::ScopedAStatus setConnectedDevices(
             const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
             override;
+    ndk::ScopedAStatus bluetoothParametersUpdated() override;
 
   protected:
     // Since switching a stream requires closing down the current stream, StreamSwitcher
@@ -187,6 +188,7 @@
     std::optional<int32_t> mHwAvSyncId;
     std::vector<VndParam> mMissedParameters;
     std::vector<std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>> mEffects;
+    bool mBluetoothParametersUpdated = false;
 };
 
 }  // namespace aidl::android::hardware::audio::core