Audio Policy Engine: fix in call routing (and other)
Routing rules for a given strategy can be adapted depending on the
context (e.g when in call or not) in order to make sure that concurrent
use cases do not use conflicting routes and that the highest priority
strategy prevails.
This strategy "remapping" must be done before we check possible
overrides of default routing for a given strategy by
setDevicesRoleForStrategy().
Commit cca11ce4 did partially address this but some cases were left aside.
This commit generalizes the behavior and moves all the strategy
remappings out of getDevicesForStrategyInt()
Bug: 183380877
Test: audio smoke tests
Change-Id: Ia272dd28ffd39441b62c9a262c38bf47dc44e7f0
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 380bf6b..1a903a6 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -144,9 +144,10 @@
void Engine::filterOutputDevicesForStrategy(legacy_strategy strategy,
DeviceVector& availableOutputDevices,
- const DeviceVector availableInputDevices,
const SwAudioOutputCollection &outputs) const
{
+ DeviceVector availableInputDevices = getApmObserver()->getAvailableInputDevices();
+
switch (strategy) {
case STRATEGY_SONIFICATION_RESPECTFUL: {
if (!(isInCall() || outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_VOICE_CALL)))) {
@@ -204,9 +205,49 @@
}
}
+product_strategy_t Engine::remapStrategyFromContext(product_strategy_t strategy,
+ const SwAudioOutputCollection &outputs) const {
+ auto legacyStrategy = mLegacyStrategyMap.find(strategy) != end(mLegacyStrategyMap) ?
+ mLegacyStrategyMap.at(strategy) : STRATEGY_NONE;
+
+ if (isInCall()) {
+ switch (legacyStrategy) {
+ case STRATEGY_ACCESSIBILITY:
+ case STRATEGY_DTMF:
+ case STRATEGY_MEDIA:
+ case STRATEGY_SONIFICATION:
+ case STRATEGY_SONIFICATION_RESPECTFUL:
+ legacyStrategy = STRATEGY_PHONE;
+ break;
+
+ default:
+ return strategy;
+ }
+ } else {
+ switch (legacyStrategy) {
+ case STRATEGY_SONIFICATION_RESPECTFUL:
+ case STRATEGY_SONIFICATION:
+ if (outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_VOICE_CALL))) {
+ legacyStrategy = STRATEGY_PHONE;
+ }
+ break;
+
+ case STRATEGY_ACCESSIBILITY:
+ if (outputs.isActive(toVolumeSource(AUDIO_STREAM_RING)) ||
+ outputs.isActive(toVolumeSource(AUDIO_STREAM_ALARM))) {
+ legacyStrategy = STRATEGY_SONIFICATION;
+ }
+ break;
+
+ default:
+ return strategy;
+ }
+ }
+ return getProductStrategyFromLegacy(legacyStrategy);
+}
+
DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
DeviceVector availableOutputDevices,
- DeviceVector availableInputDevices,
const SwAudioOutputCollection &outputs) const
{
DeviceVector devices;
@@ -217,32 +258,6 @@
devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
break;
- case STRATEGY_SONIFICATION_RESPECTFUL:
- if (isInCall() || outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_VOICE_CALL))) {
- devices = getDevicesForStrategyInt(
- STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs);
- } else {
- bool media_active_locally =
- outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_MUSIC),
- SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)
- || outputs.isActiveLocally(
- toVolumeSource(AUDIO_STREAM_ACCESSIBILITY),
- SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY);
- devices = getDevicesForStrategyInt(STRATEGY_MEDIA,
- availableOutputDevices,
- availableInputDevices, outputs);
- // if no media is playing on the device, check for mandatory use of "safe" speaker
- // when media would have played on speaker, and the safe speaker path is available
- if (!media_active_locally) {
- devices.replaceDevicesByType(
- AUDIO_DEVICE_OUT_SPEAKER,
- availableOutputDevices.getDevicesFromType(
- AUDIO_DEVICE_OUT_SPEAKER_SAFE));
- }
- }
- break;
-
- case STRATEGY_DTMF:
case STRATEGY_PHONE: {
devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID);
if (!devices.isEmpty()) break;
@@ -257,16 +272,6 @@
} break;
case STRATEGY_SONIFICATION:
-
- // If incall, just select the STRATEGY_PHONE device
- if (isInCall() ||
- outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_VOICE_CALL))) {
- devices = getDevicesForStrategyInt(
- STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
- break;
- }
- FALLTHROUGH_INTENDED;
-
case STRATEGY_ENFORCED_AUDIBLE:
// strategy STRATEGY_ENFORCED_AUDIBLE uses same routing policy as STRATEGY_SONIFICATION
// except:
@@ -314,22 +319,9 @@
// The second device used for sonification is the same as the device used by media strategy
FALLTHROUGH_INTENDED;
+ case STRATEGY_DTMF:
case STRATEGY_ACCESSIBILITY:
- if (strategy == STRATEGY_ACCESSIBILITY) {
- if (outputs.isActive(toVolumeSource(AUDIO_STREAM_RING)) ||
- outputs.isActive(toVolumeSource(AUDIO_STREAM_ALARM))) {
- return getDevicesForStrategyInt(
- STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs);
- }
- if (isInCall()) {
- return getDevicesForStrategyInt(
- STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
- }
- }
- // For other cases, STRATEGY_ACCESSIBILITY behaves like STRATEGY_MEDIA
- FALLTHROUGH_INTENDED;
-
- // FIXME: STRATEGY_REROUTING follow STRATEGY_MEDIA for now
+ case STRATEGY_SONIFICATION_RESPECTFUL:
case STRATEGY_REROUTING:
case STRATEGY_MEDIA: {
DeviceVector devices2;
@@ -342,11 +334,6 @@
devices2.add(remoteSubmix);
}
}
- if (isInCall() && (strategy == STRATEGY_MEDIA)) {
- devices = getDevicesForStrategyInt(
- STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
- break;
- }
if ((devices2.isEmpty()) &&
(getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) == AUDIO_POLICY_FORCE_SPEAKER)) {
@@ -394,9 +381,19 @@
devices.remove(devices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER));
}
- // for STRATEGY_SONIFICATION:
+ bool mediaActiveLocally =
+ outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_MUSIC),
+ SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)
+ || outputs.isActiveLocally(
+ toVolumeSource(AUDIO_STREAM_ACCESSIBILITY),
+ SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY);
+ // - for STRATEGY_SONIFICATION:
// if SPEAKER was selected, and SPEAKER_SAFE is available, use SPEAKER_SAFE instead
- if (strategy == STRATEGY_SONIFICATION) {
+ // - for STRATEGY_SONIFICATION_RESPECTFUL:
+ // if no media is playing on the device, check for mandatory use of "safe" speaker
+ // when media would have played on speaker, and the safe speaker path is available
+ if (strategy == STRATEGY_SONIFICATION
+ || (strategy == STRATEGY_SONIFICATION_RESPECTFUL && !mediaActiveLocally)) {
devices.replaceDevicesByType(
AUDIO_DEVICE_OUT_SPEAKER,
availableOutputDevices.getDevicesFromType(
@@ -649,22 +646,20 @@
return preferredAvailableDevVec;
}
+
DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t strategy) const {
- DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
+ const SwAudioOutputCollection& outputs = getApmObserver()->getOutputs();
+
+ // Take context into account to remap product strategy before
+ // checking preferred device for strategy and applying default routing rules
+ strategy = remapStrategyFromContext(strategy, outputs);
+
auto legacyStrategy = mLegacyStrategyMap.find(strategy) != end(mLegacyStrategyMap) ?
mLegacyStrategyMap.at(strategy) : STRATEGY_NONE;
- // When not in call, STRATEGY_DTMF follows STRATEGY_MEDIA
- if (!isInCall() && legacyStrategy == STRATEGY_DTMF) {
- legacyStrategy = STRATEGY_MEDIA;
- strategy = getProductStrategyFromLegacy(STRATEGY_MEDIA);
- }
+ DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
- DeviceVector availableInputDevices = getApmObserver()->getAvailableInputDevices();
- const SwAudioOutputCollection& outputs = getApmObserver()->getOutputs();
-
- filterOutputDevicesForStrategy(legacyStrategy, availableOutputDevices,
- availableInputDevices, outputs);
+ filterOutputDevicesForStrategy(legacyStrategy, availableOutputDevices, outputs);
// check if this strategy has a preferred device that is available,
// if yes, give priority to it.
@@ -676,7 +671,7 @@
return getDevicesForStrategyInt(legacyStrategy,
availableOutputDevices,
- availableInputDevices, outputs);
+ outputs);
}
DeviceVector Engine::getOutputDevicesForAttributes(const audio_attributes_t &attributes,