Fail if DAP render-only attempts to redirect mmaped stream
... to non-capable mmap device / mix port.
Bug: 293611855
Test: atest audiopolicy_tests
Change-Id: I8c8b4827633ba09af849c84e27332edbae1feaba
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index bc2ba31..0f9cc89 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -289,12 +289,20 @@
continue; // skip the mix
}
- if ((flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) && is_mix_loopback(policyMix->mRouteFlags)) {
- // AAudio MMAP_NOIRQ streams cannot be routed to loopback/loopback+render
- // using dynamic audio policy.
- ALOGD("%s: Rejecting MMAP_NOIRQ request matched to loopback dynamic audio policy mix.",
- __func__);
- return INVALID_OPERATION;
+ if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
+ if (is_mix_loopback(policyMix->mRouteFlags)) {
+ // AAudio MMAP_NOIRQ streams cannot be routed to loopback/loopback+render
+ // using dynamic audio policy.
+ ALOGD("%s: Rejecting MMAP_NOIRQ request matched to loopback dynamic "
+ "audio policy mix.", __func__);
+ return INVALID_OPERATION;
+ }
+ if (mixDevice != nullptr && !mixDevice->isMmap()) {
+ ALOGD("%s: Rejecting MMAP_NOIRQ request matched to dynamic audio policy "
+ "mix pointing to device %s which doesn't support mmap", __func__,
+ mixDevice->toString(false).c_str());
+ return INVALID_OPERATION;
+ }
}
if (mixDevice != nullptr && mixDevice->equals(requestedDevice)) {
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index b56bb16..7a391b6 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -1948,14 +1948,18 @@
}
TEST_F(AudioPolicyManagerTestMMapPlaybackRerouting,
- MmapPlaybackStreamMatchingRenderDapMixSucceeds) {
- // Add render-only mix matching the test uid.
+ MmapPlaybackStreamMatchingRenderDapMixSupportingMmapSucceeds) {
+ // Add render-only mix matching the test uid.
const int testUid = 12345;
- status_t ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER, AUDIO_DEVICE_OUT_SPEAKER,
- /*mixAddress=*/"", audioConfig, {createUidCriterion(testUid)});
+ // test_audio_policy_configuration.xml declares mmap-capable mix port
+ // for AUDIO_DEVICE_OUT_USB_DEVICE.
+ status_t ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_USB_DEVICE, /*mixAddress=*/"",
+ audioConfig, {createUidCriterion(testUid)});
ASSERT_EQ(NO_ERROR, ret);
- // Geting output for matching uid should succeed for mmaped stream.
+ // Geting output for matching uid should succeed for mmaped stream, because matched mix
+ // redirects to mmap capable device.
audio_output_flags_t outputFlags = AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
ASSERT_EQ(NO_ERROR,
mManager->getOutputForAttr(&attr, &mOutput, AUDIO_SESSION_NONE, &mStream,
@@ -1964,6 +1968,26 @@
&mOutputType, &mIsSpatialized, &mIsBitPerfect));
}
+TEST_F(AudioPolicyManagerTestMMapPlaybackRerouting,
+ MmapPlaybackStreamMatchingRenderDapMixNotSupportingMmapFails) {
+ // Add render-only mix matching the test uid.
+ const int testUid = 12345;
+ // Per test_audio_policy_configuration.xml AUDIO_DEVICE_OUT_SPEAKER doesn't support mmap.
+ status_t ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_SPEAKER, /*mixAddress=*/"", audioConfig,
+ {createUidCriterion(testUid)});
+ ASSERT_EQ(NO_ERROR, ret);
+
+ // Geting output for matching uid should fail for mmaped stream, because
+ // matched mix redirects to device which doesn't support mmap.
+ audio_output_flags_t outputFlags = AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
+ ASSERT_EQ(INVALID_OPERATION,
+ mManager->getOutputForAttr(&attr, &mOutput, AUDIO_SESSION_NONE, &mStream,
+ createAttributionSourceState(testUid), &audioConfig,
+ &outputFlags, &mSelectedDeviceId, &mPortId, {},
+ &mOutputType, &mIsSpatialized, &mIsBitPerfect));
+}
+
INSTANTIATE_TEST_SUITE_P(
MmapPlaybackRerouting, AudioPolicyManagerTestMMapPlaybackRerouting,
testing::Values(DPMmapTestParam(MIX_ROUTE_FLAG_LOOP_BACK, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
diff --git a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
index 50ca26a..7ab9519 100644
--- a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
+++ b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
@@ -55,6 +55,11 @@
samplingRates="8000 16000 32000 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
<mixPort name="hifi_output" role="source" flags="AUDIO_OUTPUT_FLAG_BIT_PERFECT"/>
+ <mixPort name="mmap_no_irq_out" role="source"
+ flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
</mixPorts>
<devicePorts>
<devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink">
@@ -96,7 +101,7 @@
<route type="mix" sink="BT A2DP Out"
sources="primary output,hifi_output"/>
<route type="mix" sink="USB Device Out"
- sources="primary output,hifi_output"/>
+ sources="primary output,hifi_output,mmap_no_irq_out"/>
</routes>
</module>