audio policy: fix playback permission checks
Align playback permission checks implementation in getOutputforAttr() on
capture checks in getInputForAttr(): use an "output type" returned by
audio policy manager and check permission accordingly.
- Do not modify but reject request to play to call uplink when permission
is denied.
- Add missing permission check for injection to remote submix.
- Clarify permission check for record from remote submix by using the
uid/pid of client explicitly.
Bug:
Test: CTS test for AudioTrack and AudioREcord.
Test: GTS tests for dynamic policies and playback capture
Change-Id: Ic0eb3b9921a491e97c58fa8f637583059a54b3a2
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 3ea69f1..355e4f0 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -945,7 +945,8 @@
audio_output_flags_t *flags,
audio_port_handle_t *selectedDeviceId,
bool *isRequestedDeviceForExclusiveUse,
- std::vector<sp<SwAudioOutputDescriptor>> *secondaryDescs)
+ std::vector<sp<SwAudioOutputDescriptor>> *secondaryDescs,
+ output_type_t *outputType)
{
DeviceVector outputDevices;
const audio_port_handle_t requestedPortId = *selectedDeviceId;
@@ -953,6 +954,7 @@
const sp<DeviceDescriptor> requestedDevice =
mAvailableOutputDevices.getDeviceFromId(requestedPortId);
+ *outputType = API_OUTPUT_INVALID;
status_t status = getAudioAttributes(resultAttr, attr, *stream);
if (status != NO_ERROR) {
return status;
@@ -991,7 +993,13 @@
mix->mDeviceAddress,
AUDIO_FORMAT_DEFAULT);
*selectedDeviceId = deviceDesc != 0 ? deviceDesc->getId() : AUDIO_PORT_HANDLE_NONE;
+
ALOGV("getOutputForAttr() returns output %d", *output);
+ if (resultAttr->usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
+ *outputType = API_OUT_MIX_PLAYBACK;
+ } else {
+ *outputType = API_OUTPUT_LEGACY;
+ }
return NO_ERROR;
}
// Virtual sources must always be dynamicaly or explicitly routed
@@ -1048,6 +1056,12 @@
*selectedDeviceId = getFirstDeviceId(outputDevices);
+ if (outputDevices.onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
+ *outputType = API_OUTPUT_TELEPHONY_TX;
+ } else {
+ *outputType = API_OUTPUT_LEGACY;
+ }
+
ALOGV("%s returns output %d selectedDeviceId %d", __func__, *output, *selectedDeviceId);
return NO_ERROR;
@@ -1062,7 +1076,8 @@
audio_output_flags_t *flags,
audio_port_handle_t *selectedDeviceId,
audio_port_handle_t *portId,
- std::vector<audio_io_handle_t> *secondaryOutputs)
+ std::vector<audio_io_handle_t> *secondaryOutputs,
+ output_type_t *outputType)
{
// The supplied portId must be AUDIO_PORT_HANDLE_NONE
if (*portId != AUDIO_PORT_HANDLE_NONE) {
@@ -1082,7 +1097,7 @@
status_t status = getOutputForAttrInt(&resultAttr, output, session, attr, stream, uid,
config, flags, selectedDeviceId, &isRequestedDeviceForExclusiveUse,
- &secondaryOutputDescs);
+ &secondaryOutputDescs, outputType);
if (status != NO_ERROR) {
return status;
}
@@ -3909,10 +3924,11 @@
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
bool isRequestedDeviceForExclusiveUse = false;
std::vector<sp<SwAudioOutputDescriptor>> secondaryOutputs;
+ output_type_t outputType;
getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE,
&attributes, &stream, sourceDesc->uid(), &config, &flags,
&selectedDeviceId, &isRequestedDeviceForExclusiveUse,
- &secondaryOutputs);
+ &secondaryOutputs, &outputType);
if (output == AUDIO_IO_HANDLE_NONE) {
ALOGV("%s no output for device %s",
__FUNCTION__, dumpDeviceTypes(sinkDevices.types()).c_str());