CSD: enable sound dose with internal MEL

Test: logs and dumpsys
Bug: 268035692
Change-Id: I0dd8ca5f8c925d984a782293bba1a7be121fca7c
diff --git a/media/libaudioclient/aidl/android/media/ISoundDose.aidl b/media/libaudioclient/aidl/android/media/ISoundDose.aidl
index 6404753..a4c37bc 100644
--- a/media/libaudioclient/aidl/android/media/ISoundDose.aidl
+++ b/media/libaudioclient/aidl/android/media/ISoundDose.aidl
@@ -48,6 +48,15 @@
      */
     oneway void updateAttenuation(float attenuationDB, int device);
 
+    /**
+     * Disable the calculation of sound dose. This has the effect that no MEL
+     * values will be computed on the framework side. The MEL returned from
+     * the IHalSoundDoseCallbacks will be ignored.
+     * Should only be called once at startup if the AudioService does not
+     * support CSD.
+     */
+    oneway void disableCsd();
+
     /* -------------------------- Test API methods --------------------------
     /** Get the currently used RS2 upper bound. */
     float getOutputRs2UpperBound();
diff --git a/services/audioflinger/MelReporter.cpp b/services/audioflinger/MelReporter.cpp
index 52af56f..c5c9652 100644
--- a/services/audioflinger/MelReporter.cpp
+++ b/services/audioflinger/MelReporter.cpp
@@ -81,6 +81,10 @@
 }
 
 bool AudioFlinger::MelReporter::shouldComputeMelForDeviceType(audio_devices_t device) {
+    if (mSoundDoseManager->isCsdDisabled()) {
+        ALOGV("%s csd is disabled", __func__);
+        return false;
+    }
     if (mSoundDoseManager->forceComputeCsdOnAllDevices()) {
         return true;
     }
@@ -102,6 +106,11 @@
 
 void AudioFlinger::MelReporter::updateMetadataForCsd(audio_io_handle_t streamHandle,
         const std::vector<playback_track_metadata_v7_t>& metadataVec) {
+    if (mSoundDoseManager->isCsdDisabled()) {
+        ALOGV("%s csd is disabled", __func__);
+        return;
+    }
+
     std::lock_guard _laf(mAudioFlinger.mLock);
     std::lock_guard _l(mLock);
     auto activeMelPatchId = activePatchStreamHandle_l(streamHandle);
@@ -133,6 +142,10 @@
 
 void AudioFlinger::MelReporter::onCreateAudioPatch(audio_patch_handle_t handle,
         const PatchPanel::Patch& patch) {
+    if (mSoundDoseManager->isCsdDisabled()) {
+        ALOGV("%s csd is disabled", __func__);
+        return;
+    }
     if (useHalSoundDoseInterface()) {
         ALOGV("%s using HAL sound dose, ignore new patch", __func__);
         return;
@@ -193,6 +206,11 @@
 }
 
 void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
+    if (mSoundDoseManager->isCsdDisabled()) {
+        ALOGV("%s csd is disabled", __func__);
+        return;
+    }
+
     ActiveMelPatch melPatch;
     {
         std::lock_guard _l(mLock);
diff --git a/services/audioflinger/sounddose/SoundDoseManager.cpp b/services/audioflinger/sounddose/SoundDoseManager.cpp
index 18d93a5..dd2d80a 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.cpp
+++ b/services/audioflinger/sounddose/SoundDoseManager.cpp
@@ -50,7 +50,7 @@
         size_t channelCount, audio_format_t format) {
     std::lock_guard _l(mLock);
 
-    if (mHalSoundDose != nullptr) {
+    if (mHalSoundDose != nullptr && !mDisableCsd) {
         ALOGW("%s: using HAL MEL computation, no MelProcessor needed.", __func__);
         return nullptr;
     }
@@ -287,6 +287,15 @@
     return binder::Status::ok();
 }
 
+binder::Status SoundDoseManager::SoundDose::disableCsd() {
+    ALOGV("%s", __func__);
+    auto soundDoseManager = mSoundDoseManager.promote();
+    if (soundDoseManager != nullptr) {
+        soundDoseManager->disableCsd();
+    }
+    return binder::Status::ok();
+}
+
 binder::Status SoundDoseManager::SoundDose::getOutputRs2UpperBound(float* value) {
     ALOGV("%s", __func__);
     auto soundDoseManager = mSoundDoseManager.promote();
@@ -343,6 +352,28 @@
     }
 }
 
+void SoundDoseManager::disableCsd() {
+    ALOGV("%s",  __func__);
+
+    std::lock_guard _l(mLock);
+    mDisableCsd = true;
+
+    // Normally, there should be no active MelProcessors when this method is called
+    // We pause however every cached MelProcessor as a defensive mechanism to not
+    // have unnecessary processing
+    for (auto& activeEntry : mActiveProcessors) {
+        auto melProcessor = activeEntry.second.promote();
+        if (melProcessor != nullptr) {
+            melProcessor->pause();
+        }
+    }
+}
+
+bool SoundDoseManager::isCsdDisabled() {
+    std::lock_guard _l(mLock);
+    return mDisableCsd;
+}
+
 void SoundDoseManager::setUseFrameworkMel(bool useFrameworkMel) {
     // invalidate any HAL sound dose interface used
     setHalSoundDoseInterface(nullptr);
@@ -392,11 +423,16 @@
                                       audio_port_handle_t deviceId) const {
     ALOGV("%s", __func__);
 
+
     sp<media::ISoundDoseCallback> soundDoseCallback;
     std::vector<audio_utils::CsdRecord> records;
     float currentCsd;
     {
         std::lock_guard _l(mLock);
+        if (mDisableCsd) {
+            return;
+        }
+
 
         int64_t timestampSec = getMonotonicSecond();
 
@@ -432,6 +468,13 @@
 void SoundDoseManager::onMomentaryExposure(float currentMel, audio_port_handle_t deviceId) const {
     ALOGV("%s: Momentary exposure for device %d triggered: %f MEL", __func__, deviceId, currentMel);
 
+    {
+        std::lock_guard _l(mLock);
+        if (mDisableCsd) {
+            return;
+        }
+    }
+
     auto soundDoseCallback = getSoundDoseCallback();
     if (soundDoseCallback != nullptr) {
         soundDoseCallback->onMomentaryExposure(currentMel, deviceId);
@@ -451,6 +494,14 @@
 
 std::string SoundDoseManager::dump() const {
     std::string output;
+    {
+        std::lock_guard _l(mLock);
+        if (mDisableCsd) {
+            base::StringAppendF(&output, "CSD is disabled");
+            return output;
+        }
+    }
+
     mMelAggregator->foreachCsd([&output](audio_utils::CsdRecord csdRecord) {
         base::StringAppendF(&output,
                             "CSD %f with average MEL %f in interval [%" PRId64 ", %" PRId64 "]",
diff --git a/services/audioflinger/sounddose/SoundDoseManager.h b/services/audioflinger/sounddose/SoundDoseManager.h
index 9e07d38..d7a686a 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.h
+++ b/services/audioflinger/sounddose/SoundDoseManager.h
@@ -101,6 +101,9 @@
     /** Clear all map entries with passed audio_port_handle_t. */
     void clearMapDeviceIdEntries(audio_port_handle_t deviceId);
 
+    /** Returns true if CSD is disabled. */
+    bool isCsdDisabled();
+
     std::string dump() const;
 
     // used for testing only
@@ -134,6 +137,8 @@
                                 const std::vector<media::SoundDoseRecord>& records) override;
         binder::Status updateAttenuation(float attenuationDB, int device) override;
         binder::Status getOutputRs2UpperBound(float* value) override;
+        binder::Status disableCsd() override;
+
         binder::Status getCsd(float* value) override;
         binder::Status forceUseFrameworkMel(bool useFrameworkMel) override;
         binder::Status forceComputeCsdOnAllDevices(bool computeCsdOnAllDevices) override;
@@ -164,6 +169,7 @@
     sp<media::ISoundDoseCallback> getSoundDoseCallback() const;
 
     void updateAttenuation(float attenuationDB, audio_devices_t deviceType);
+    void disableCsd();
     void setUseFrameworkMel(bool useFrameworkMel);
     void setComputeCsdOnAllDevices(bool computeCsdOnAllDevices);
     /** Returns the HAL sound dose interface or null if internal MEL computation is used. */
@@ -191,8 +197,10 @@
     std::shared_ptr<ISoundDose> mHalSoundDose GUARDED_BY(mLock);
     std::shared_ptr<HalSoundDoseCallback> mHalSoundDoseCallback GUARDED_BY(mLock);
 
-    bool mUseFrameworkMel GUARDED_BY(mLock) = false;
+    bool mUseFrameworkMel GUARDED_BY(mLock) = true;
     bool mComputeCsdOnAllDevices GUARDED_BY(mLock) = false;
+
+    bool mDisableCsd GUARDED_BY(mLock) = false;
 };
 
 }  // namespace android
diff --git a/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
index e07a3a4..9fab77d 100644
--- a/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
+++ b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
@@ -239,7 +239,8 @@
 }
 
 TEST_F(SoundDoseManagerTest, GetDefaultForceUseFrameworkMel) {
-    EXPECT_FALSE(mSoundDoseManager->forceUseFrameworkMel());
+    // TODO: for now dogfooding with internal MEL. Revert to false when using the HAL MELs
+    EXPECT_TRUE(mSoundDoseManager->forceUseFrameworkMel());
 }
 
 }  // namespace