audiopolicy: apm: Fix default bus device issue
When a bus device is used as default, when calling setForceUse,
a given SwOutputDescriptor might be asked to switch to another
bus device (the default), violating the Policy Mix rule.
Test: see below
-start an automotive device with PolicyMix registered and
bus device as the default.
-Consider having a system bus for system sound and media for music.
-Play touch sound (check played in system bus).
-launch music player.
Result:
-Music shall be played on media bus device
-Touch sound still played on system bus device
Change-Id: I6668cffa525af51af6ed0838745658f72ae00a62
Signed-off-by: François Gaffie <francois.gaffie@renault.com>
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index e6a62d9..2932296 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -23,9 +23,10 @@
#include <system/audio.h>
#include <utils/String8.h>
-namespace android {
+#include <DeviceDescriptor.h>
+#include <AudioOutputDescriptor.h>
-class SwAudioOutputDescriptor;
+namespace android {
/**
* custom mix entry in mPolicyMixes
@@ -79,6 +80,18 @@
const DeviceVector &availableDeviceTypes,
AudioMix **policyMix);
+ /**
+ * @brief try to find a matching mix for a given output descriptor and returns the associated
+ * output device.
+ * @param output to be considered
+ * @param availableOutputDevices list of output devices currently reachable
+ * @param policyMix to be returned if any mix matching ouput descriptor
+ * @return device selected from the mix attached to the output, null pointer otherwise
+ */
+ sp<DeviceDescriptor> getDeviceAndMixForOutput(const sp<SwAudioOutputDescriptor> &output,
+ const DeviceVector &availableOutputDevices,
+ AudioMix **policyMix = nullptr);
+
status_t getInputMixForAttr(audio_attributes_t attr, AudioMix **policyMix);
status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices);
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 799950c..3b9411a 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -280,6 +280,27 @@
return BAD_VALUE;
}
+sp<DeviceDescriptor> AudioPolicyMixCollection::getDeviceAndMixForOutput(
+ const sp<SwAudioOutputDescriptor> &output,
+ const DeviceVector &availableOutputDevices,
+ AudioMix **policyMix)
+{
+ for (size_t i = 0; i < size(); i++) {
+ if (valueAt(i)->getOutput() == output) {
+ AudioMix *mix = valueAt(i)->getMix();
+ if (policyMix != nullptr)
+ *policyMix = mix;
+ // This Desc is involved in a Mix, which has the highest prio
+ audio_devices_t deviceType = mix->mDeviceType;
+ String8 address = mix->mDeviceAddress;
+ ALOGV("%s: device (0x%x, addr=%s) forced by mix",
+ __FUNCTION__, deviceType, address.c_str());
+ return availableOutputDevices.getDevice(deviceType, address, AUDIO_FORMAT_DEFAULT);
+ }
+ }
+ return nullptr;
+}
+
sp<DeviceDescriptor> AudioPolicyMixCollection::getDeviceAndMixForInputSource(
audio_source_t inputSource, const DeviceVector &availDevices, AudioMix **policyMix)
{
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 262ee8b..0d9663a 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -790,6 +790,9 @@
sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
DeviceVector newDevices = getNewOutputDevices(outputDesc, true /*fromCache*/);
if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (outputDesc != mPrimaryOutput)) {
+ // As done in setDeviceConnectionState, we could also fix default device issue by
+ // preventing the force re-routing in case of default dev that distinguishes on address.
+ // Let's give back to engine full device choice decision however.
waitMs = setOutputDevices(outputDesc, newDevices, !newDevices.isEmpty(), delayMs);
}
if (forceVolumeReeval && !newDevices.isEmpty()) {
@@ -4969,6 +4972,13 @@
return DeviceVector(device);
}
+ // Legacy Engine cannot take care of bus devices and mix, so we need to handle the conflict
+ // of setForceUse / Default Bus device here
+ device = mPolicyMixes.getDeviceAndMixForOutput(outputDesc, mAvailableOutputDevices);
+ if (device != nullptr) {
+ return DeviceVector(device);
+ }
+
// check the following by order of priority to request a routing change if necessary:
// 1: the strategy enforced audible is active and enforced on the output:
// use device for strategy enforced audible