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/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index df3dec7..ac92eaa 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -452,6 +452,7 @@
"aidl/android/media/IAudioTrack.aidl",
"aidl/android/media/IAudioTrackCallback.aidl",
+ "aidl/android/media/ISoundDose.aidl",
"aidl/android/media/ISoundDoseCallback.aidl",
"aidl/android/media/SoundDoseRecord.aidl",
],
@@ -551,6 +552,7 @@
unstable: true,
local_include_dir: "aidl",
srcs: [
+ "aidl/android/media/ISoundDose.aidl",
"aidl/android/media/ISoundDoseCallback.aidl",
"aidl/android/media/SoundDoseRecord.aidl",
],
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index fa9239f..77c14a0 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -2374,13 +2374,18 @@
return OK;
}
-status_t AudioSystem::registerSoundDoseCallback(const sp<media::ISoundDoseCallback>& callback) {
+status_t AudioSystem::getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
+ sp<media::ISoundDose>* soundDose) {
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == nullptr) {
return PERMISSION_DENIED;
}
+ if (soundDose == nullptr) {
+ return BAD_VALUE;
+ }
- return af->registerSoundDoseCallback(callback);
+ RETURN_STATUS_IF_ERROR(af->getSoundDoseInterface(callback, soundDose));
+ return OK;
}
status_t AudioSystem::getDirectPlaybackSupport(const audio_attributes_t *attr,
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 97b61a5..e6d84ad 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -837,9 +837,10 @@
return NO_ERROR;
}
-status_t AudioFlingerClientAdapter::registerSoundDoseCallback(
- const sp<media::ISoundDoseCallback> &callback) {
- return statusTFromBinderStatus(mDelegate->registerSoundDoseCallback(callback));
+status_t AudioFlingerClientAdapter::getSoundDoseInterface(
+ const sp<media::ISoundDoseCallback> &callback,
+ sp<media::ISoundDose>* soundDose) {
+ return statusTFromBinderStatus(mDelegate->getSoundDoseInterface(callback, soundDose));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -1360,10 +1361,11 @@
return Status::ok();
}
-Status AudioFlingerServerAdapter::registerSoundDoseCallback(
- const sp<media::ISoundDoseCallback>& callback)
+Status AudioFlingerServerAdapter::getSoundDoseInterface(
+ const sp<media::ISoundDoseCallback>& callback,
+ sp<media::ISoundDose>* soundDose)
{
- return Status::fromStatusT(mDelegate->registerSoundDoseCallback(callback));
+ return Status::fromStatusT(mDelegate->getSoundDoseInterface(callback, soundDose));
}
} // namespace android
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index 133e363..4383b9e 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -35,6 +35,7 @@
import android.media.IAudioFlingerClient;
import android.media.IAudioRecord;
import android.media.IAudioTrack;
+import android.media.ISoundDose;
import android.media.ISoundDoseCallback;
import android.media.LatencyMode;
import android.media.MicrophoneInfoData;
@@ -247,8 +248,11 @@
*/
LatencyMode[] getSupportedLatencyModes(int output);
- /** Registers the sound dose callback. */
- oneway void registerSoundDoseCallback(ISoundDoseCallback callback);
+ /**
+ * Registers the sound dose callback and returns the interface for executing
+ * sound dose methods on the audio server.
+ */
+ ISoundDose getSoundDoseInterface(in ISoundDoseCallback callback);
// When adding a new method, please review and update
// IAudioFlinger.h AudioFlingerServerAdapter::Delegate::TransactionCode
diff --git a/media/libaudioclient/aidl/android/media/ISoundDose.aidl b/media/libaudioclient/aidl/android/media/ISoundDose.aidl
new file mode 100644
index 0000000..f31f091
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/ISoundDose.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.media.SoundDoseRecord;
+
+/**
+ * Interface used to push the sound dose related information from the
+ * AudioService#SoundDoseHelper to the audio server
+ */
+oneway interface ISoundDose {
+ /** Set a new RS2 value used for momentary exposure warnings. */
+ void setOutputRs2(float rs2Value);
+
+ /**
+ * Resets the native CSD values. This can happen after a crash in the
+ * audio server or after booting when restoring the previous state.
+ * 'currentCsd' represents the restored CSD value and 'records' contains the
+ * dosage values and MELs together with their timestamps that lead to this
+ * CSD.
+ */
+ void resetCsd(float currentCsd, in SoundDoseRecord[] records);
+}
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index a5feb3d..6aec78b 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -28,6 +28,7 @@
#include <android/media/BnAudioPolicyServiceClient.h>
#include <android/media/EffectDescriptor.h>
#include <android/media/INativeSpatializerCallback.h>
+#include <android/media/ISoundDose.h>
#include <android/media/ISoundDoseCallback.h>
#include <android/media/ISpatializer.h>
#include <android/media/RecordClientInfo.h>
@@ -586,8 +587,15 @@
const AudioDeviceTypeAddrVector &devices,
bool *canBeSpatialized);
- /** Registers the sound dose callback with the audio server. */
- static status_t registerSoundDoseCallback(const sp<media::ISoundDoseCallback>& callback);
+ /**
+ * Registers the sound dose callback with the audio server and returns the ISoundDose
+ * interface.
+ *
+ * \param callback to send messages to the audio server
+ * \param soundDose binder to send messages to the AudioService
+ **/
+ static status_t getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
+ sp<media::ISoundDose>* soundDose);
/**
* Query how the direct playback is currently supported on the device.
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index c883e18..bf61612 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -55,6 +55,7 @@
#include "android/media/IAudioTrackCallback.h"
#include "android/media/IEffect.h"
#include "android/media/IEffectClient.h"
+#include "android/media/ISoundDose.h"
#include "android/media/ISoundDoseCallback.h"
#include "android/media/OpenInputRequest.h"
#include "android/media/OpenInputResponse.h"
@@ -368,7 +369,8 @@
virtual status_t getSupportedLatencyModes(audio_io_handle_t output,
std::vector<audio_latency_mode_t>* modes) = 0;
- virtual status_t registerSoundDoseCallback(const sp<media::ISoundDoseCallback>& callback) = 0;
+ virtual status_t getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
+ sp<media::ISoundDose>* soundDose) = 0;
};
/**
@@ -475,7 +477,8 @@
audio_latency_mode_t mode) override;
status_t getSupportedLatencyModes(
audio_io_handle_t output, std::vector<audio_latency_mode_t>* modes) override;
- status_t registerSoundDoseCallback(const sp<media::ISoundDoseCallback>& callback) override;
+ status_t getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
+ sp<media::ISoundDose>* soundDose) override;
private:
const sp<media::IAudioFlingerService> mDelegate;
@@ -567,7 +570,7 @@
SET_DEVICE_CONNECTED_STATE = media::BnAudioFlingerService::TRANSACTION_setDeviceConnectedState,
SET_REQUESTED_LATENCY_MODE = media::BnAudioFlingerService::TRANSACTION_setRequestedLatencyMode,
GET_SUPPORTED_LATENCY_MODES = media::BnAudioFlingerService::TRANSACTION_getSupportedLatencyModes,
- REGISTER_SOUND_DOSE_CALLBACK = media::BnAudioFlingerService::TRANSACTION_registerSoundDoseCallback,
+ GET_SOUND_DOSE_INTERFACE = media::BnAudioFlingerService::TRANSACTION_getSoundDoseInterface,
};
protected:
@@ -692,7 +695,8 @@
Status setRequestedLatencyMode(int output, media::LatencyMode mode) override;
Status getSupportedLatencyModes(int output,
std::vector<media::LatencyMode>* _aidl_return) override;
- Status registerSoundDoseCallback(const sp<media::ISoundDoseCallback>& callback) override;
+ Status getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
+ sp<media::ISoundDose>* _aidl_return) override;
private:
const sp<AudioFlingerServerAdapter::Delegate> mDelegate;
};
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