Support routing audio playback to telephony uplink
This change enables phone apps to play audio to the uplink stream
during a call.
This change maks the AUDIO_OUTPUT_FLAG_INCALL_MUSIC_UPLINK flag to be added to the flags that are sent to the HAL when an ongoing call is active, the chosen output device is the TX telephony device, the stream type is music, and the calling app has the MODIFY_PHONE_STATE permission.
For this change to take place, the following changes were made to the signature of getOutputForAttr in IAudioPolicyService:
1. Add pid (process id) parameter to getOutputForAttr.
2. Make the flags parameter a pointer so changed value can be
examined by calling function.
Bug: 69973354.
Test: tested manually.
Change-Id: I74cef3f8b66de6e0e8f87b6235130c2cdf423da7
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 78a02b2..e058dc8 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -741,7 +741,7 @@
audio_stream_type_t *stream,
uid_t uid,
const audio_config_t *config,
- audio_output_flags_t flags,
+ audio_output_flags_t *flags,
audio_port_handle_t *selectedDeviceId,
audio_port_handle_t *portId)
{
@@ -801,12 +801,12 @@
audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
if ((attributes.flags & AUDIO_FLAG_HW_AV_SYNC) != 0) {
- flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
+ *flags = (audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
}
ALOGV("getOutputForAttr() device 0x%x, sampling rate %d, format %#x, channel mask %#x, "
"flags %#x",
- device, config->sample_rate, config->format, config->channel_mask, flags);
+ device, config->sample_rate, config->format, config->channel_mask, *flags);
*output = getOutputForDevice(device, session, *stream, config, flags);
if (*output == AUDIO_IO_HANDLE_NONE) {
@@ -828,7 +828,7 @@
audio_session_t session,
audio_stream_type_t stream,
const audio_config_t *config,
- audio_output_flags_t flags)
+ audio_output_flags_t *flags)
{
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
status_t status;
@@ -837,35 +837,41 @@
//force direct flag if offload flag is set: offloading implies a direct output stream
// and all common behaviors are driven by checking only the direct flag
// this should normally be set appropriately in the policy configuration file
- if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
- flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_DIRECT);
+ if ((*flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
+ *flags = (audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_DIRECT);
}
- if ((flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) {
- flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_DIRECT);
+ if ((*flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) {
+ *flags = (audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_DIRECT);
}
// only allow deep buffering for music stream type
if (stream != AUDIO_STREAM_MUSIC) {
- flags = (audio_output_flags_t)(flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER);
+ *flags = (audio_output_flags_t)(*flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER);
} else if (/* stream == AUDIO_STREAM_MUSIC && */
- flags == AUDIO_OUTPUT_FLAG_NONE &&
+ *flags == AUDIO_OUTPUT_FLAG_NONE &&
property_get_bool("audio.deep_buffer.media", false /* default_value */)) {
// use DEEP_BUFFER as default output for music stream type
- flags = (audio_output_flags_t)AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
+ *flags = (audio_output_flags_t)AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
}
if (stream == AUDIO_STREAM_TTS) {
- flags = AUDIO_OUTPUT_FLAG_TTS;
+ *flags = AUDIO_OUTPUT_FLAG_TTS;
} else if (stream == AUDIO_STREAM_VOICE_CALL &&
audio_is_linear_pcm(config->format)) {
- flags = (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_VOIP_RX |
+ *flags = (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_VOIP_RX |
AUDIO_OUTPUT_FLAG_DIRECT);
ALOGV("Set VoIP and Direct output flags for PCM format");
+ } else if (device == AUDIO_DEVICE_OUT_TELEPHONY_TX &&
+ stream == AUDIO_STREAM_MUSIC &&
+ audio_is_linear_pcm(config->format) &&
+ isInCall()) {
+ *flags = (audio_output_flags_t)AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
}
+
sp<IOProfile> profile;
// skip direct output selection if the request can obviously be attached to a mixed output
// and not explicitly requested
- if (((flags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) &&
+ if (((*flags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) &&
audio_is_linear_pcm(config->format) && config->sample_rate <= SAMPLE_RATE_HZ_MAX &&
audio_channel_count_from_out_mask(config->channel_mask) <= 2) {
goto non_direct_output;
@@ -878,13 +884,13 @@
// This may prevent offloading in rare situations where effects are left active by apps
// in the background.
- if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) ||
+ if (((*flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) ||
!(mEffects.isNonOffloadableEffectEnabled() || mMasterMono)) {
profile = getProfileForDirectOutput(device,
config->sample_rate,
config->format,
config->channel_mask,
- (audio_output_flags_t)flags);
+ (audio_output_flags_t)*flags);
}
if (profile != 0) {
@@ -916,7 +922,7 @@
String8 address = outputDevices.size() > 0 ? outputDevices.itemAt(0)->mAddress
: String8("");
- status = outputDesc->open(config, device, address, stream, flags, &output);
+ status = outputDesc->open(config, device, address, stream, *flags, &output);
// only accept an output with the requested parameters
if (status != NO_ERROR ||
@@ -954,7 +960,7 @@
// A request for HW A/V sync cannot fallback to a mixed output because time
// stamps are embedded in audio data
- if ((flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) {
+ if ((*flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) {
return AUDIO_IO_HANDLE_NONE;
}
@@ -969,12 +975,12 @@
SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs);
// at this stage we should ignore the DIRECT flag as no direct output could be found earlier
- flags = (audio_output_flags_t)(flags & ~AUDIO_OUTPUT_FLAG_DIRECT);
- output = selectOutput(outputs, flags, config->format);
+ *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_DIRECT);
+ output = selectOutput(outputs, *flags, config->format);
}
ALOGW_IF((output == 0), "getOutputForDevice() could not find output for stream %d, "
"sampling rate %d, format %#x, channels %#x, flags %#x",
- stream, config->sample_rate, config->format, config->channel_mask, flags);
+ stream, config->sample_rate, config->format, config->channel_mask, *flags);
return output;
}