Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 25fbcf21 authored by Atneya Nair's avatar Atneya Nair
Browse files

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
parent 89ff0436
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@ parcelable GetInputForAttrResponse {
    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;
}
+22 −11
Original line number Diff line number Diff line
@@ -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 @@ public:
    // 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.
+7 −6
Original line number Diff line number Diff line
@@ -286,7 +286,7 @@ bool AudioPolicyManagerFuzzer::getOutputForAttr(
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 @@ bool AudioPolicyManagerFuzzer::getInputForAttr(
    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;
+1 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ cc_library_shared {
        // 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",
+137 −148
Original line number Diff line number Diff line
@@ -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::AudioMMapPolicyInfo;
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 @@ bool AudioPolicyManager::releaseOutput(audio_port_handle_t portId)
    return false;
}

status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr,
                                             audio_io_handle_t *input,
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,
                                             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)
{
    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,39 +2993,37 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr,
                    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;
        ALOGV("%s reusing MMAP input %d for session %d", __FUNCTION__, requestedInput, session);
        // TODO perm check
    } else {
        *inputType = API_INPUT_INVALID;

        if (attributes.source == AUDIO_SOURCE_REMOTE_SUBMIX &&
                extractAddressFromAudioAttributes(attributes).has_value()) {
        status = mPolicyMixes.getInputMixForAttr(attributes, &policyMix);
            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());
            goto error;
                return base::unexpected {aidl_utils::binderStatusFromStatusT(status)};
            }
            device = mAvailableInputDevices.getDevice(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
                                                  String8(attr->tags + strlen("addr=")),
                                                      String8(attributes.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;
                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)) {
@@ -3037,9 +3031,8 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr,
            } else {
                *inputType = API_INPUT_MIX_EXT_POLICY_REROUTE;
            }
        if (virtualDeviceId) {
            *virtualDeviceId = policyMix->mVirtualDeviceId;
        }
            // TODO is this correct?
            vdi = policyMix->mVirtualDeviceId;
        } else {
            if (explicitRoutingDevice != nullptr) {
                device = explicitRoutingDevice;
@@ -3051,9 +3044,10 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr,
                    __FUNCTION__, device->type());
            }
            if (device == nullptr) {
            ALOGW("getInputForAttr() could not find device for source %d", attributes.source);
            status = BAD_VALUE;
            goto error;
                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;
@@ -3063,10 +3057,7 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr,
                // 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;
            }
                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) {
@@ -3074,69 +3065,67 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr,
            } else {
                *inputType = API_INPUT_LEGACY;
            }

        }

    *input = getInputForDevice(device, session, attributes, config, flags, policyMix);
    if (*input == AUDIO_IO_HANDLE_NONE) {
        status = INVALID_OPERATION;
        // 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();
                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();
                        (sampleRates.find(config.sample_rate) == sampleRates.end())) {
                    config.sample_rate = *sampleRates.begin();
                }
            config->format = profiles[0]->getFormat();
                config.format = profiles[0]->getFormat();
            }
        goto error;
            const auto suggestedConfig = VALUE_OR_FATAL(
                legacy2aidl_audio_config_base_t_AudioConfigBase(config, true /*isInput*/));
            return base::unexpected {suggestedConfig};
        }


    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_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)
{
                                                        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 @@ audio_io_handle_t AudioPolicyManager::getInputForDevice(const sp<DeviceDescripto
            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 @@ audio_io_handle_t AudioPolicyManager::getInputForDevice(const sp<DeviceDescripto
    }

    // 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 @@ audio_io_handle_t AudioPolicyManager::getInputForDevice(const sp<DeviceDescripto
    }

    // 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;
    }
Loading