APM: update logic for output selection with preferred mixer attributes.
1. All playback from the preferred mixer attributes owner will be routed
to output with preferred mixer.
2. If bit-perfect playback is active, APM will route all playback to the
preferred mixer when the routed device is the same as the targeted
device for preferred mixer.
3. The client will be bit-perfect only when it is from the owner of
preferred mixer attributes and the request matches the preferred
mixer attributes.
Bug: 263279716
Test: manually
Test: atest audiopolicy_tests
Change-Id: I74efef10909d888dd47cc66444685f5b19a08a43
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index aad82fb..e3f250e 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1281,17 +1281,26 @@
info = getPreferredMixerAttributesInfo(
outputDevices.itemAt(0)->getId(),
mEngine->getProductStrategyForAttributes(*resultAttr));
- if (info != nullptr && info->getUid() != uid && info->getActiveClientCount() == 0) {
- // Only use preferred mixer when the requested uid matched or
- // there is active client on preferred mixer.
+ // Only use preferred mixer if the uid matches or the preferred mixer is bit-perfect
+ // and it is currently active.
+ if (info != nullptr && info->getUid() != uid &&
+ ((info->getFlags() & AUDIO_OUTPUT_FLAG_BIT_PERFECT) == AUDIO_OUTPUT_FLAG_NONE ||
+ info->getActiveClientCount() == 0)) {
info = nullptr;
}
}
*output = getOutputForDevices(outputDevices, session, resultAttr, config,
flags, isSpatialized, info, resultAttr->flags & AUDIO_FLAG_MUTE_HAPTIC);
+ // The client will be active if the client is currently preferred mixer owner and the
+ // requested configuration matches the preferred mixer configuration.
*isBitPerfect = (info != nullptr
&& (info->getFlags() & AUDIO_OUTPUT_FLAG_BIT_PERFECT) != AUDIO_OUTPUT_FLAG_NONE
- && *output != AUDIO_IO_HANDLE_NONE);
+ && info->getUid() == uid
+ && *output != AUDIO_IO_HANDLE_NONE
+ // When bit-perfect output is selected for the preferred mixer attributes owner,
+ // only need to consider the config matches.
+ && mOutputs.valueFor(*output)->isConfigurationMatched(
+ clientConfig, AUDIO_OUTPUT_FLAG_NONE));
}
if (*output == AUDIO_IO_HANDLE_NONE) {
AudioProfileVector profiles;