Enable global effect on Spatializer thread
- APM select spatializer output for music effects when it is active
- mirror mEffectBuffer input/output for AUDIO_SESSION_OUTPUT_MIX session
- return mixerChannelMask for AUDIO_SESSION_OUTPUT_MIX session
- add a helper for stereo spatializer feature enablement check
Flag: EXEMPT bugfix
Bug: 361519000
Test: Enable Visualizer/DynamicsProcessing effect with Clarity
Test: atest CtsMediaAudioTestCases
Change-Id: I366da7bde778040fb8907505760b8e5fc061161d
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 6273570..84505d3 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -3266,7 +3266,9 @@
}
if (mThreadType == IAfThreadBase::SPATIALIZER) {
- if (c->sessionId() == AUDIO_SESSION_OUTPUT_STAGE) {
+ if (c->sessionId() == AUDIO_SESSION_OUTPUT_MIX) {
+ return t->mixerChannelMask();
+ } else if (c->sessionId() == AUDIO_SESSION_OUTPUT_STAGE) {
if (c->isFirstEffect_l(id)) {
return t->mixerChannelMask();
} else {
@@ -3313,7 +3315,8 @@
return t->channelMask();
}
} else {
- return t->channelMask();
+ return (c->sessionId() == AUDIO_SESSION_OUTPUT_MIX) ? t->mixerChannelMask()
+ : t->channelMask();
}
} else {
return t->channelMask();
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 583552a..400613a 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1578,14 +1578,13 @@
}
break;
case SPATIALIZER:
- // Global effects (AUDIO_SESSION_OUTPUT_MIX) are not supported on spatializer mixer
- // as there is no common accumulation buffer for sptialized and non sptialized tracks.
+ // Global effects (AUDIO_SESSION_OUTPUT_MIX) are supported on spatializer mixer, but only
+ // the spatialized track have global effects applied for now.
// Post processing effects (AUDIO_SESSION_OUTPUT_STAGE or AUDIO_SESSION_DEVICE)
// are supported and added after the spatializer.
if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
- ALOGW("%s: global effect %s not supported on spatializer thread %s",
- __func__, desc->name, mThreadName);
- return BAD_VALUE;
+ ALOGD("%s: global effect %s on spatializer thread %s", __func__, desc->name,
+ mThreadName);
} else if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
// only post processing , downmixer or spatializer effects on output stage session
if (IAfEffectModule::isSpatializer(&desc->type)
@@ -3803,19 +3802,31 @@
ALOGV("addEffectChain_l() creating new input buffer %p session %d",
buffer, session);
} else {
- // A global session on a SPATIALIZER thread is either OUTPUT_STAGE or DEVICE
- // - OUTPUT_STAGE session uses the mEffectBuffer as input buffer and
- // mPostSpatializerBuffer as output buffer
- // - DEVICE session uses the mPostSpatializerBuffer as input and output buffer.
- status_t result = mAfThreadCallback->getEffectsFactoryHal()->mirrorBuffer(
- mEffectBuffer, mEffectBufferSize, &halInBuffer);
- if (result != OK) return result;
- result = mAfThreadCallback->getEffectsFactoryHal()->mirrorBuffer(
- mPostSpatializerBuffer, mPostSpatializerBufferSize, &halOutBuffer);
- if (result != OK) return result;
+ status_t result = INVALID_OPERATION;
+ // Buffer configuration for global sessions on a SPATIALIZER thread:
+ // - AUDIO_SESSION_OUTPUT_MIX session uses the mEffectBuffer as input and output buffer
+ // - AUDIO_SESSION_OUTPUT_STAGE session uses the mEffectBuffer as input buffer and
+ // mPostSpatializerBuffer as output buffer
+ // - AUDIO_SESSION_DEVICE session uses the mPostSpatializerBuffer as input and output
+ // buffer
+ if (session == AUDIO_SESSION_OUTPUT_MIX || session == AUDIO_SESSION_OUTPUT_STAGE) {
+ result = mAfThreadCallback->getEffectsFactoryHal()->mirrorBuffer(
+ mEffectBuffer, mEffectBufferSize, &halInBuffer);
+ if (result != OK) return result;
- if (session == AUDIO_SESSION_DEVICE) {
- halInBuffer = halOutBuffer;
+ if (session == AUDIO_SESSION_OUTPUT_MIX) {
+ halOutBuffer = halInBuffer;
+ }
+ }
+
+ if (session == AUDIO_SESSION_OUTPUT_STAGE || session == AUDIO_SESSION_DEVICE) {
+ result = mAfThreadCallback->getEffectsFactoryHal()->mirrorBuffer(
+ mPostSpatializerBuffer, mPostSpatializerBufferSize, &halOutBuffer);
+ if (result != OK) return result;
+
+ if (session == AUDIO_SESSION_DEVICE) {
+ halInBuffer = halOutBuffer;
+ }
}
}
} else {
diff --git a/services/audiopolicy/common/include/SpatializerHelper.h b/services/audiopolicy/common/include/SpatializerHelper.h
new file mode 100644
index 0000000..2eb6613
--- /dev/null
+++ b/services/audiopolicy/common/include/SpatializerHelper.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+#pragma once
+
+#include <com_android_media_audio.h>
+#include <cutils/properties.h>
+
+namespace android {
+
+class SpatializerHelper {
+ public:
+ /**
+ * @brief Check if the stereo spatialization feature turned on by:
+ * - sysprop "ro.audio.stereo_spatialization_enabled" is true
+ * - com_android_media_audio_stereo_spatialization flag is on
+ *
+ * @return true if the stereo spatialization feature is enabled
+ * @return false if the stereo spatialization feature is not enabled
+ */
+ static bool isStereoSpatializationFeatureEnabled() {
+ static const bool stereoSpatializationEnabled =
+ property_get_bool("ro.audio.stereo_spatialization_enabled", false) &&
+ com_android_media_audio_stereo_spatialization();
+ return stereoSpatializationEnabled;
+ }
+};
+
+} // namespace android
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 3ac233f..5a23b44 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -45,7 +45,6 @@
#include <android_media_audiopolicy.h>
#include <com_android_media_audioserver.h>
#include <cutils/bitops.h>
-#include <cutils/properties.h>
#include <media/AudioParameter.h>
#include <policy.h>
#include <private/android_filesystem_config.h>
@@ -55,6 +54,7 @@
#include <utils/Log.h>
#include "AudioPolicyManager.h"
+#include "SpatializerHelper.h"
#include "TypeConverter.h"
namespace android {
@@ -3797,9 +3797,10 @@
// 1: An offloaded output. If the effect ends up not being offloadable,
// AudioFlinger will invalidate the track and the offloaded output
// will be closed causing the effect to be moved to a PCM output.
- // 2: A deep buffer output
- // 3: The primary output
- // 4: the first output in the list
+ // 2: Spatializer output if the stereo spatializer feature enabled
+ // 3: A deep buffer output
+ // 4: The primary output
+ // 5: the first output in the list
DeviceVector devices = mEngine->getOutputDevicesForAttributes(
attributes_initializer(AUDIO_USAGE_MEDIA), nullptr, false /*fromCache*/);
@@ -3814,28 +3815,36 @@
while (output == AUDIO_IO_HANDLE_NONE) {
audio_io_handle_t outputOffloaded = AUDIO_IO_HANDLE_NONE;
+ audio_io_handle_t outputSpatializer = AUDIO_IO_HANDLE_NONE;
audio_io_handle_t outputDeepBuffer = AUDIO_IO_HANDLE_NONE;
audio_io_handle_t outputPrimary = AUDIO_IO_HANDLE_NONE;
- for (audio_io_handle_t output : outputs) {
- sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(output);
+ for (audio_io_handle_t outputLoop : outputs) {
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(outputLoop);
if (activeOnly && !desc->isActive(toVolumeSource(AUDIO_STREAM_MUSIC))) {
continue;
}
ALOGV("selectOutputForMusicEffects activeOnly %d output %d flags 0x%08x",
- activeOnly, output, desc->mFlags);
+ activeOnly, outputLoop, desc->mFlags);
if ((desc->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
- outputOffloaded = output;
+ outputOffloaded = outputLoop;
+ }
+ if ((desc->mFlags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0) {
+ if (SpatializerHelper::isStereoSpatializationFeatureEnabled()) {
+ outputSpatializer = outputLoop;
+ }
}
if ((desc->mFlags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) != 0) {
- outputDeepBuffer = output;
+ outputDeepBuffer = outputLoop;
}
if ((desc->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) != 0) {
- outputPrimary = output;
+ outputPrimary = outputLoop;
}
}
if (outputOffloaded != AUDIO_IO_HANDLE_NONE) {
output = outputOffloaded;
+ } else if (outputSpatializer != AUDIO_IO_HANDLE_NONE) {
+ output = outputSpatializer;
} else if (outputDeepBuffer != AUDIO_IO_HANDLE_NONE) {
output = outputDeepBuffer;
} else if (outputPrimary != AUDIO_IO_HANDLE_NONE) {
@@ -6363,13 +6372,10 @@
// mode is not requested.
if (config != nullptr && *config != AUDIO_CONFIG_INITIALIZER) {
- static const bool stereo_spatialization_prop_enabled =
- property_get_bool("ro.audio.stereo_spatialization_enabled", false);
const bool channel_mask_spatialized =
- (stereo_spatialization_prop_enabled
- && com_android_media_audio_stereo_spatialization())
- ? audio_channel_mask_contains_stereo(config->channel_mask)
- : audio_is_channel_mask_spatialized(config->channel_mask);
+ SpatializerHelper::isStereoSpatializationFeatureEnabled()
+ ? audio_channel_mask_contains_stereo(config->channel_mask)
+ : audio_is_channel_mask_spatialized(config->channel_mask);
if (!channel_mask_spatialized) {
return false;
}
diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp
index 9cc3b8f..c7740ad 100644
--- a/services/audiopolicy/service/Spatializer.cpp
+++ b/services/audiopolicy/service/Spatializer.cpp
@@ -29,9 +29,7 @@
#include <android/content/AttributionSourceState.h>
#include <android/sysprop/BluetoothProperties.sysprop.h>
#include <audio_utils/fixedfft.h>
-#include <com_android_media_audio.h>
#include <cutils/bitops.h>
-#include <cutils/properties.h>
#include <hardware/sensors.h>
#include <media/stagefright/foundation/AHandler.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -43,6 +41,7 @@
#include <utils/Thread.h>
#include "Spatializer.h"
+#include "SpatializerHelper.h"
namespace android {
@@ -398,12 +397,10 @@
return status;
}
for (const auto channelMask : channelMasks) {
- static const bool stereo_spatialization_enabled =
- property_get_bool("ro.audio.stereo_spatialization_enabled", false);
const bool channel_mask_spatialized =
- (stereo_spatialization_enabled && com_android_media_audio_stereo_spatialization())
- ? audio_channel_mask_contains_stereo(channelMask)
- : audio_is_channel_mask_spatialized(channelMask);
+ SpatializerHelper::isStereoSpatializationFeatureEnabled()
+ ? audio_channel_mask_contains_stereo(channelMask)
+ : audio_is_channel_mask_spatialized(channelMask);
if (!channel_mask_spatialized) {
ALOGW("%s: ignoring channelMask:%#x", __func__, channelMask);
continue;
@@ -1272,12 +1269,9 @@
mDisplayOrientation);
// 4. Show flag or property state.
- static const bool stereo_spatialization_prop_enabled =
- property_get_bool("ro.audio.stereo_spatialization_enabled", false);
- const bool stereo_spatialization = com_android_media_audio_stereo_spatialization()
- && stereo_spatialization_prop_enabled;
- base::StringAppendF(&ss, "%sStereo Spatialization: %s\n", prefixSpace.c_str(),
- stereo_spatialization ? "true" : "false");
+ base::StringAppendF(
+ &ss, "%sStereo Spatialization: %s\n", prefixSpace.c_str(),
+ SpatializerHelper::isStereoSpatializationFeatureEnabled() ? "true" : "false");
ss.append(prefixSpace + "CommandLog:\n");
ss += mLocalLog.dumpToString((prefixSpace + " ").c_str(), mMaxLocalLogLine);