APM: route all clients to bit-perfect output when it is active.
When bit-perfect output is active, all clients should be routed to
bit-perfect output so that there won't be issues for the HAL to configure
the sink.
Bug: 285345410
Test: atest audiopolicy_tests
Change-Id: I374171611f02e60f999ac81a0eed4db0c6079313
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index f093e68..7d667d5 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1293,7 +1293,8 @@
if (outputDevices.size() == 1) {
info = getPreferredMixerAttributesInfo(
outputDevices.itemAt(0)->getId(),
- mEngine->getProductStrategyForAttributes(*resultAttr));
+ mEngine->getProductStrategyForAttributes(*resultAttr),
+ true /*activeBitPerfectPreferred*/);
// 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 &&
@@ -4485,16 +4486,24 @@
}
sp<PreferredMixerAttributesInfo> AudioPolicyManager::getPreferredMixerAttributesInfo(
- audio_port_handle_t devicePortId, product_strategy_t strategy) {
+ audio_port_handle_t devicePortId,
+ product_strategy_t strategy,
+ bool activeBitPerfectPreferred) {
auto it = mPreferredMixerAttrInfos.find(devicePortId);
if (it == mPreferredMixerAttrInfos.end()) {
return nullptr;
}
- auto mixerAttrInfoIt = it->second.find(strategy);
- if (mixerAttrInfoIt == it->second.end()) {
- return nullptr;
+ if (activeBitPerfectPreferred) {
+ for (auto [strategy, info] : it->second) {
+ if ((info->getFlags() & AUDIO_OUTPUT_FLAG_BIT_PERFECT) != AUDIO_OUTPUT_FLAG_NONE
+ && info->getActiveClientCount() != 0) {
+ return info;
+ }
+ }
}
- return mixerAttrInfoIt->second;
+ auto strategyMatchedMixerAttrInfoIt = it->second.find(strategy);
+ return strategyMatchedMixerAttrInfoIt == it->second.end()
+ ? nullptr : strategyMatchedMixerAttrInfoIt->second;
}
status_t AudioPolicyManager::getPreferredMixerAttributes(
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 88bafef..98988e7 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -1298,8 +1298,15 @@
uint32_t flags,
bool isInput);
+ /**
+ * Returns the preferred mixer attributes info for the given device port id and strategy.
+ * Bit-perfect mixer attributes will be returned if it is active and
+ * `activeBitPerfectPreferred` is true.
+ */
sp<PreferredMixerAttributesInfo> getPreferredMixerAttributesInfo(
- audio_port_handle_t devicePortId, product_strategy_t strategy);
+ audio_port_handle_t devicePortId,
+ product_strategy_t strategy,
+ bool activeBitPerfectPreferred = false);
sp<SwAudioOutputDescriptor> reopenOutput(
sp<SwAudioOutputDescriptor> outputDesc,
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 97a1e0d..7a21aa8 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -1232,6 +1232,19 @@
EXPECT_FALSE(isBitPerfect);
EXPECT_EQ(bitPerfectOutput, output);
+ const audio_attributes_t dtmfAttr = {
+ .content_type = AUDIO_CONTENT_TYPE_UNKNOWN,
+ .usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
+ };
+ audio_io_handle_t dtmfOutput = AUDIO_IO_HANDLE_NONE;
+ selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ portId = AUDIO_PORT_HANDLE_NONE;
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ 48000, AUDIO_OUTPUT_FLAG_NONE, &dtmfOutput, &portId, dtmfAttr,
+ AUDIO_SESSION_NONE, anotherUid, &isBitPerfect);
+ EXPECT_FALSE(isBitPerfect);
+ EXPECT_EQ(bitPerfectOutput, dtmfOutput);
+
// When configuration matches preferred mixer attributes, which is bit-perfect, but the client
// is not the owner of preferred mixer attributes, the playback will not be bit-perfect.
getOutputForAttr(&selectedDeviceId, bitPerfectFormat, bitPerfectChannelMask,