getInputForAttr perm check cleanup pt2
Update param types for AudioPolicyManager::getInputForAttr to avoid
ptrs/inout for clarity.
No behavior changes for now.
Test: CtsMediaAudioTestCases
Bug: 374870131
Bug: 343523722
Flag: EXEMPT mechanical refactoring
Change-Id: Ic179b09159b47b5af5a56811af9ef759e47eea0c
diff --git a/media/libaudioclient/aidl/android/media/GetInputForAttrResponse.aidl b/media/libaudioclient/aidl/android/media/GetInputForAttrResponse.aidl
index 347bf79..9e57820 100644
--- a/media/libaudioclient/aidl/android/media/GetInputForAttrResponse.aidl
+++ b/media/libaudioclient/aidl/android/media/GetInputForAttrResponse.aidl
@@ -28,6 +28,8 @@
int selectedDeviceId;
/** Interpreted as audio_port_handle_t. */
int portId;
+ /** The virtual device id corresponding to the opened input. */
+ int virtualDeviceId;
/** The suggested config if fails to get an input. **/
AudioConfigBase config;
}
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 8dd247a..33194b7 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -19,15 +19,17 @@
#include <android/media/DeviceConnectedState.h>
#include <android/media/TrackInternalMuteInfo.h>
+#include <android/media/audio/common/AudioConfigBase.h>
#include <android/media/audio/common/AudioMMapPolicyInfo.h>
#include <android/media/audio/common/AudioMMapPolicyType.h>
+#include <android/media/GetInputForAttrResponse.h>
+#include <android/content/AttributionSourceState.h>
#include <media/AudioCommonTypes.h>
#include <media/AudioContainers.h>
#include <media/AudioDeviceTypeAddr.h>
-#include <media/AudioSystem.h>
#include <media/AudioPolicy.h>
+#include <media/AudioSystem.h>
#include <media/DeviceDescriptorBase.h>
-#include <android/content/AttributionSourceState.h>
#include <utils/String8.h>
namespace android {
@@ -161,18 +163,27 @@
// releases the output, return true if the output descriptor is reopened.
virtual bool releaseOutput(audio_port_handle_t portId) = 0;
- // request an input appropriate for record from the supplied device with supplied parameters.
- virtual status_t getInputForAttr(const audio_attributes_t *attr,
- audio_io_handle_t *input,
+ // Request an input appropriate for record from the supplied device with supplied parameters.
+ // attr -- attributes for the requested record
+ // requestedInput -- input only for MMAP mode where an input is re-used, otherwise output param
+ // requestedDeviceId, config, flags -- additional params for matching
+ // riid, session, attributionSource -- params which encapsulate client info to associate with
+ // this input
+ //
+ // On most errors, return a Status describing the error in the error object.
+ // However, in cases where an appropriate device cannot be found for a config, the error side of
+ // the unexpected will contain a suggested config.
+ virtual base::expected<media::GetInputForAttrResponse,
+ std::variant<binder::Status, media::audio::common::AudioConfigBase>>
+ getInputForAttr(audio_attributes_t attributes,
+ audio_io_handle_t requestedInput,
+ audio_port_handle_t requestedDeviceId,
+ audio_config_base_t config,
+ audio_input_flags_t flags,
audio_unique_id_t riid,
audio_session_t session,
const AttributionSourceState& attributionSource,
- audio_config_base_t *config,
- audio_input_flags_t flags,
- audio_port_handle_t *selectedDeviceId,
- input_type_t *inputType,
- audio_port_handle_t *portId,
- uint32_t *virtualDeviceId) = 0;
+ input_type_t *inputType /* out param */) = 0;
// indicates to the audio policy manager that the input starts being used.
virtual status_t startInput(audio_port_handle_t portId) = 0;
// indicates to the audio policy manager that the input stops being used.
diff --git a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
index 1c6248a..84ad604 100644
--- a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
+++ b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
@@ -286,7 +286,7 @@
bool AudioPolicyManagerFuzzer::getInputForAttr(
const audio_attributes_t &attr, audio_unique_id_t riid, audio_port_handle_t *selectedDeviceId,
audio_format_t format, audio_channel_mask_t channelMask, int sampleRate,
- audio_input_flags_t flags, audio_port_handle_t *portId, uint32_t *virtualDeviceId) {
+ audio_input_flags_t flags, audio_port_handle_t *portId, uint32_t*) {
audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
config.sample_rate = sampleRate;
@@ -300,11 +300,12 @@
AttributionSourceState attributionSource;
attributionSource.uid = 0;
attributionSource.token = sp<BBinder>::make();
- if (mManager->getInputForAttr(&attr, &input, riid, AUDIO_SESSION_NONE, attributionSource,
- &config, flags, selectedDeviceId, &inputType, portId, virtualDeviceId) != OK) {
- return false;
- }
- if (*portId == AUDIO_PORT_HANDLE_NONE || input == AUDIO_IO_HANDLE_NONE) {
+ const auto inputRes =
+ mManager->getInputForAttr(attr, input, *selectedDeviceId, config, flags, riid,
+ AUDIO_SESSION_NONE, attributionSource, &inputType);
+ if (!inputRes.has_value()) return false;
+
+ if (inputRes->portId == AUDIO_PORT_HANDLE_NONE || inputRes->input == AUDIO_IO_HANDLE_NONE) {
return false;
}
return true;
diff --git a/services/audiopolicy/managerdefault/Android.bp b/services/audiopolicy/managerdefault/Android.bp
index e6f6374..94be786 100644
--- a/services/audiopolicy/managerdefault/Android.bp
+++ b/services/audiopolicy/managerdefault/Android.bp
@@ -41,6 +41,7 @@
// a dependency on it in the device makefile. There will be no build time
// conflict with libaudiopolicyenginedefault.
"audioclient-types-aidl-cpp",
+ "audiopolicy-aidl-cpp",
// Flag support
"android.media.audiopolicy-aconfig-cc",
"com.android.media.audioserver-aconfig-cc",
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 0ebf8d1..88bced6 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include "utils/Errors.h"
#define LOG_TAG "APM_AudioPolicyManager"
// Need to keep the log statements even in production builds
@@ -46,6 +45,7 @@
#include <android_media_audiopolicy.h>
#include <com_android_media_audioserver.h>
#include <cutils/bitops.h>
+#include <error/expected_utils.h>
#include <media/AudioParameter.h>
#include <policy.h>
#include <private/android_filesystem_config.h>
@@ -71,6 +71,8 @@
using android::media::audio::common::AudioMMapPolicyType;
using android::media::audio::common::AudioPortDeviceExt;
using android::media::audio::common::AudioPortExt;
+using android::media::audio::common::AudioConfigBase;
+using binder::Status;
using com::android::media::audioserver::fix_call_audio_patch;
using content::AttributionSourceState;
@@ -2925,63 +2927,57 @@
return false;
}
-status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr,
- audio_io_handle_t *input,
- audio_unique_id_t riid,
- audio_session_t session,
- const AttributionSourceState& attributionSource,
- audio_config_base_t *config,
- audio_input_flags_t flags,
- audio_port_handle_t *selectedDeviceId,
- input_type_t *inputType,
- audio_port_handle_t *portId,
- uint32_t *virtualDeviceId)
+base::expected<media::GetInputForAttrResponse, std::variant<binder::Status, AudioConfigBase>>
+AudioPolicyManager::getInputForAttr(audio_attributes_t attributes,
+ audio_io_handle_t requestedInput,
+ audio_port_handle_t requestedDeviceId,
+ audio_config_base_t config,
+ audio_input_flags_t flags,
+ audio_unique_id_t riid,
+ audio_session_t session,
+ const AttributionSourceState& attributionSource,
+ input_type_t *inputType)
{
ALOGV("%s() source %d, sampling rate %d, format %#x, channel mask %#x, session %d, "
"flags %#x attributes=%s requested device ID %d",
- __func__, attr->source, config->sample_rate, config->format, config->channel_mask,
- session, flags, toString(*attr).c_str(), *selectedDeviceId);
+ __func__, attributes.source, config.sample_rate, config.format, config.channel_mask,
+ session, flags, toString(attributes).c_str(), requestedDeviceId);
- status_t status = NO_ERROR;
- audio_attributes_t attributes = *attr;
sp<AudioPolicyMix> policyMix;
sp<DeviceDescriptor> device;
sp<AudioInputDescriptor> inputDesc;
sp<AudioInputDescriptor> previousInputDesc;
sp<RecordClientDescriptor> clientDesc;
- audio_port_handle_t requestedDeviceId = *selectedDeviceId;
- uid_t uid = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_uid_t(attributionSource.uid));
+ uid_t uid = static_cast<uid_t>(attributionSource.uid);
bool isSoundTrigger;
+ int vdi = 0 /* default device id */;
+ audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
- // The supplied portId must be AUDIO_PORT_HANDLE_NONE
- if (*portId != AUDIO_PORT_HANDLE_NONE) {
- return INVALID_OPERATION;
- }
-
- if (attr->source == AUDIO_SOURCE_DEFAULT) {
+ if (attributes.source == AUDIO_SOURCE_DEFAULT) {
attributes.source = AUDIO_SOURCE_MIC;
}
// Explicit routing?
sp<DeviceDescriptor> explicitRoutingDevice =
- mAvailableInputDevices.getDeviceFromId(*selectedDeviceId);
+ mAvailableInputDevices.getDeviceFromId(requestedDeviceId);
// special case for mmap capture: if an input IO handle is specified, we reuse this input if
// possible
if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) == AUDIO_INPUT_FLAG_MMAP_NOIRQ &&
- *input != AUDIO_IO_HANDLE_NONE) {
- ssize_t index = mInputs.indexOfKey(*input);
+ requestedInput != AUDIO_IO_HANDLE_NONE) {
+ input = requestedInput;
+ ssize_t index = mInputs.indexOfKey(requestedInput);
if (index < 0) {
- ALOGW("getInputForAttr() unknown MMAP input %d", *input);
- status = BAD_VALUE;
- goto error;
+ return base::unexpected{Status::fromExceptionCode(
+ EX_ILLEGAL_ARGUMENT,
+ String8::format("%s unknown MMAP input %d", __func__, requestedInput))};
}
sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index);
RecordClientVector clients = inputDesc->getClientsForSession(session);
if (clients.size() == 0) {
- ALOGW("getInputForAttr() unknown session %d on input %d", session, *input);
- status = BAD_VALUE;
- goto error;
+ return base::unexpected{Status::fromExceptionCode(
+ EX_ILLEGAL_ARGUMENT, String8::format("%s unknown session %d on input %d",
+ __func__, session, requestedInput))};
}
// For MMAP mode, the first call to getInputForAttr() is made on behalf of audioflinger.
// The second call is for the first active client and sets the UID. Any further call
@@ -2997,146 +2993,139 @@
continue;
}
if (uid != client->uid() && !client->isSilenced()) {
- ALOGW("getInputForAttr() bad uid %d for client %d uid %d",
- uid, client->portId(), client->uid());
- status = INVALID_OPERATION;
- goto error;
+ return base::unexpected{Status::fromExceptionCode(
+ EX_ILLEGAL_STATE,
+ String8::format("%s bad uid %d for client %d uid %d", __func__, uid,
+ client->portId(), client->uid()))};
}
}
}
*inputType = API_INPUT_LEGACY;
device = inputDesc->getDevice();
-
- ALOGV("%s reusing MMAP input %d for session %d", __FUNCTION__, *input, session);
- goto exit;
- }
-
- *input = AUDIO_IO_HANDLE_NONE;
- *inputType = API_INPUT_INVALID;
-
- if (attributes.source == AUDIO_SOURCE_REMOTE_SUBMIX &&
- extractAddressFromAudioAttributes(attributes).has_value()) {
- status = mPolicyMixes.getInputMixForAttr(attributes, &policyMix);
- if (status != NO_ERROR) {
- ALOGW("%s could not find input mix for attr %s",
- __func__, toString(attributes).c_str());
- goto error;
- }
- device = mAvailableInputDevices.getDevice(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
- String8(attr->tags + strlen("addr=")),
- AUDIO_FORMAT_DEFAULT);
- if (device == nullptr) {
- ALOGW("%s could not find in Remote Submix device for source %d, tags %s",
- __func__, attributes.source, attributes.tags);
- status = BAD_VALUE;
- goto error;
- }
-
- if (is_mix_loopback_render(policyMix->mRouteFlags)) {
- *inputType = API_INPUT_MIX_PUBLIC_CAPTURE_PLAYBACK;
- } else {
- *inputType = API_INPUT_MIX_EXT_POLICY_REROUTE;
- }
- if (virtualDeviceId) {
- *virtualDeviceId = policyMix->mVirtualDeviceId;
- }
+ ALOGV("%s reusing MMAP input %d for session %d", __FUNCTION__, requestedInput, session);
+ // TODO perm check
} else {
- if (explicitRoutingDevice != nullptr) {
- device = explicitRoutingDevice;
+ *inputType = API_INPUT_INVALID;
+
+ if (attributes.source == AUDIO_SOURCE_REMOTE_SUBMIX &&
+ extractAddressFromAudioAttributes(attributes).has_value()) {
+ status_t status = mPolicyMixes.getInputMixForAttr(attributes, &policyMix);
+ if (status != NO_ERROR) {
+ ALOGW("%s could not find input mix for attr %s",
+ __func__, toString(attributes).c_str());
+ return base::unexpected {aidl_utils::binderStatusFromStatusT(status)};
+ }
+ device = mAvailableInputDevices.getDevice(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+ String8(attributes.tags + strlen("addr=")),
+ AUDIO_FORMAT_DEFAULT);
+ if (device == nullptr) {
+ return base::unexpected{Status::fromExceptionCode(
+ EX_ILLEGAL_ARGUMENT,
+ String8::format(
+ "%s could not find in Remote Submix device for source %d, tags %s",
+ __func__, attributes.source, attributes.tags))};
+ }
+
+ if (is_mix_loopback_render(policyMix->mRouteFlags)) {
+ *inputType = API_INPUT_MIX_PUBLIC_CAPTURE_PLAYBACK;
+ } else {
+ *inputType = API_INPUT_MIX_EXT_POLICY_REROUTE;
+ }
+ // TODO is this correct?
+ vdi = policyMix->mVirtualDeviceId;
} else {
- // Prevent from storing invalid requested device id in clients
- requestedDeviceId = AUDIO_PORT_HANDLE_NONE;
- device = mEngine->getInputDeviceForAttributes(attributes, uid, session, &policyMix);
- ALOGV_IF(device != nullptr, "%s found device type is 0x%X",
- __FUNCTION__, device->type());
- }
- if (device == nullptr) {
- ALOGW("getInputForAttr() could not find device for source %d", attributes.source);
- status = BAD_VALUE;
- goto error;
- }
- if (device->type() == AUDIO_DEVICE_IN_ECHO_REFERENCE) {
- *inputType = API_INPUT_MIX_CAPTURE;
- } else if (policyMix) {
- ALOG_ASSERT(policyMix->mMixType == MIX_TYPE_RECORDERS, "Invalid Mix Type");
- // there is an external policy, but this input is attached to a mix of recorders,
- // meaning it receives audio injected into the framework, so the recorder doesn't
- // know about it and is therefore considered "legacy"
- *inputType = API_INPUT_LEGACY;
-
- if (virtualDeviceId) {
- *virtualDeviceId = policyMix->mVirtualDeviceId;
+ if (explicitRoutingDevice != nullptr) {
+ device = explicitRoutingDevice;
+ } else {
+ // Prevent from storing invalid requested device id in clients
+ requestedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ device = mEngine->getInputDeviceForAttributes(attributes, uid, session, &policyMix);
+ ALOGV_IF(device != nullptr, "%s found device type is 0x%X",
+ __FUNCTION__, device->type());
}
- } else if (audio_is_remote_submix_device(device->type())) {
- *inputType = API_INPUT_MIX_CAPTURE;
- } else if (device->type() == AUDIO_DEVICE_IN_TELEPHONY_RX) {
- *inputType = API_INPUT_TELEPHONY_RX;
- } else {
- *inputType = API_INPUT_LEGACY;
+ if (device == nullptr) {
+ return base::unexpected{Status::fromExceptionCode(
+ EX_ILLEGAL_ARGUMENT,
+ String8::format("%s could not find device for source %d", __func__,
+ attributes.source))};
+ }
+ if (device->type() == AUDIO_DEVICE_IN_ECHO_REFERENCE) {
+ *inputType = API_INPUT_MIX_CAPTURE;
+ } else if (policyMix) {
+ ALOG_ASSERT(policyMix->mMixType == MIX_TYPE_RECORDERS, "Invalid Mix Type");
+ // there is an external policy, but this input is attached to a mix of recorders,
+ // meaning it receives audio injected into the framework, so the recorder doesn't
+ // know about it and is therefore considered "legacy"
+ *inputType = API_INPUT_LEGACY;
+ vdi = policyMix->mVirtualDeviceId;
+ } else if (audio_is_remote_submix_device(device->type())) {
+ *inputType = API_INPUT_MIX_CAPTURE;
+ } else if (device->type() == AUDIO_DEVICE_IN_TELEPHONY_RX) {
+ *inputType = API_INPUT_TELEPHONY_RX;
+ } else {
+ *inputType = API_INPUT_LEGACY;
+ }
}
+ // TODO perm check
+
+ input = getInputForDevice(device, session, attributes, config, flags, policyMix);
+ if (input == AUDIO_IO_HANDLE_NONE) {
+ AudioProfileVector profiles;
+ status_t ret = getProfilesForDevices(
+ DeviceVector(device), profiles, flags, true /*isInput*/);
+ if (ret == NO_ERROR && !profiles.empty()) {
+ const auto channels = profiles[0]->getChannels();
+ if (!channels.empty() && (channels.find(config.channel_mask) == channels.end())) {
+ config.channel_mask = *channels.begin();
+ }
+ const auto sampleRates = profiles[0]->getSampleRates();
+ if (!sampleRates.empty() &&
+ (sampleRates.find(config.sample_rate) == sampleRates.end())) {
+ config.sample_rate = *sampleRates.begin();
+ }
+ config.format = profiles[0]->getFormat();
+ }
+ const auto suggestedConfig = VALUE_OR_FATAL(
+ legacy2aidl_audio_config_base_t_AudioConfigBase(config, true /*isInput*/));
+ return base::unexpected {suggestedConfig};
+ }
}
- *input = getInputForDevice(device, session, attributes, config, flags, policyMix);
- if (*input == AUDIO_IO_HANDLE_NONE) {
- status = INVALID_OPERATION;
- AudioProfileVector profiles;
- status_t ret = getProfilesForDevices(
- DeviceVector(device), profiles, flags, true /*isInput*/);
- if (ret == NO_ERROR && !profiles.empty()) {
- const auto channels = profiles[0]->getChannels();
- if (!channels.empty() && (channels.find(config->channel_mask) == channels.end())) {
- config->channel_mask = *channels.begin();
- }
- const auto sampleRates = profiles[0]->getSampleRates();
- if (!sampleRates.empty() &&
- (sampleRates.find(config->sample_rate) == sampleRates.end())) {
- config->sample_rate = *sampleRates.begin();
- }
- config->format = profiles[0]->getFormat();
- }
- goto error;
- }
-
-
- if (policyMix != nullptr && virtualDeviceId != nullptr) {
- *virtualDeviceId = policyMix->mVirtualDeviceId;
- }
-
-exit:
-
- *selectedDeviceId = mAvailableInputDevices.contains(device) ?
+ auto selectedDeviceId = mAvailableInputDevices.contains(device) ?
device->getId() : AUDIO_PORT_HANDLE_NONE;
isSoundTrigger = attributes.source == AUDIO_SOURCE_HOTWORD &&
mSoundTriggerSessions.indexOfKey(session) >= 0;
- *portId = PolicyAudioPort::getNextUniqueId();
- clientDesc = new RecordClientDescriptor(*portId, riid, uid, session, attributes, *config,
+ const auto allocatedPortId = PolicyAudioPort::getNextUniqueId();
+
+ clientDesc = new RecordClientDescriptor(allocatedPortId, riid, uid, session, attributes, config,
requestedDeviceId, attributes.source, flags,
isSoundTrigger);
- inputDesc = mInputs.valueFor(*input);
+ inputDesc = mInputs.valueFor(input);
// Move (if found) effect for the client session to its input
- mEffects.moveEffectsForIo(session, *input, &mInputs, mpClientInterface);
+ mEffects.moveEffectsForIo(session, input, &mInputs, mpClientInterface);
inputDesc->addClient(clientDesc);
ALOGV("getInputForAttr() returns input %d type %d selectedDeviceId %d for port ID %d",
- *input, *inputType, *selectedDeviceId, *portId);
+ input, *inputType, selectedDeviceId, allocatedPortId);
- return NO_ERROR;
-
-error:
- return status;
+ auto ret = media::GetInputForAttrResponse {};
+ ret.input = input;
+ ret.selectedDeviceId = selectedDeviceId;
+ ret.portId = allocatedPortId;
+ ret.virtualDeviceId = vdi;
+ ret.config = legacy2aidl_audio_config_base_t_AudioConfigBase(config, true /*isInput*/).value();
+ return ret;
}
-
-audio_io_handle_t AudioPolicyManager::getInputForDevice(const sp<DeviceDescriptor> &device,
+audio_io_handle_t AudioPolicyManager::getInputForDevice(const sp<DeviceDescriptor>& device,
audio_session_t session,
- const audio_attributes_t &attributes,
- audio_config_base_t *config,
+ const audio_attributes_t& attributes,
+ const audio_config_base_t& config,
audio_input_flags_t flags,
- const sp<AudioPolicyMix> &policyMix)
-{
+ const sp<AudioPolicyMix>& policyMix) {
audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
audio_source_t halInputSource = attributes.source;
bool isSoundTrigger = false;
@@ -3152,7 +3141,7 @@
halInputSource = AUDIO_SOURCE_VOICE_RECOGNITION;
}
} else if (attributes.source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
- audio_is_linear_pcm(config->format)) {
+ audio_is_linear_pcm(config.format)) {
flags = (audio_input_flags_t)(flags | AUDIO_INPUT_FLAG_VOIP_TX);
}
@@ -3161,10 +3150,10 @@
}
// sampling rate and flags may be updated by getInputProfile
- uint32_t profileSamplingRate = (config->sample_rate == 0) ?
- SAMPLE_RATE_HZ_DEFAULT : config->sample_rate;
- audio_format_t profileFormat = config->format;
- audio_channel_mask_t profileChannelMask = config->channel_mask;
+ uint32_t profileSamplingRate = (config.sample_rate == 0) ?
+ SAMPLE_RATE_HZ_DEFAULT : config.sample_rate;
+ audio_format_t profileFormat = config.format;
+ audio_channel_mask_t profileChannelMask = config.channel_mask;
audio_input_flags_t profileFlags = flags;
// find a compatible input profile (not necessarily identical in parameters)
sp<IOProfile> profile = getInputProfile(
@@ -3174,7 +3163,7 @@
}
// Pick input sampling rate if not specified by client
- uint32_t samplingRate = config->sample_rate;
+ uint32_t samplingRate = config.sample_rate;
if (samplingRate == 0) {
samplingRate = profileSamplingRate;
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index e0cafd4..28bf5cb 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -134,17 +134,18 @@
virtual status_t startOutput(audio_port_handle_t portId);
virtual status_t stopOutput(audio_port_handle_t portId);
virtual bool releaseOutput(audio_port_handle_t portId);
- virtual status_t getInputForAttr(const audio_attributes_t *attr,
- audio_io_handle_t *input,
+
+ base::expected<media::GetInputForAttrResponse, std::variant<binder::Status,
+ media::audio::common::AudioConfigBase>>
+ getInputForAttr(audio_attributes_t attributes,
+ audio_io_handle_t requestedInput,
+ audio_port_handle_t requestedDeviceId,
+ audio_config_base_t config,
+ audio_input_flags_t flags,
audio_unique_id_t riid,
audio_session_t session,
const AttributionSourceState& attributionSource,
- audio_config_base_t *config,
- audio_input_flags_t flags,
- audio_port_handle_t *selectedDeviceId,
- input_type_t *inputType,
- audio_port_handle_t *portId,
- uint32_t *virtualDeviceId);
+ input_type_t *inputType /* out param */) override;
// indicates to the audio policy manager that the input starts being used.
virtual status_t startInput(audio_port_handle_t portId);
@@ -1226,7 +1227,7 @@
audio_io_handle_t getInputForDevice(const sp<DeviceDescriptor> &device,
audio_session_t session,
const audio_attributes_t &attributes,
- audio_config_base_t *config,
+ const audio_config_base_t &config,
audio_input_flags_t flags,
const sp<AudioPolicyMix> &policyMix);
diff --git a/services/audiopolicy/service/Android.bp b/services/audiopolicy/service/Android.bp
index 619c924..79e328e 100644
--- a/services/audiopolicy/service/Android.bp
+++ b/services/audiopolicy/service/Android.bp
@@ -11,6 +11,10 @@
cc_defaults {
name: "libaudiopolicyservice_dependencies",
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_shared",
+ ],
+
include_dirs: [
"frameworks/av/services/audiopolicy", // include path outside of libaudiopolicyservice
],
@@ -64,7 +68,6 @@
name: "libaudiopolicyservice",
defaults: [
- "latest_android_media_audio_common_types_cpp_shared",
"libaudiopolicyservice_dependencies",
],
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 20bc788..9d9836f 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -815,23 +815,21 @@
int32_t selectedDeviceIdAidl,
media::GetInputForAttrResponse* _aidl_return) {
auto inputSource = attrAidl.source;
- audio_attributes_t attr = VALUE_OR_RETURN_BINDER_STATUS(
+ const audio_attributes_t attr = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
- audio_io_handle_t input = VALUE_OR_RETURN_BINDER_STATUS(
+ const audio_io_handle_t requestedInput = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_int32_t_audio_io_handle_t(inputAidl));
- audio_unique_id_t riid = VALUE_OR_RETURN_BINDER_STATUS(
+ const audio_unique_id_t riid = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_int32_t_audio_unique_id_t(riidAidl));
- audio_session_t session = VALUE_OR_RETURN_BINDER_STATUS(
+ const audio_session_t session = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_int32_t_audio_session_t(sessionAidl));
- audio_config_base_t config = VALUE_OR_RETURN_BINDER_STATUS(
+ const audio_config_base_t config = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioConfigBase_audio_config_base_t(configAidl, true /*isInput*/));
- audio_input_flags_t flags = VALUE_OR_RETURN_BINDER_STATUS(
+ const audio_input_flags_t flags = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_int32_t_audio_input_flags_t_mask(flagsAidl));
- audio_port_handle_t selectedDeviceId = VALUE_OR_RETURN_BINDER_STATUS(
+ const audio_port_handle_t requestedDeviceId = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_int32_t_audio_port_handle_t(selectedDeviceIdAidl));
- audio_port_handle_t portId;
-
if (mAudioPolicyManager == NULL) {
return binderStatusFromStatusT(NO_INIT);
}
@@ -881,77 +879,72 @@
toString(inputSource).c_str()));
}
- uint32_t virtualDeviceId = kDefaultVirtualDeviceId;
-
- sp<AudioPolicyEffects>audioPolicyEffects;
+ sp<AudioPolicyEffects> audioPolicyEffects;
+ base::expected<media::GetInputForAttrResponse, std::variant<binder::Status, AudioConfigBase>>
+ res;
{
- status_t status;
AudioPolicyInterface::input_type_t inputType;
audio_utils::lock_guard _l(mMutex);
{
AutoCallerClear acc;
// the audio_in_acoustics_t parameter is ignored by get_input()
- status = mAudioPolicyManager->getInputForAttr(&attr, &input, riid, session,
- attributionSource, &config,
- flags, &selectedDeviceId,
- &inputType, &portId,
- &virtualDeviceId);
+ res = mAudioPolicyManager->getInputForAttr(attr, requestedInput, requestedDeviceId,
+ config, flags, riid, session, attributionSource, &inputType);
}
audioPolicyEffects = mAudioPolicyEffects;
- if (status == NO_ERROR) {
+ if (res.has_value()) {
const auto permResult = evaluatePermsForDevice(attributionSource,
- inputSource, inputType, virtualDeviceId,
+ inputSource, inputType, res->virtualDeviceId,
isCallRedir);
if (!permResult.has_value()) {
AutoCallerClear acc;
- mAudioPolicyManager->releaseInput(portId);
+ mAudioPolicyManager->releaseInput(res->portId);
return permResult.error();
} else if (!permResult.value()) {
AutoCallerClear acc;
- mAudioPolicyManager->releaseInput(portId);
+ mAudioPolicyManager->releaseInput(res->portId);
return Status::fromExceptionCode(
EX_SECURITY,
String8::format(
"%s: %s missing perms for input type %d, inputSource %d, vdi %d",
__func__, attributionSource.toString().c_str(), inputType,
- inputSource, virtualDeviceId));
+ inputSource, res->virtualDeviceId));
}
}
- if (status != NO_ERROR) {
- _aidl_return->config = VALUE_OR_RETURN_BINDER_STATUS(
- legacy2aidl_audio_config_base_t_AudioConfigBase(config, true /*isInput*/));
- return binderStatusFromStatusT(status);
+ if (!res.has_value()) {
+ if (res.error().index() == 1) {
+ _aidl_return->config = std::get<1>(res.error());
+ return Status::fromExceptionCode(EX_ILLEGAL_STATE);
+ } else {
+ return std::get<0>(res.error());
+ }
}
- DeviceIdVector selectedDeviceIds = { selectedDeviceId };
- sp<AudioRecordClient> client = new AudioRecordClient(attr, input, session, portId,
+ DeviceIdVector selectedDeviceIds = { res->selectedDeviceId };
+ sp<AudioRecordClient> client = new AudioRecordClient(attr, res->input, session, res->portId,
selectedDeviceIds, attributionSource,
- virtualDeviceId,
+ res->virtualDeviceId,
canBypassConcurrentPolicy,
mOutputCommandThread);
- mAudioRecordClients.add(portId, client);
+ mAudioRecordClients.add(res->portId, client);
}
if (audioPolicyEffects != 0) {
// create audio pre processors according to input source
- status_t status = audioPolicyEffects->addInputEffects(input,
+ status_t status = audioPolicyEffects->addInputEffects(res->input,
aidl2legacy_AudioSource_audio_source_t(inputSource).value(), session);
if (status != NO_ERROR && status != ALREADY_EXISTS) {
- ALOGW("Failed to add effects on input %d", input);
+ ALOGW("Failed to add effects on input %d", res->input);
}
}
- _aidl_return->input = VALUE_OR_RETURN_BINDER_STATUS(
- legacy2aidl_audio_io_handle_t_int32_t(input));
- _aidl_return->selectedDeviceId = VALUE_OR_RETURN_BINDER_STATUS(
- legacy2aidl_audio_port_handle_t_int32_t(selectedDeviceId));
- _aidl_return->portId = VALUE_OR_RETURN_BINDER_STATUS(
- legacy2aidl_audio_port_handle_t_int32_t(portId));
+ *_aidl_return = res.value();
+
return Status::ok();
}
diff --git a/services/audiopolicy/tests/Android.bp b/services/audiopolicy/tests/Android.bp
index 182dc61..a6e5c75 100644
--- a/services/audiopolicy/tests/Android.bp
+++ b/services/audiopolicy/tests/Android.bp
@@ -21,6 +21,7 @@
],
shared_libs: [
+ "audiopolicy-aidl-cpp",
"framework-permission-aidl-cpp",
"libaudioclient",
"libaudiofoundation",
@@ -32,6 +33,7 @@
"libhidlbase",
"liblog",
"libmedia_helper",
+ "libstagefright_foundation",
"libutils",
"libxml2",
"server_configurable_flags",
@@ -42,6 +44,7 @@
"audioclient-types-aidl-cpp",
"com.android.media.audio-aconfig-cc",
"com.android.media.audioserver-aconfig-cc",
+ "libaudio_aidl_conversion_common_cpp",
"libaudiopolicycomponents",
"libflagtest",
"libgmock",
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index f8f91fc..3cdf6a1 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -97,13 +97,6 @@
attributionSourceState.token = sp<BBinder>::make();
return attributionSourceState;
}
-
-bool equals(const audio_config_base_t& config1, const audio_config_base_t& config2) {
- return config1.format == config2.format
- && config1.sample_rate == config2.sample_rate
- && config1.channel_mask == config2.channel_mask;
-}
-
} // namespace
TEST(AudioPolicyConfigTest, DefaultConfigForTestsIsEmpty) {
@@ -343,10 +336,14 @@
if (!virtualDeviceId) virtualDeviceId = 0;
AudioPolicyInterface::input_type_t inputType;
AttributionSourceState attributionSource = createAttributionSourceState(/*uid=*/ 0);
- ASSERT_EQ(OK, mManager->getInputForAttr(
- &attr, input, riid, session, attributionSource, &config, flags,
- selectedDeviceId, &inputType, portId, virtualDeviceId));
- ASSERT_NE(AUDIO_PORT_HANDLE_NONE, *portId);
+ auto inputRes = mManager->getInputForAttr(attr, *input, *selectedDeviceId,
+ config, flags, riid, session, attributionSource, &inputType);
+ ASSERT_TRUE(inputRes.has_value());
+ ASSERT_NE(inputRes->portId, AUDIO_PORT_HANDLE_NONE);
+ *input = inputRes->input;
+ if (selectedDeviceId != nullptr) *selectedDeviceId = inputRes->selectedDeviceId;
+ *portId = inputRes->portId;
+ if (virtualDeviceId != nullptr) *virtualDeviceId = inputRes->virtualDeviceId;
}
void AudioPolicyManagerTest::getAudioPorts(audio_port_type_t type, audio_port_role_t role,
@@ -1231,40 +1228,39 @@
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
"", "", AUDIO_FORMAT_DEFAULT));
- audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ const audio_port_handle_t requestedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ const audio_io_handle_t requestedInput = AUDIO_PORT_HANDLE_NONE;
+ const AttributionSourceState attributionSource = createAttributionSourceState(/*uid=*/ 0);
+ AudioPolicyInterface::input_type_t inputType;
+
audio_attributes_t attr = {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
AUDIO_SOURCE_VOICE_COMMUNICATION,AUDIO_FLAG_NONE, ""};
- AudioPolicyInterface::input_type_t inputType;
- audio_io_handle_t input = AUDIO_PORT_HANDLE_NONE;
- AttributionSourceState attributionSource = createAttributionSourceState(/*uid=*/ 0);
audio_config_base_t requestedConfig = {
.sample_rate = k48000SamplingRate,
.channel_mask = AUDIO_CHANNEL_IN_STEREO,
.format = AUDIO_FORMAT_PCM_16_BIT,
};
- audio_config_base_t config = requestedConfig;
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
- uint32_t *virtualDeviceId = 0;
- ASSERT_EQ(OK, mManager->getInputForAttr(
- &attr, &input, 1 /*riid*/, AUDIO_SESSION_NONE, attributionSource, &config,
- AUDIO_INPUT_FLAG_NONE,
- &selectedDeviceId, &inputType, &portId, virtualDeviceId));
- ASSERT_NE(AUDIO_PORT_HANDLE_NONE, portId);
- ASSERT_TRUE(equals(requestedConfig, config));
+ auto inputRes = mManager->getInputForAttr(attr, requestedInput, requestedDeviceId,
+ requestedConfig, AUDIO_INPUT_FLAG_NONE, 1 /*riid*/,
+ AUDIO_SESSION_NONE, attributionSource, &inputType);
+ ASSERT_TRUE(inputRes.has_value());
+ ASSERT_NE(inputRes->portId, AUDIO_PORT_HANDLE_NONE);
+ ASSERT_EQ(VALUE_OR_FATAL(legacy2aidl_audio_config_base_t_AudioConfigBase(
+ requestedConfig, true /* isInput */)),
+ inputRes->config);
attr = {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
AUDIO_SOURCE_VOICE_COMMUNICATION, AUDIO_FLAG_NONE, ""};
requestedConfig.channel_mask = deviceChannelMask;
- config = requestedConfig;
- selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
- input = AUDIO_PORT_HANDLE_NONE;
- portId = AUDIO_PORT_HANDLE_NONE;
- ASSERT_EQ(OK, mManager->getInputForAttr(
- &attr, &input, 1 /*riid*/, AUDIO_SESSION_NONE, attributionSource, &config,
- AUDIO_INPUT_FLAG_NONE,
- &selectedDeviceId, &inputType, &portId, virtualDeviceId));
- ASSERT_NE(AUDIO_PORT_HANDLE_NONE, portId);
- ASSERT_TRUE(equals(requestedConfig, config));
+
+ inputRes = mManager->getInputForAttr(attr, requestedInput, requestedDeviceId, requestedConfig,
+ AUDIO_INPUT_FLAG_NONE, 1 /*riid*/, AUDIO_SESSION_NONE,
+ attributionSource, &inputType);
+ ASSERT_TRUE(inputRes.has_value());
+ ASSERT_NE(inputRes->portId, AUDIO_PORT_HANDLE_NONE);
+ ASSERT_EQ(VALUE_OR_FATAL(legacy2aidl_audio_config_base_t_AudioConfigBase(requestedConfig,
+ true /* isInput */)),
+ inputRes->config);
ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(AUDIO_DEVICE_IN_USB_DEVICE,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,