Merge "Support routing audio playback to telephony uplink"

gugelfrei
Nadav Bar 7 years ago committed by Android (Google) Code Review
commit 52fe83f701

@ -858,6 +858,7 @@ status_t AudioSystem::getOutputForAttr(const audio_attributes_t *attr,
audio_io_handle_t *output,
audio_session_t session,
audio_stream_type_t *stream,
pid_t pid,
uid_t uid,
const audio_config_t *config,
audio_output_flags_t flags,
@ -866,7 +867,7 @@ status_t AudioSystem::getOutputForAttr(const audio_attributes_t *attr,
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return NO_INIT;
return aps->getOutputForAttr(attr, output, session, stream, uid,
return aps->getOutputForAttr(attr, output, session, stream, pid, uid,
config,
flags, selectedDeviceId, portId);
}

@ -174,6 +174,7 @@ public:
audio_io_handle_t *output,
audio_session_t session,
audio_stream_type_t *stream,
pid_t pid,
uid_t uid,
const audio_config_t *config,
audio_output_flags_t flags,
@ -217,6 +218,7 @@ public:
data.writeInt32(1);
data.writeInt32(*stream);
}
data.writeInt32(pid);
data.writeInt32(uid);
data.write(config, sizeof(audio_config_t));
data.writeInt32(static_cast <uint32_t>(flags));
@ -968,6 +970,7 @@ status_t BnAudioPolicyService::onTransact(
if (hasStream) {
stream = (audio_stream_type_t)data.readInt32();
}
pid_t pid = (pid_t)data.readInt32();
uid_t uid = (uid_t)data.readInt32();
audio_config_t config;
memset(&config, 0, sizeof(audio_config_t));
@ -978,7 +981,7 @@ status_t BnAudioPolicyService::onTransact(
audio_port_handle_t portId = (audio_port_handle_t)data.readInt32();
audio_io_handle_t output = 0;
status_t status = getOutputForAttr(hasAttributes ? &attr : NULL,
&output, session, &stream, uid,
&output, session, &stream, pid, uid,
&config,
flags, &selectedDeviceId, &portId);
reply->writeInt32(status);

@ -216,6 +216,7 @@ public:
audio_io_handle_t *output,
audio_session_t session,
audio_stream_type_t *stream,
pid_t pid,
uid_t uid,
const audio_config_t *config,
audio_output_flags_t flags,

@ -60,6 +60,7 @@ public:
audio_io_handle_t *output,
audio_session_t session,
audio_stream_type_t *stream,
pid_t pid,
uid_t uid,
const audio_config_t *config,
audio_output_flags_t flags,

@ -115,6 +115,9 @@ const OutputFlagConverter::Table OutputFlagConverter::mTable[] = {
MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_DIRECT_PCM),
MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ),
MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_VOIP_RX),
// FIXME: this cast will be removed when the flag will be
// declared in types.hal for audio HAL V4.0 and auto imported to audio-base.h
MAKE_STRING_FROM_ENUM((audio_output_flags_t)AUDIO_OUTPUT_FLAG_INCALL_MUSIC),
TERMINATOR
};

@ -309,7 +309,7 @@ status_t AudioFlinger::openMmapStream(MmapStreamInterface::stream_direction_t di
fullConfig.format = config->format;
ret = AudioSystem::getOutputForAttr(attr, &io,
actualSessionId,
&streamType, client.clientUid,
&streamType, client.clientPid, client.clientUid,
&fullConfig,
(audio_output_flags_t)(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ |
AUDIO_OUTPUT_FLAG_DIRECT),
@ -690,7 +690,7 @@ sp<IAudioTrack> AudioFlinger::createTrack(const CreateTrackInput& input,
output.selectedDeviceId = input.selectedDeviceId;
lStatus = AudioSystem::getOutputForAttr(&input.attr, &output.outputId, sessionId, &streamType,
clientUid, &input.config, input.flags,
clientPid, clientUid, &input.config, input.flags,
&output.selectedDeviceId, &portId);
if (lStatus != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {

@ -153,4 +153,11 @@ bool dumpAllowed() {
return ok;
}
bool modifyPhoneStateAllowed(pid_t pid, uid_t uid) {
static const String16 sModifyPhoneState("android.permission.MODIFY_PHONE_STATE");
bool ok = checkPermission(sModifyPhoneState, pid, uid);
if (!ok) ALOGE("Request requires android.permission.MODIFY_PHONE_STATE");
return ok;
}
} // namespace android

@ -26,4 +26,5 @@ bool captureHotwordAllowed(pid_t pid, uid_t uid);
bool settingsAllowed();
bool modifyAudioRoutingAllowed();
bool dumpAllowed();
bool modifyPhoneStateAllowed(pid_t pid, uid_t uid);
}

@ -7819,6 +7819,7 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client,
ret = AudioSystem::getOutputForAttr(&mAttr, &io,
mSessionId,
&stream,
client.clientPid,
client.clientUid,
&config,
flags,

@ -116,7 +116,7 @@ public:
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) = 0;
// indicates to the audio policy manager that the output starts being used by corresponding stream.

@ -333,6 +333,10 @@ bool SwAudioOutputDescriptor::isFixedVolume(audio_devices_t device)
return true;
}
}
if (device == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
ALOGV("max gain when output device is telephony tx");
return true;
}
return false;
}

@ -741,7 +741,7 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
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 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
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_io_handle_t AudioPolicyManager::getOutputForDevice(
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 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevice(
//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 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevice(
// 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 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevice(
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 @@ non_direct_output:
// 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 @@ non_direct_output:
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;
}

@ -110,7 +110,7 @@ public:
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);
virtual status_t startOutput(audio_io_handle_t output,
@ -629,7 +629,7 @@ private:
audio_session_t session,
audio_stream_type_t stream,
const audio_config_t *config,
audio_output_flags_t flags);
audio_output_flags_t *flags);
// internal method to return the input handle for the given device and format
audio_io_handle_t getInputForDevice(audio_devices_t device,
String8 address,

@ -158,6 +158,7 @@ status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr,
audio_io_handle_t *output,
audio_session_t session,
audio_stream_type_t *stream,
pid_t pid,
uid_t uid,
const audio_config_t *config,
audio_output_flags_t flags,
@ -176,9 +177,26 @@ status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr,
"%s uid %d tried to pass itself off as %d", __FUNCTION__, callingUid, uid);
uid = callingUid;
}
return mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid,
audio_output_flags_t originalFlags = flags;
status_t result = mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid,
config,
flags, selectedDeviceId, portId);
&flags, selectedDeviceId, portId);
// FIXME: Introduce a way to check for the the telephony device before opening the output
if ((result == NO_ERROR) &&
(flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) &&
!modifyPhoneStateAllowed(pid, uid)) {
// If the app tries to play music through the telephony device and doesn't have permission
// the fallback to the default output device.
mAudioPolicyManager->releaseOutput(*output, *stream, session);
flags = originalFlags;
*selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
*portId = AUDIO_PORT_HANDLE_NONE;
result = mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid,
config,
&flags, selectedDeviceId, portId);
}
return result;
}
status_t AudioPolicyService::startOutput(audio_io_handle_t output,

@ -78,6 +78,7 @@ public:
audio_io_handle_t *output,
audio_session_t session,
audio_stream_type_t *stream,
pid_t pid,
uid_t uid,
const audio_config_t *config,
audio_output_flags_t flags,

Loading…
Cancel
Save