CSD: add logic for selecting ISoundDose interface

There are two options for supporting sound dose. 1) the hardware
implements the standalone AIDL sound dose interface together with the
legacy audio HIDL HAL or 2) the hardware implements the new sound dose
methods as part of the audio AIDL HAL. The new logic selects the
implementation to use depending on the audio HAL that is active.

Test: bluejay-userdebug logs
Bug: 264254879
Change-Id: I0af9cd31c2e97bb9c9895439f55bbfa50e87e159
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index 829a79a..b6602ec 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -207,6 +207,8 @@
 cc_library_shared {
     name: "libaudiohal@7.1",
     defaults: [
+        "latest_android_hardware_audio_core_sounddose_ndk_shared",
+        "latest_android_hardware_audio_sounddose_ndk_shared",
         "libaudiohal_default",
         "libaudiohal_hidl_default"
     ],
@@ -226,6 +228,9 @@
         "android.hardware.audio@7.1-util",
         "libaudiohal.effect@7.0",
     ],
+    shared_libs: [
+        "libbinder_ndk",
+    ],
     cflags: [
         "-DMAJOR_VERSION=7",
         "-DMINOR_VERSION=1",
@@ -241,6 +246,7 @@
         "libaudiohal_default",
         "latest_android_hardware_audio_common_ndk_shared",
         "latest_android_hardware_audio_core_ndk_shared",
+        "latest_android_hardware_audio_core_sounddose_ndk_shared",
         "latest_android_hardware_audio_effect_ndk_static",
         "latest_android_media_audio_common_types_ndk_shared",
     ],
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index 179a655..280306d 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -15,6 +15,7 @@
  */
 
 #define LOG_TAG "DeviceHalAidl"
+// #define LOG_NDEBUG 0
 
 #include <aidl/android/hardware/audio/core/StreamDescriptor.h>
 #include <error/expected_utils.h>
@@ -32,6 +33,7 @@
 using aidl::android::hardware::audio::core::IModule;
 using aidl::android::hardware::audio::core::ITelephony;
 using aidl::android::hardware::audio::core::StreamDescriptor;
+using aidl::android::hardware::audio::core::sounddose::ISoundDose;
 
 namespace android {
 
@@ -286,4 +288,24 @@
     return INVALID_OPERATION;
 }
 
+status_t DeviceHalAidl::getSoundDoseInterface(const std::string& module,
+                                              ::ndk::SpAIBinder* soundDoseBinder)  {
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    if (mSoundDose == nullptr) {
+        ndk::ScopedAStatus status = mModule->getSoundDose(&mSoundDose);
+        if (!status.isOk()) {
+            ALOGE("%s failed to return the sound dose interface for module %s: %s",
+                  __func__,
+                  module.c_str(),
+                  status.getDescription().c_str());
+            return BAD_VALUE;
+        }
+    }
+    *soundDoseBinder = mSoundDose->asBinder();
+    ALOGI("%s using audio AIDL HAL sound dose interface", __func__);
+
+    return OK;
+}
+
 } // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index 99e28d8..b1aa351 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <aidl/android/hardware/audio/core/sounddose/BpSoundDose.h>
 #include <aidl/android/hardware/audio/core/BpModule.h>
 #include <media/audiohal/DeviceHalInterface.h>
 #include <media/audiohal/EffectHalInterface.h>
@@ -117,10 +118,15 @@
 
     int32_t supportsBluetoothVariableLatency(bool* supports __unused) override;
 
+    status_t getSoundDoseInterface(const std::string& module,
+                                   ::ndk::SpAIBinder* soundDoseBinder) override;
+
   private:
     friend class sp<DeviceHalAidl>;
 
     const std::shared_ptr<::aidl::android::hardware::audio::core::IModule> mModule;
