CSD: Enable the CSD only for MUSIC and GAME usage
Any mix that contain a track with MUSIC and GAME usage can have an
active CSD computation. This is a requirement of the IEC62368-1 3rd
edition and EN50332-3.
Also implemented logic to ignore the HAL MELs when there is no active
stream with MUSIC/GAME usage on the device that reports the values.
Test: dumpsys media.audio_flinger and logs
Bug: 265936306
Change-Id: I583de61c6917823522557ae5c1371d9242a273cb
diff --git a/services/audioflinger/MelReporter.cpp b/services/audioflinger/MelReporter.cpp
index bc5b5db..5dbcb33 100644
--- a/services/audioflinger/MelReporter.cpp
+++ b/services/audioflinger/MelReporter.cpp
@@ -100,14 +100,50 @@
}
}
+void AudioFlinger::MelReporter::updateMetadataForCsd(audio_io_handle_t streamHandle,
+ const std::vector<playback_track_metadata_v7_t>& metadataVec) {
+ std::lock_guard _laf(mAudioFlinger.mLock);
+ std::lock_guard _l(mLock);
+ auto activeMelPatchId = activePatchStreamHandle_l(streamHandle);
+ if (!activeMelPatchId) {
+ ALOGV("%s stream handle %d does not have an active patch", __func__, streamHandle);
+ return;
+ }
+
+ bool shouldActivateCsd = false;
+ for (const auto& metadata : metadataVec) {
+ if (metadata.base.usage == AUDIO_USAGE_GAME || metadata.base.usage == AUDIO_USAGE_MEDIA) {
+ shouldActivateCsd = true;
+ }
+ }
+
+ auto activeMelPatchIt = mActiveMelPatches.find(activeMelPatchId.value());
+ if (activeMelPatchIt != mActiveMelPatches.end()
+ && shouldActivateCsd != activeMelPatchIt->second.csdActive) {
+ if (activeMelPatchIt->second.csdActive) {
+ ALOGV("%s should not compute CSD for stream handle %d", __func__, streamHandle);
+ stopMelComputationForPatch_l(activeMelPatchIt->second);
+ } else {
+ ALOGV("%s should compute CSD for stream handle %d", __func__, streamHandle);
+ startMelComputationForActivePatch_l(activeMelPatchIt->second);
+ }
+ activeMelPatchIt->second.csdActive = shouldActivateCsd;
+ }
+}
+
void AudioFlinger::MelReporter::onCreateAudioPatch(audio_patch_handle_t handle,
const PatchPanel::Patch& patch) {
+ if (useHalSoundDoseInterface()) {
+ ALOGV("%s using HAL sound dose, ignore new patch", __func__);
+ return;
+ }
+
ALOGV("%s: handle %d mHalHandle %d device sink %08x",
__func__, handle, patch.mHalHandle,
patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
if (patch.mAudioPatch.num_sources == 0
|| patch.mAudioPatch.sources[0].type != AUDIO_PORT_TYPE_MIX) {
- ALOGW("%s: patch does not contain any mix sources", __func__);
+ ALOGV("%s: patch does not contain any mix sources", __func__);
return;
}
@@ -122,49 +158,46 @@
AudioDeviceTypeAddr adt{patch.mAudioPatch.sinks[i].ext.device.type,
patch.mAudioPatch.sinks[i].ext.device.address};
mSoundDoseManager->mapAddressToDeviceId(adt, deviceId);
-
- bool useHalSoundDoseInterface = !mSoundDoseManager->forceUseFrameworkMel();
- {
- std::lock_guard _l(mLock);
- useHalSoundDoseInterface &= mUseHalSoundDoseInterface;
- }
- if (!useHalSoundDoseInterface) {
- startMelComputationForNewPatch(streamHandle, deviceId);
- }
}
}
+ std::lock_guard _afl(mAudioFlinger.mLock);
std::lock_guard _l(mLock);
- mActiveMelPatches[patch.mAudioPatch.id] = newPatch;
+ ALOGV("%s add patch handle %d to active devices", __func__, handle);
+ startMelComputationForActivePatch_l(newPatch);
+ newPatch.csdActive = true;
+ mActiveMelPatches[handle] = 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) {
+void AudioFlinger::MelReporter::startMelComputationForActivePatch_l(const ActiveMelPatch& patch) {
+ auto thread = mAudioFlinger.checkPlaybackThread_l(patch.streamHandle);
+ if (thread == nullptr) {
+ ALOGE("%s cannot find thread for stream handle %d", __func__, patch.streamHandle);
+ return;
+ }
+
+ for (const auto& deviceHandle : patch.deviceHandles) {
+ ++mActiveDevices[deviceHandle];
+ ALOGI("%s add stream %d that uses device %d for CSD, nr of streams: %d", __func__,
+ patch.streamHandle, deviceHandle, mActiveDevices[deviceHandle]);
thread->startMelComputation(mSoundDoseManager->getOrCreateProcessorForDevice(
- deviceId,
- streamHandle,
+ deviceHandle,
+ patch.streamHandle,
thread->mSampleRate,
thread->mChannelCount,
thread->mFormat));
- }
+ }
}
void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
- ALOGV("%s", __func__);
-
ActiveMelPatch melPatch;
{
std::lock_guard _l(mLock);
auto patchIt = mActiveMelPatches.find(handle);
if (patchIt == mActiveMelPatches.end()) {
- ALOGW(
- "%s patch does not contain any mix sources with active MEL calculation",
- __func__);
+ ALOGV("%s patch handle %d does not contain any mix sources with active MEL calculation",
+ __func__, handle);
return;
}
@@ -172,10 +205,9 @@
mActiveMelPatches.erase(patchIt);
}
- for (const auto& deviceId : melPatch.deviceHandles) {
- mSoundDoseManager->clearMapDeviceIdEntries(deviceId);
- }
- stopInternalMelComputationForStream(melPatch.streamHandle);
+ std::lock_guard _afl(mAudioFlinger.mLock);
+ std::lock_guard _l(mLock);
+ stopMelComputationForPatch_l(melPatch);
}
sp<media::ISoundDose> AudioFlinger::MelReporter::getSoundDoseInterface(
@@ -191,17 +223,46 @@
mUseHalSoundDoseInterface = true;
}
-void AudioFlinger::MelReporter::stopInternalMelComputationForStream(audio_io_handle_t streamId) {
- ALOGV("%s: stop internal mel for stream id: %d", __func__, streamId);
+void AudioFlinger::MelReporter::stopMelComputationForPatch_l(const ActiveMelPatch& patch) {
+ auto thread = mAudioFlinger.checkPlaybackThread_l(patch.streamHandle);
+ ALOGV("%s: stop MEL for stream id: %d", __func__, patch.streamHandle);
+ for (const auto& deviceId : patch.deviceHandles) {
+ if (mActiveDevices[deviceId] > 0) {
+ --mActiveDevices[deviceId];
+ if (mActiveDevices[deviceId] == 0) {
+ // no stream is using deviceId anymore
+ ALOGI("%s removing device %d from active CSD devices", __func__, deviceId);
+ mSoundDoseManager->clearMapDeviceIdEntries(deviceId);
+ }
+ }
+ }
- std::lock_guard _lAf(mAudioFlinger.mLock);
- mSoundDoseManager->removeStreamProcessor(streamId);
- auto thread = mAudioFlinger.checkPlaybackThread_l(streamId);
+ mSoundDoseManager->removeStreamProcessor(patch.streamHandle);
if (thread != nullptr) {
thread->stopMelComputation();
}
}
+
+std::optional<audio_patch_handle_t> AudioFlinger::MelReporter::activePatchStreamHandle_l(
+ audio_io_handle_t streamHandle) {
+ for(const auto& patchIt : mActiveMelPatches) {
+ if (patchIt.second.streamHandle == streamHandle) {
+ return patchIt.first;
+ }
+ }
+ return std::nullopt;
+}
+
+bool AudioFlinger::MelReporter::useHalSoundDoseInterface() {
+ bool useHalSoundDoseInterface = !mSoundDoseManager->forceUseFrameworkMel();
+ {
+ std::lock_guard _l(mLock);
+ useHalSoundDoseInterface &= mUseHalSoundDoseInterface;
+ }
+ return useHalSoundDoseInterface;
+}
+
std::string AudioFlinger::MelReporter::dump() {
std::lock_guard _l(mLock);
std::string output("\nSound Dose:\n");