audio: Add IBluetoothA2dp

Similar to IBluetooth interface which controls SCO/HFP,
IBluetoothA2dp controls the A2DP profile. This interface
replaces the following string parameters:

AUDIO_PARAMETER_A2DP_RECONFIG_SUPPORTED
AUDIO_PARAMETER_RECONFIG_A2DP
"A2dpSuspended"

Also, refactor fields used by Module implementation
for persistent child interfaces.

Bug: 270731693
Test: atest VtsHalAudioCoreTargetTest
Change-Id: Ie62952c3bc3af2f53535d716e5b57bf48c661306
Merged-In: Ie62952c3bc3af2f53535d716e5b57bf48c661306
diff --git a/audio/aidl/default/Bluetooth.cpp b/audio/aidl/default/Bluetooth.cpp
index 38e0c21..bd9a864 100644
--- a/audio/aidl/default/Bluetooth.cpp
+++ b/audio/aidl/default/Bluetooth.cpp
@@ -19,6 +19,7 @@
 
 #include "core-impl/Bluetooth.h"
 
+using aidl::android::hardware::audio::core::VendorParameter;
 using aidl::android::media::audio::common::Boolean;
 using aidl::android::media::audio::common::Float;
 using aidl::android::media::audio::common::Int;
@@ -79,4 +80,29 @@
     return ndk::ScopedAStatus::ok();
 }
 