+    std::shared_ptr<::aidl::android::hardware::audio::core::sounddose::ISoundDose>
+        mSoundDose = nullptr;
 
     // Can not be constructed directly by clients.
     explicit DeviceHalAidl(
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index 12acebd..e0b1afb 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -17,7 +17,7 @@
 #include <stdio.h>
 
 #define LOG_TAG "DeviceHalHidl"
-//#define LOG_NDEBUG 0
+// #define LOG_NDEBUG 0
 
 #include <cutils/native_handle.h>
 #include <cutils/properties.h>
@@ -35,6 +35,17 @@
 #include "ParameterUtils.h"
 #include "StreamHalHidl.h"
 
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+#include <aidl/android/hardware/audio/core/sounddose/BpSoundDose.h>
+#include <aidl/android/hardware/audio/sounddose/BpSoundDoseFactory.h>
+#include <android/binder_manager.h>
+
+constexpr std::string_view kSoundDoseInterfaceModule = "/default";
+
+using aidl::android::hardware::audio::core::sounddose::ISoundDose;
+using aidl::android::hardware::audio::sounddose::ISoundDoseFactory;
+#endif
+
 using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
 using ::android::hardware::audio::common::utils::EnumBitfield;
 using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::CoreUtils;
@@ -46,8 +57,21 @@
 using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
 using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
 
+class DeviceHalHidl::SoundDoseWrapper {
+public:
+    SoundDoseWrapper() = default;
+    ~SoundDoseWrapper() = default;
+
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+    std::shared_ptr<ISoundDoseFactory> mSoundDoseFactory;
+    std::shared_ptr<ISoundDose> mSoundDose;
+#endif
+};
+
 DeviceHalHidl::DeviceHalHidl(const sp<::android::hardware::audio::CPP_VERSION::IDevice>& device)
-        : CoreConversionHelperHidl("DeviceHalHidl"), mDevice(device) {
+        : CoreConversionHelperHidl("DeviceHalHidl"),
+          mDevice(device),
+          mSoundDoseWrapper(std::make_unique<DeviceHalHidl::SoundDoseWrapper>()) {
 }
 
 DeviceHalHidl::DeviceHalHidl(
@@ -56,7 +80,8 @@
 #if MAJOR_VERSION <= 6 || (MAJOR_VERSION == 7 && MINOR_VERSION == 0)
           mDevice(device),
 #endif
-          mPrimaryDevice(device) {
+          mPrimaryDevice(device),
+          mSoundDoseWrapper(std::make_unique<DeviceHalHidl::SoundDoseWrapper>()) {
 #if MAJOR_VERSION == 7 && MINOR_VERSION == 1
     auto getDeviceRet = mPrimaryDevice->getDevice();
     if (getDeviceRet.isOk()) {
@@ -574,4 +599,50 @@
     return processReturn("dump", ret);
 }
 
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+status_t DeviceHalHidl::getSoundDoseInterface(const std::string& module,
+                                              ::ndk::SpAIBinder* soundDoseBinder) {
+    if (mSoundDoseWrapper->mSoundDose != nullptr) {
+        *soundDoseBinder = mSoundDoseWrapper->mSoundDose->asBinder();
+        return OK;
+    }
+
+    if (mSoundDoseWrapper->mSoundDoseFactory == nullptr) {
+        std::string interface =
+            std::string(ISoundDoseFactory::descriptor) + kSoundDoseInterfaceModule.data();
+        AIBinder* binder = AServiceManager_checkService(interface.c_str());
+        if (binder == nullptr) {
+            ALOGW("%s service %s doesn't exist", __func__, interface.c_str());
+            return NO_INIT;
+        }
+        mSoundDoseWrapper->mSoundDoseFactory =
+                ISoundDoseFactory::fromBinder(ndk::SpAIBinder(binder));
+    }
+
+    auto result = mSoundDoseWrapper->mSoundDoseFactory->getSoundDose(
+                        module, &mSoundDoseWrapper->mSoundDose);
+    if (!result.isOk()) {
+        ALOGW("%s could not get sound dose interface: %s", __func__, result.getMessage());
+        return BAD_VALUE;
+    }
+
+    if (mSoundDoseWrapper->mSoundDose == nullptr) {
+        ALOGW("%s standalone sound dose interface is not implemented", __func__);
+        *soundDoseBinder = nullptr;
+        return OK;
+    }
+
+    *soundDoseBinder = mSoundDoseWrapper->mSoundDose->asBinder();
+    ALOGI("%s using standalone sound dose interface", __func__);
+    return OK;
+}
+#else
+status_t DeviceHalHidl::getSoundDoseInterface(const std::string& module,
+                                              ::ndk::SpAIBinder* soundDoseBinder) {
+    (void)module;  // avoid unused param
+    (void)soundDoseBinder;  // avoid unused param
+    return INVALID_OPERATION;
+}
+#endif
+
 } // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h
index 052eb65..30fbd6d 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.h
+++ b/media/libaudiohal/impl/DeviceHalHidl.h
@@ -130,12 +130,17 @@
 
     status_t dump(int fd, const Vector<String16>& args) override;
 
+    status_t getSoundDoseInterface(const std::string& module,
+                                   ::ndk::SpAIBinder* soundDoseBinder) override;
+
   private:
     friend class DevicesFactoryHalHidl;
     sp<::android::hardware::audio::CPP_VERSION::IDevice> mDevice;
     // Null if it's not a primary device.
     sp<::android::hardware::audio::CPP_VERSION::IPrimaryDevice> mPrimaryDevice;
     bool supportsSetConnectedState7_1 = true;
+    class SoundDoseWrapper;
+    const std::unique_ptr<SoundDoseWrapper> mSoundDoseWrapper;
 
     // Can not be constructed directly by clients.
     explicit DeviceHalHidl(const sp<::android::hardware::audio::CPP_VERSION::IDevice>& device);
diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index 094b415..d5a1a60 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -26,6 +26,10 @@
 #include <utils/RefBase.h>
 #include <utils/String8.h>
 
+namespace ndk {
+class SpAIBinder;
+}
+
 namespace android {
 
 class StreamInHalInterface;
@@ -140,6 +144,10 @@
 
     virtual status_t dump(int fd, const Vector<String16>& args) = 0;
 
+    // Returns the sound dose binder interface if it is supported by the HAL, nullptr otherwise
+    virtual status_t getSoundDoseInterface(const std::string& module,
+                                           ::ndk::SpAIBinder* soundDoseBinder) = 0;
+
   protected:
     // Subclasses can not be constructed directly by clients.
     DeviceHalInterface() {}
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index 4b6d5f2..43ef311 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -24,7 +24,7 @@
 
     defaults: [
         "latest_android_media_audio_common_types_cpp_shared",
-        "latest_android_hardware_audio_sounddose_ndk_shared",
+        "latest_android_hardware_audio_core_sounddose_ndk_shared",
     ],
 
     srcs: [
@@ -111,7 +111,7 @@
 
     export_shared_lib_headers: [
         "libpermission",
-        "android.hardware.audio.sounddose-V1-ndk",
+        "android.hardware.audio.core.sounddose-V1-ndk",
     ],
 
     cflags: [
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index f8d7c70..7bb0fd3 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2573,7 +2573,7 @@
         ALOGE("loadHwModule() error %d loading module %s", rc, name);
         return AUDIO_MODULE_HANDLE_NONE;
     }
-    if (!mMelReporter->activateHalSoundDoseComputation(name)) {
+    if (!mMelReporter->activateHalSoundDoseComputation(name, dev)) {
         ALOGW("loadHwModule() sound dose reporting is not available");
     }
 
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 100d8c7..e8133d9 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -33,7 +33,6 @@
 #include <sys/types.h>
 #include <limits.h>
 
-#include <aidl/android/hardware/audio/sounddose/ISoundDoseFactory.h>
 #include <android/media/BnAudioTrack.h>
 #include <android/media/IAudioFlingerClient.h>
 #include <android/media/IAudioTrackCallback.h>
diff --git a/services/audioflinger/MelReporter.cpp b/services/audioflinger/MelReporter.cpp
index 5ac7cde..bc5b5db 100644
--- a/services/audioflinger/MelReporter.cpp
+++ b/services/audioflinger/MelReporter.cpp
@@ -22,38 +22,37 @@
 
 #include <android/media/ISoundDoseCallback.h>
 #include <audio_utils/power.h>
-#include <android/binder_manager.h>
 #include <utils/Log.h>
 
 using aidl::android::hardware::audio::core::sounddose::ISoundDose;
-using aidl::android::hardware::audio::sounddose::ISoundDoseFactory;
 
 namespace android {
 
-constexpr std::string_view kSoundDoseInterfaceModule = "/default";
-
-bool AudioFlinger::MelReporter::activateHalSoundDoseComputation(const std::string& module) {
+bool AudioFlinger::MelReporter::activateHalSoundDoseComputation(const std::string& module,
+        const sp<DeviceHalInterface>& device) {
     if (mSoundDoseManager->forceUseFrameworkMel()) {
         ALOGD("%s: Forcing use of internal MEL computation.", __func__);
         activateInternalSoundDoseComputation();
         return false;
     }
 
-    if (mSoundDoseFactory == nullptr) {
-        ALOGW("%s: sound dose HAL reporting not available", __func__);
-        activateInternalSoundDoseComputation();
-        return false;
-    }
-
-    std::shared_ptr<ISoundDose> soundDoseInterface;
-    auto result = mSoundDoseFactory->getSoundDose(module, &soundDoseInterface);
-    if (!result.isOk()) {
-        ALOGW("%s: HAL cannot provide sound dose interface for module %s",
+    ndk::SpAIBinder soundDoseBinder;
+    if (device->getSoundDoseInterface(module, &soundDoseBinder) != OK) {
+        ALOGW("%s: HAL cannot provide sound dose interface for module %s, use internal MEL",
               __func__, module.c_str());
         activateInternalSoundDoseComputation();
         return false;
     }
 
+    if (soundDoseBinder == nullptr) {
+         ALOGW("%s: HAL doesn't implement a sound dose interface for module %s, use internal MEL",
+              __func__, module.c_str());
+        activateInternalSoundDoseComputation();
+        return false;
+    }
+
+    std::shared_ptr<ISoundDose> soundDoseInterface = ISoundDose::fromBinder(soundDoseBinder);
+
     if (!mSoundDoseManager->setHalSoundDoseInterface(soundDoseInterface)) {
         ALOGW("%s: cannot activate HAL MEL reporting for module %s", __func__, module.c_str());
         activateInternalSoundDoseComputation();
@@ -79,16 +78,6 @@
 
 void AudioFlinger::MelReporter::onFirstRef() {
     mAudioFlinger.mPatchCommandThread->addListener(this);
-
-    std::string interface =
-        std::string(ISoundDoseFactory::descriptor) + kSoundDoseInterfaceModule.data();
-    AIBinder* binder = AServiceManager_checkService(interface.c_str());
-    if (binder == nullptr) {
-        ALOGW("%s service %s doesn't exist", __func__, interface.c_str());
-        return;
-    }
-
-    mSoundDoseFactory = ISoundDoseFactory::fromBinder(ndk::SpAIBinder(binder));
 }
 
 bool AudioFlinger::MelReporter::shouldComputeMelForDeviceType(audio_devices_t device) {
diff --git a/services/audioflinger/MelReporter.h b/services/audioflinger/MelReporter.h
index acbc8ed..5e7f0cc 100644
--- a/services/audioflinger/MelReporter.h
+++ b/services/audioflinger/MelReporter.h
@@ -45,13 +45,16 @@
      * does not support the sound dose interface for this module, the internal MEL
      * calculation will be use.
      *
-     * For now support internal MelReporting only if the sound dose standalone HAL
-     * is not implemented
+     * <p>If the device is using the audio AIDL HAL then this method will try to get the sound
+     * dose interface from IModule#getSoundDose(). Otherwise, if the legacy audio HIDL HAL is used
+     * this method will be looking for the standalone sound dose implementation. It falls back to
+     * the internal MEL computation if no valid sound dose interface can be retrieved.
      *
-     * @return true if the MEL reporting will be done from the sound dose HAL
-     * interface
+     * @return true if the MEL reporting will be done from any sound dose HAL interface
+     * implementation, false otherwise.
      */
-    bool activateHalSoundDoseComputation(const std::string& module);
+    bool activateHalSoundDoseComputation(const std::string& module,
+                                         const sp<DeviceHalInterface>& device);
 
     /**
      * Activates the MEL reporting from internal framework values. These are used
@@ -78,8 +81,6 @@
                                         audio_port_handle_t deviceId);
 
     AudioFlinger& mAudioFlinger;  // does not own the object
-    std::shared_ptr<::aidl::android::hardware::audio::sounddose::ISoundDoseFactory>
-        mSoundDoseFactory;
 
     sp<SoundDoseManager> mSoundDoseManager;