Notifications are not duplicated over multiple devices
Sonifications follow media routing, except for speaker playback
where they follow the "safe" path when available in the
absence of media playback.
Test: 1/ plug headphones on phone, play notification, verify it
comes only from headset
2/ mirror device and play media, then notification, verify
it only comes from the speaker
Change-Id: I762ad0688e879ad1e5565b4b77a7393fa7ce7ac5
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 2803ec1..cd2174d 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -187,6 +187,15 @@
bool isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
/**
+ * return whether a stream is playing, but not on a "remote" device.
+ * Override to change the definition of a local/remote playback.
+ * Used for instance by policy manager to alter the speaker playback ("speaker safe" behavior)
+ * when media plays or not locally.
+ * For the base implementation, "remotely" means playing during screen mirroring.
+ */
+ bool isStreamActiveLocally(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
+
+ /**
* returns the A2DP output handle if it is open or 0 otherwise
*/
audio_io_handle_t getA2dpOutput() const;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index d5e8e1b..17fc272 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -579,6 +579,19 @@
return false;
}
+bool SwAudioOutputCollection::isStreamActiveLocally(audio_stream_type_t stream, uint32_t inPastMs) const
+{
+ nsecs_t sysTime = systemTime();
+ for (size_t i = 0; i < this->size(); i++) {
+ const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i);
+ if (outputDesc->isStreamActive(stream, inPastMs, sysTime)
+ && ((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) == 0)) {
+ return true;
+ }
+ }
+ return false;
+}
+
bool SwAudioOutputCollection::isStreamActiveRemotely(audio_stream_type_t stream,
uint32_t inPastMs) const
{
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 9bdb98c..5ec0475 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -238,18 +238,19 @@
const SwAudioOutputCollection &outputs = mApmObserver->getOutputs();
return getDeviceForStrategyInt(strategy, availableOutputDevices,
- availableInputDevices, outputs);
+ availableInputDevices, outputs, (uint32_t)AUDIO_DEVICE_NONE);
}
-
audio_devices_t Engine::getDeviceForStrategyInt(routing_strategy strategy,
- DeviceVector availableOutputDevices,
- DeviceVector availableInputDevices,
- const SwAudioOutputCollection &outputs) const
+ DeviceVector availableOutputDevices,
+ DeviceVector availableInputDevices,
+ const SwAudioOutputCollection &outputs,
+ uint32_t outputDeviceTypesToIgnore) const
{
uint32_t device = AUDIO_DEVICE_NONE;
- uint32_t availableOutputDevicesType = availableOutputDevices.types();
+ uint32_t availableOutputDevicesType =
+ availableOutputDevices.types() & ~outputDeviceTypesToIgnore;
switch (strategy) {
@@ -260,38 +261,24 @@
case STRATEGY_SONIFICATION_RESPECTFUL:
if (isInCall()) {
device = getDeviceForStrategyInt(
- STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs);
- } else if (outputs.isStreamActiveRemotely(AUDIO_STREAM_MUSIC,
- SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
- // while media is playing on a remote device, use the the sonification behavior.
- // Note that we test this usecase before testing if media is playing because
- // the isStreamActive() method only informs about the activity of a stream, not
- // if it's for local playback. Note also that we use the same delay between both tests
- device = getDeviceForStrategyInt(
- STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs);
- //user "safe" speaker if available instead of normal speaker to avoid triggering
- //other acoustic safety mechanisms for notification
- if ((device & AUDIO_DEVICE_OUT_SPEAKER) &&
- (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
- device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE;
- device &= ~AUDIO_DEVICE_OUT_SPEAKER;
- }
- } else if (outputs.isStreamActive(
- AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)
- || outputs.isStreamActive(
- AUDIO_STREAM_ACCESSIBILITY, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY))
- {
- // while media/a11y is playing (or has recently played), use the same device
- device = getDeviceForStrategyInt(
- STRATEGY_MEDIA, availableOutputDevices, availableInputDevices, outputs);
+ STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs,
+ outputDeviceTypesToIgnore);
} else {
- // when media is not playing anymore, fall back on the sonification behavior
- device = getDeviceForStrategyInt(
- STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs);
- //user "safe" speaker if available instead of normal speaker to avoid triggering
- //other acoustic safety mechanisms for notification
- if ((device & AUDIO_DEVICE_OUT_SPEAKER) &&
- (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
+ bool media_active_locally =
+ outputs.isStreamActiveLocally(
+ AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)
+ || outputs.isStreamActiveLocally(
+ AUDIO_STREAM_ACCESSIBILITY, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY);
+ // routing is same as media without the "remote" device
+ device = getDeviceForStrategyInt(STRATEGY_MEDIA,
+ availableOutputDevices,
+ availableInputDevices, outputs,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX | outputDeviceTypesToIgnore);
+ // 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
+ && (device & AUDIO_DEVICE_OUT_SPEAKER)
+ && (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE;
device &= ~AUDIO_DEVICE_OUT_SPEAKER;
}
@@ -302,7 +289,8 @@
if (!isInCall()) {
// when off call, DTMF strategy follows the same rules as MEDIA strategy
device = getDeviceForStrategyInt(
- STRATEGY_MEDIA, availableOutputDevices, availableInputDevices, outputs);
+ STRATEGY_MEDIA, availableOutputDevices, availableInputDevices, outputs,
+ outputDeviceTypesToIgnore);
break;
}
// when in call, DTMF and PHONE strategies follow the same rules
@@ -408,7 +396,8 @@
// handleIncallSonification().
if (isInCall()) {
device = getDeviceForStrategyInt(
- STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
+ STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs,
+ outputDeviceTypesToIgnore);
break;
}
// FALL THROUGH
@@ -463,11 +452,13 @@
if (outputs.isStreamActive(AUDIO_STREAM_RING) ||
outputs.isStreamActive(AUDIO_STREAM_ALARM)) {
return getDeviceForStrategyInt(
- STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs);
+ STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs,
+ outputDeviceTypesToIgnore);
}
if (isInCall()) {
return getDeviceForStrategyInt(
- STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
+ STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs,
+ outputDeviceTypesToIgnore);
}
}
// For other cases, STRATEGY_ACCESSIBILITY behaves like STRATEGY_MEDIA
@@ -486,7 +477,8 @@
}
if (isInCall() && (strategy == STRATEGY_MEDIA)) {
device = getDeviceForStrategyInt(
- STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
+ STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs,
+ outputDeviceTypesToIgnore);
break;
}
if ((device2 == AUDIO_DEVICE_NONE) &&
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index 57538c4..06186c1 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -126,9 +126,10 @@
routing_strategy getStrategyForUsage(audio_usage_t usage);
audio_devices_t getDeviceForStrategy(routing_strategy strategy) const;
audio_devices_t getDeviceForStrategyInt(routing_strategy strategy,
- DeviceVector availableOutputDevices,
- DeviceVector availableInputDevices,
- const SwAudioOutputCollection &outputs) const;
+ DeviceVector availableOutputDevices,
+ DeviceVector availableInputDevices,
+ const SwAudioOutputCollection &outputs,
+ uint32_t outputDeviceTypesToIgnore) const;
audio_devices_t getDeviceForInputSource(audio_source_t inputSource) const;
audio_mode_t mPhoneState; /**< current phone state. */