+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;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothA2dp::supportsOffloadReconfiguration(bool* _aidl_return) {
+    *_aidl_return = true;
+    LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothA2dp::reconfigureOffload(
+        const std::vector<::aidl::android::hardware::audio::core::VendorParameter>& in_parameters
+                __unused) {
+    LOG(DEBUG) << __func__ << ": " << ::android::internal::ToString(in_parameters);
+    return ndk::ScopedAStatus::ok();
+}
+
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 5440b8d..a8f03af 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -370,29 +370,32 @@
 }
 
 ndk::ScopedAStatus Module::getTelephony(std::shared_ptr<ITelephony>* _aidl_return) {
-    if (mTelephony == nullptr) {
+    if (!mTelephony) {
         mTelephony = ndk::SharedRefBase::make<Telephony>();
-        mTelephonyBinder = mTelephony->asBinder();
-        AIBinder_setMinSchedulerPolicy(mTelephonyBinder.get(), SCHED_NORMAL,
-                                       ANDROID_PRIORITY_AUDIO);
     }
-    *_aidl_return = mTelephony;
+    *_aidl_return = mTelephony.getPtr();
     LOG(DEBUG) << __func__ << ": returning instance of ITelephony: " << _aidl_return->get();
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus Module::getBluetooth(std::shared_ptr<IBluetooth>* _aidl_return) {
-    if (mBluetooth == nullptr) {
+    if (!mBluetooth) {
         mBluetooth = ndk::SharedRefBase::make<Bluetooth>();
-        mBluetoothBinder = mBluetooth->asBinder();
-        AIBinder_setMinSchedulerPolicy(mBluetoothBinder.get(), SCHED_NORMAL,
-                                       ANDROID_PRIORITY_AUDIO);
     }
-    *_aidl_return = mBluetooth;
+    *_aidl_return = mBluetooth.getPtr();
     LOG(DEBUG) << __func__ << ": returning instance of IBluetooth: " << _aidl_return->get();
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus Module::getBluetoothA2dp(std::shared_ptr<IBluetoothA2dp>* _aidl_return) {
+    if (!mBluetoothA2dp) {
+        mBluetoothA2dp = ndk::SharedRefBase::make<BluetoothA2dp>();
+    }
+    *_aidl_return = mBluetoothA2dp.getPtr();
+    LOG(DEBUG) << __func__ << ": returning instance of IBluetoothA2dp: " << _aidl_return->get();
+    return ndk::ScopedAStatus::ok();
+}
+
 ndk::ScopedAStatus Module::connectExternalDevice(const AudioPort& in_templateIdAndAdditionalData,
                                                  AudioPort* _aidl_return) {
     const int32_t templateId = in_templateIdAndAdditionalData.id;
@@ -1039,13 +1042,10 @@
 }
 
 ndk::ScopedAStatus Module::getSoundDose(std::shared_ptr<ISoundDose>* _aidl_return) {
-    if (mSoundDose == nullptr) {
+    if (!mSoundDose) {
         mSoundDose = ndk::SharedRefBase::make<sounddose::SoundDose>();
-        mSoundDoseBinder = mSoundDose->asBinder();
-        AIBinder_setMinSchedulerPolicy(mSoundDoseBinder.get(), SCHED_NORMAL,
-                                       ANDROID_PRIORITY_AUDIO);
     }
-    *_aidl_return = mSoundDose;
+    *_aidl_return = mSoundDose.getPtr();
     LOG(DEBUG) << __func__ << ": returning instance of ISoundDose: " << _aidl_return->get();
     return ndk::ScopedAStatus::ok();
 }
diff --git a/audio/aidl/default/include/core-impl/Bluetooth.h b/audio/aidl/default/include/core-impl/Bluetooth.h
index f2e762d..e2f48ba 100644
--- a/audio/aidl/default/include/core-impl/Bluetooth.h
+++ b/audio/aidl/default/include/core-impl/Bluetooth.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <aidl/android/hardware/audio/core/BnBluetooth.h>
+#include <aidl/android/hardware/audio/core/BnBluetoothA2dp.h>
 
 namespace aidl::android::hardware::audio::core {
 
@@ -32,4 +33,19 @@
     HfpConfig mHfpConfig;
 };
 
+class BluetoothA2dp : public BnBluetoothA2dp {
+  public:
+    BluetoothA2dp() = default;
+
+  private:
+    ndk::ScopedAStatus isEnabled(bool* _aidl_return) override;
+    ndk::ScopedAStatus setEnabled(bool in_enabled) override;
+    ndk::ScopedAStatus supportsOffloadReconfiguration(bool* _aidl_return) override;
+    ndk::ScopedAStatus reconfigureOffload(
+            const std::vector<::aidl::android::hardware::audio::core::VendorParameter>&
+                    in_parameters) override;
+
+    bool mEnabled = false;
+};
+
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index 8365b34..6b254db 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -46,11 +46,32 @@
         bool forceTransientBurst = false;
         bool forceSynchronousDrain = false;
     };
+    // Helper used for interfaces that require a persistent instance. We hold them via a strong
+    // pointer. The binder token is retained for a call to 'setMinSchedulerPolicy'.
+    template <class C>
+    struct ChildInterface : private std::pair<std::shared_ptr<C>, ndk::SpAIBinder> {
+        ChildInterface() {}
+        ChildInterface& operator=(const std::shared_ptr<C>& c) {
+            return operator=(std::shared_ptr<C>(c));
+        }
+        ChildInterface& operator=(std::shared_ptr<C>&& c) {
+            this->first = std::move(c);
+            this->second = this->first->asBinder();
+            AIBinder_setMinSchedulerPolicy(this->second.get(), SCHED_NORMAL,
+                                           ANDROID_PRIORITY_AUDIO);
+            return *this;
+        }
+        explicit operator bool() const { return !!this->first; }
+        C& operator*() const { return *(this->first); }
+        C* operator->() const { return this->first; }
+        std::shared_ptr<C> getPtr() const { return this->first; }
+    };
 
     ndk::ScopedAStatus setModuleDebug(
             const ::aidl::android::hardware::audio::core::ModuleDebug& in_debug) override;
     ndk::ScopedAStatus getTelephony(std::shared_ptr<ITelephony>* _aidl_return) override;
     ndk::ScopedAStatus getBluetooth(std::shared_ptr<IBluetooth>* _aidl_return) override;
+    ndk::ScopedAStatus getBluetoothA2dp(std::shared_ptr<IBluetoothA2dp>* _aidl_return) override;
     ndk::ScopedAStatus connectExternalDevice(
             const ::aidl::android::media::audio::common::AudioPort& in_templateIdAndAdditionalData,
             ::aidl::android::media::audio::common::AudioPort* _aidl_return) override;
@@ -151,12 +172,9 @@
     std::unique_ptr<internal::Configuration> mConfig;
     ModuleDebug mDebug;
     VendorDebug mVendorDebug;
-    // For the interfaces requiring to return the same instance, we need to hold them
-    // via a strong pointer. The binder token is retained for a call to 'setMinSchedulerPolicy'.
-    std::shared_ptr<ITelephony> mTelephony;
-    ndk::SpAIBinder mTelephonyBinder;
-    std::shared_ptr<IBluetooth> mBluetooth;
-    ndk::SpAIBinder mBluetoothBinder;
+    ChildInterface<ITelephony> mTelephony;
+    ChildInterface<IBluetooth> mBluetooth;
+    ChildInterface<IBluetoothA2dp> mBluetoothA2dp;
     // ids of ports created at runtime via 'connectExternalDevice'.
     std::set<int32_t> mConnectedDevicePorts;
     Streams mStreams;
@@ -166,8 +184,7 @@
     bool mMasterMute = false;
     float mMasterVolume = 1.0f;
     bool mMicMute = false;
-    std::shared_ptr<sounddose::ISoundDose> mSoundDose;
-    ndk::SpAIBinder mSoundDoseBinder;
+    ChildInterface<sounddose::ISoundDose> mSoundDose;
     std::optional<bool> mIsMmapSupported;
 
   protected: