CSD: return interface for messages to audio server

Whenever the AudioService registers for receiving sound dose callbacks from the
native side, the native sends back the ISoundDose interface.

Test: logs, dumpsys and UT
Bug: 257238734
Change-Id: I5605196e8be91f00a7fbcf65573dfabe6e5c03d3
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 0719838..6505698 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -229,7 +229,7 @@
 BINDER_METHOD_ENTRY(setDeviceConnectedState) \
 BINDER_METHOD_ENTRY(setRequestedLatencyMode) \
 BINDER_METHOD_ENTRY(getSupportedLatencyModes) \
-BINDER_METHOD_ENTRY(registerSoundDoseCallback) \
+BINDER_METHOD_ENTRY(getSoundDoseInterface) \
 
 // singleton for Binder Method Statistics for IAudioFlinger
 static auto& getIAudioFlingerStatistics() {
@@ -1657,8 +1657,13 @@
     return thread->getSupportedLatencyModes(modes);
 }
 
-status_t AudioFlinger::registerSoundDoseCallback(const sp<media::ISoundDoseCallback>& callback) {
-    mMelReporter->registerSoundDoseCallback(callback);
+status_t AudioFlinger::getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
+                                             sp<media::ISoundDose>* soundDose) {
+    if (soundDose == nullptr) {
+        return BAD_VALUE;
+    }
+
+    *soundDose = mMelReporter->getSoundDoseInterface(callback);
     return NO_ERROR;
 }
 
@@ -4618,7 +4623,7 @@
         case TransactionCode::SET_MASTER_VOLUME:
         case TransactionCode::SET_MASTER_MUTE:
         case TransactionCode::MASTER_MUTE:
-        case TransactionCode::REGISTER_SOUND_DOSE_CALLBACK:
+        case TransactionCode::GET_SOUND_DOSE_INTERFACE:
         case TransactionCode::SET_MODE:
         case TransactionCode::SET_MIC_MUTE:
         case TransactionCode::SET_LOW_RAM_DEVICE:
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index a2cde70..d6faae0 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -306,7 +306,8 @@
     virtual status_t getSupportedLatencyModes(audio_io_handle_t output,
             std::vector<audio_latency_mode_t>* modes);
 
-    virtual status_t registerSoundDoseCallback(const sp<media::ISoundDoseCallback>& callback);
+    virtual status_t getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
+                                           sp<media::ISoundDose>* soundDose);
 
     status_t onTransactWrapper(TransactionCode code, const Parcel& data, uint32_t flags,
         const std::function<status_t()>& delegate) override;
diff --git a/services/audioflinger/MelReporter.cpp b/services/audioflinger/MelReporter.cpp
index 279f30d..8cc7eab 100644
--- a/services/audioflinger/MelReporter.cpp
+++ b/services/audioflinger/MelReporter.cpp
@@ -108,10 +108,10 @@
     }
 }
 
-void AudioFlinger::MelReporter::registerSoundDoseCallback(
+sp<media::ISoundDose> AudioFlinger::MelReporter::getSoundDoseInterface(
         const sp<media::ISoundDoseCallback>& callback) {
-    // no need to lock since registerSoundDoseCallback is synchronized
-    mSoundDoseManager.registerSoundDoseCallback(callback);
+    // no need to lock since getSoundDoseInterface is synchronized
+    return mSoundDoseManager.getSoundDoseInterface(callback);
 }
 
 std::string AudioFlinger::MelReporter::dump() {
diff --git a/services/audioflinger/MelReporter.h b/services/audioflinger/MelReporter.h
index 3625a86..f73b3d6 100644
--- a/services/audioflinger/MelReporter.h
+++ b/services/audioflinger/MelReporter.h
@@ -44,7 +44,7 @@
     // For now only support internal MelReporting
     [[nodiscard]] bool isHalReportingEnabled() const { return false; }
 
-    void registerSoundDoseCallback(const sp<media::ISoundDoseCallback>& callback);
+    sp<media::ISoundDose> getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback);
 
     std::string dump();
 
diff --git a/services/audioflinger/sounddose/Android.bp b/services/audioflinger/sounddose/Android.bp
index 6149472..0e409d3 100644
--- a/services/audioflinger/sounddose/Android.bp
+++ b/services/audioflinger/sounddose/Android.bp
@@ -20,6 +20,7 @@
         "audioflinger-aidl-cpp",
         "libaudioutils",
         "libbase",
+        "libbinder",
         "liblog",
         "libutils",
     ],
