CSD: add logic for using HAL sound dose values
When the HAL supports the sound dose computation we prefer to use the
MEL value provided by the HAL. These should be more accurate and can be
used for certification with IEC62368-1 3rd edition and EN50332-3.
Current implementation supports the standalone sound dose HAL.
Test: sounddosemanager_tests UT & bluejay-userdebug with internal MEL
Bug: 252776298
Change-Id: Ibbda76781fc869ac457d03d4f9a871fb353a9ba8
diff --git a/services/audioflinger/MelReporter.cpp b/services/audioflinger/MelReporter.cpp
index b2e8027..7902444 100644
--- a/services/audioflinger/MelReporter.cpp
+++ b/services/audioflinger/MelReporter.cpp
@@ -22,12 +22,73 @@
#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::ISoundDose;
+using aidl::android::hardware::audio::sounddose::ISoundDoseFactory;
+
namespace android {
+constexpr std::string_view kSoundDoseInterfaceModule = "/default";
+
+bool AudioFlinger::MelReporter::activateHalSoundDoseComputation(const std::string& module) {
+ 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",
+ __func__, module.c_str());
+ activateInternalSoundDoseComputation();
+ return false;
+ }
+
+ if (!mSoundDoseManager->setHalSoundDoseInterface(soundDoseInterface)) {
+ ALOGW("%s cannot activate HAL MEL reporting for module %s", __func__, module.c_str());
+ activateInternalSoundDoseComputation();
+ return false;
+ }
+
+ std::lock_guard _l(mLock);
+ mUseHalSoundDoseInterface = true;
+ stopInternalMelComputation();
+ return true;
+}
+
+void AudioFlinger::MelReporter::activateInternalSoundDoseComputation() {
+ mSoundDoseManager->setHalSoundDoseInterface(nullptr);
+
+ std::lock_guard _l(mLock);
+ mUseHalSoundDoseInterface = false;
+
+ for (const auto& activePatches : mActiveMelPatches) {
+ for (const auto& deviceId : activePatches.second.deviceHandles) {
+ startMelComputationForNewPatch(activePatches.second.streamHandle, deviceId);
+ }
+ }
+}
+
+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) {
- if (mSoundDoseManager.computeCsdOnAllDevices()) {
+ if (mSoundDoseManager->computeCsdOnAllDevices()) {
return true;
}
@@ -65,17 +126,17 @@
&& shouldComputeMelForDeviceType(patch.mAudioPatch.sinks[i].ext.device.type)) {
audio_port_handle_t deviceId = patch.mAudioPatch.sinks[i].id;
newPatch.deviceHandles.push_back(deviceId);
+ AudioDeviceTypeAddr adt{patch.mAudioPatch.sinks[i].ext.device.type,
+ patch.mAudioPatch.sinks[i].ext.device.address};
+ mSoundDoseManager->mapAddressToDeviceId(adt, deviceId);
- // Start the MEL calculation in the PlaybackThread
- std::lock_guard _lAf(mAudioFlinger.mLock);
- auto thread = mAudioFlinger.checkPlaybackThread_l(streamHandle);
- if (thread != nullptr) {
- thread->startMelComputation(mSoundDoseManager.getOrCreateProcessorForDevice(
- deviceId,
- newPatch.streamHandle,
- thread->mSampleRate,
- thread->mChannelCount,
- thread->mFormat));
+ bool useHalSoundDoseInterface;
+ {
+ std::lock_guard _l(mLock);
+ useHalSoundDoseInterface = mUseHalSoundDoseInterface;
+ }
+ if (!useHalSoundDoseInterface) {
+ startMelComputationForNewPatch(streamHandle, deviceId);
}
}
}
@@ -84,6 +145,21 @@
mActiveMelPatches[patch.mAudioPatch.id] = newPatch;
}
+void AudioFlinger::MelReporter::startMelComputationForNewPatch(
+ audio_io_handle_t streamHandle, audio_port_handle_t deviceId) {
+ // Start the MEL calculation in the PlaybackThread
+ std::lock_guard _lAf(mAudioFlinger.mLock);
+ auto thread = mAudioFlinger.checkPlaybackThread_l(streamHandle);
+ if (thread != nullptr) {
+ thread->startMelComputation(mSoundDoseManager->getOrCreateProcessorForDevice(
+ deviceId,
+ streamHandle,
+ thread->mSampleRate,
+ thread->mChannelCount,
+ thread->mFormat));
+ }
+}
+
void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
ALOGV("%s", __func__);
@@ -103,25 +179,47 @@
mActiveMelPatches.erase(patchIt);
}
- // Stop MEL calculation for the PlaybackThread
- std::lock_guard _lAf(mAudioFlinger.mLock);
- mSoundDoseManager.removeStreamProcessor(melPatch.streamHandle);
- auto thread = mAudioFlinger.checkPlaybackThread_l(melPatch.streamHandle);
- if (thread != nullptr) {
- thread->stopMelComputation();
+ for (const auto& deviceId : melPatch.deviceHandles) {
+ mSoundDoseManager->clearMapDeviceIdEntries(deviceId);
}
+ stopInternalMelComputationForStream(melPatch.streamHandle);
}
sp<media::ISoundDose> AudioFlinger::MelReporter::getSoundDoseInterface(
const sp<media::ISoundDoseCallback>& callback) {
// no need to lock since getSoundDoseInterface is synchronized
- return mSoundDoseManager.getSoundDoseInterface(callback);
+ return mSoundDoseManager->getSoundDoseInterface(callback);
+}
+
+void AudioFlinger::MelReporter::stopInternalMelComputation() {
+ ALOGV("%s", __func__);
+ std::unordered_map<audio_patch_handle_t, ActiveMelPatch> activePatchesCopy;
+ {
+ std::lock_guard _l(mLock);
+ activePatchesCopy = mActiveMelPatches;
+ mActiveMelPatches.clear();
+ }
+
+ for (const auto& activePatch : activePatchesCopy) {
+ stopInternalMelComputationForStream(activePatch.second.streamHandle);
+ }
+}
+
+void AudioFlinger::MelReporter::stopInternalMelComputationForStream(audio_io_handle_t streamId) {
+ ALOGV("%s: stop internal mel for stream id: %d", __func__, streamId);
+
+ std::lock_guard _lAf(mAudioFlinger.mLock);
+ mSoundDoseManager->removeStreamProcessor(streamId);
+ auto thread = mAudioFlinger.checkPlaybackThread_l(streamId);
+ if (thread != nullptr) {
+ thread->stopMelComputation();
+ }
}
std::string AudioFlinger::MelReporter::dump() {
std::lock_guard _l(mLock);
std::string output("\nSound Dose:\n");
- output.append(mSoundDoseManager.dump());
+ output.append(mSoundDoseManager->dump());
return output;
}