diff --git a/services/audioflinger/sounddose/SoundDoseManager.cpp b/services/audioflinger/sounddose/SoundDoseManager.cpp
index 474d0ce..46f310c 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.cpp
+++ b/services/audioflinger/sounddose/SoundDoseManager.cpp
@@ -52,6 +52,7 @@
             (processor = streamProcessor->second.promote())) {
         ALOGV("%s: found callback for stream %d", __func__, streamHandle);
         processor->setDeviceId(deviceId);
+        processor->setOutputRs2(mRs2Value);
         return processor;
     } else {
         ALOGV("%s: creating new callback for device %d", __func__, streamHandle);
@@ -66,12 +67,14 @@
     ALOGV("%s", __func__);
     std::lock_guard _l(mLock);
 
+    mRs2Value = rs2Value;
+
     for (auto& streamProcessor : mActiveProcessors) {
         sp<audio_utils::MelProcessor> processor = streamProcessor.second.promote();
         if (processor != nullptr) {
-            status_t result = processor->setOutputRs2(rs2Value);
+            status_t result = processor->setOutputRs2(mRs2Value);
             if (result != NO_ERROR) {
-                ALOGW("%s: could not set RS2 value %f for stream %d", __func__, rs2Value,
+                ALOGW("%s: could not set RS2 value %f for stream %d", __func__, mRs2Value,
                       streamProcessor.first);
             }
         }
@@ -86,6 +89,51 @@
     }
 }
 
+void SoundDoseManager::SoundDose::binderDied(__unused const wp<IBinder>& who) {
+    ALOGV("%s", __func__);
+
+    auto soundDoseManager = mSoundDoseManager.promote();
+    if (soundDoseManager != nullptr) {
+        soundDoseManager->resetSoundDose();
+    }
+}
+
+binder::Status SoundDoseManager::SoundDose::setOutputRs2(float value) {
+    ALOGV("%s", __func__);
+    auto soundDoseManager = mSoundDoseManager.promote();
+    if (soundDoseManager != nullptr) {
+        soundDoseManager->setOutputRs2(value);
+    }
+    return binder::Status::ok();
+}
+
+binder::Status SoundDoseManager::SoundDose::resetCsd(
+        float currentCsd, const std::vector<media::SoundDoseRecord>& records) {
+    ALOGV("%s", __func__);
+    auto soundDoseManager = mSoundDoseManager.promote();
+    if (soundDoseManager != nullptr) {
+        soundDoseManager->resetCsd(currentCsd, records);
+    }
+    return binder::Status::ok();
+}
+
+void SoundDoseManager::resetSoundDose() {
+    std::lock_guard lock(mLock);
+    mSoundDose = nullptr;
+}
+
+void SoundDoseManager::resetCsd(float currentCsd,
+                                const std::vector<media::SoundDoseRecord>& records) {
+    std::lock_guard lock(mLock);
+    std::vector<audio_utils::CsdRecord> resetRecords;
+    for (const auto& record : records) {
+        resetRecords.emplace_back(record.timestamp, record.duration, record.value,
+                                  record.averageMel);
+    }
+
+    mMelAggregator->reset(currentCsd, resetRecords);
+}
+
 void SoundDoseManager::onNewMelValues(const std::vector<float>& mels, size_t offset, size_t length,
                                       audio_port_handle_t deviceId) const {
     ALOGV("%s", __func__);
@@ -120,28 +168,31 @@
 
 sp<media::ISoundDoseCallback> SoundDoseManager::getSoundDoseCallback() const {
     std::lock_guard _l(mLock);
-    return mSoundDoseCallback;
+    if (mSoundDose == nullptr) {
+        return nullptr;
+    }
+
+    return mSoundDose->mSoundDoseCallback;
 }
 
 void SoundDoseManager::onMomentaryExposure(float currentMel, audio_port_handle_t deviceId) const {
     ALOGV("%s: Momentary exposure for device %d triggered: %f MEL", __func__, deviceId, currentMel);
 
-    sp<media::ISoundDoseCallback> soundDoseCallback;
-    {
-        std::lock_guard _l(mLock);
-        soundDoseCallback = mSoundDoseCallback;
-    }
-
+    auto soundDoseCallback = getSoundDoseCallback();
     if (soundDoseCallback != nullptr) {
-        mSoundDoseCallback->onMomentaryExposure(currentMel, deviceId);
+        soundDoseCallback->onMomentaryExposure(currentMel, deviceId);
     }
 }
 
-void SoundDoseManager::registerSoundDoseCallback(const sp<media::ISoundDoseCallback>& callback) {
+sp<media::ISoundDose> SoundDoseManager::getSoundDoseInterface(
+        const sp<media::ISoundDoseCallback>& callback) {
     ALOGV("%s: Register ISoundDoseCallback", __func__);
 
     std::lock_guard _l(mLock);
-    mSoundDoseCallback = callback;
+    if (mSoundDose == nullptr) {
+        mSoundDose = sp<SoundDose>::make(this, callback);
+    }
+    return mSoundDose;
 }
 
 std::string SoundDoseManager::dump() const {
diff --git a/services/audioflinger/sounddose/SoundDoseManager.h b/services/audioflinger/sounddose/SoundDoseManager.h
index 9a95e8a..b0aa5d6 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.h
+++ b/services/audioflinger/sounddose/SoundDoseManager.h
@@ -17,10 +17,11 @@
 
 #pragma once
 
+#include <android/media/BnSoundDose.h>
 #include <android/media/ISoundDoseCallback.h>
 #include <audio_utils/MelAggregator.h>
 #include <audio_utils/MelProcessor.h>
-#include <utils/Errors.h>
+#include <binder/Status.h>
 #include <mutex>
 #include <unordered_map>
 
@@ -69,10 +70,15 @@
      */
     void setOutputRs2(float rs2Value);
 
-    std::string dump() const;
+    /**
+     * \brief Registers the interface for passing callbacks to the AudioService and gets
+     * the ISoundDose interface.
+     *
+     * \returns the sound dose binder to send commands to the SoundDoseManager
+     **/
+    sp<media::ISoundDose> getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback);
 
-    /** \brief Registers the interface for passing callbacks to the AudioService. */
-    void registerSoundDoseCallback(const sp<media::ISoundDoseCallback>& callback);
+    std::string dump() const;
 
     // used for testing
     size_t getCachedMelRecordsSize() const;
@@ -86,9 +92,32 @@
 
     void onMomentaryExposure(float currentMel, audio_port_handle_t deviceId) const override;
 
-  private:
-    sp<media::ISoundDoseCallback> getSoundDoseCallback() const;
+private:
+    class SoundDose : public media::BnSoundDose,
+                      public IBinder::DeathRecipient {
+    public:
+        SoundDose(SoundDoseManager* manager, const sp<media::ISoundDoseCallback>& callback)
+            : mSoundDoseManager(manager),
+              mSoundDoseCallback(callback) {};
 
+        /** IBinder::DeathRecipient. Listen to the death of ISoundDoseCallback. */
+        virtual void binderDied(const wp<IBinder>& who);
+
+        /** BnSoundDose override */
+        binder::Status setOutputRs2(float value) override;
+        binder::Status resetCsd(float currentCsd,
+                                const std::vector<media::SoundDoseRecord>& records) override;
+
+        wp<SoundDoseManager> mSoundDoseManager;
+        const sp<media::ISoundDoseCallback> mSoundDoseCallback;
+    };
+
+    void resetSoundDose();
+
+    void resetCsd(float currentCsd, const std::vector<media::SoundDoseRecord>& records);
+
+    sp<media::ISoundDoseCallback> getSoundDoseCallback() const;
+    
     mutable std::mutex mLock;
 
     // no need for lock since MelAggregator is thread-safe
@@ -99,7 +128,7 @@
 
     float mRs2Value GUARDED_BY(mLock);
 
-    sp<media::ISoundDoseCallback> mSoundDoseCallback GUARDED_BY(mLock);
+    sp<SoundDose> mSoundDose GUARDED_BY(mLock);
 };
 
 }  // namespace android