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

Commit d00c4607 authored by Hongwei Wang's avatar Hongwei Wang Committed by Android (Google) Code Review
Browse files

Merge "In favor of SW patch in AudioPolicyManager::connectAudioSource"

parents 61cf6c17 bb93dfb7
Loading
Loading
Loading
Loading
+101 −52
Original line number Diff line number Diff line
@@ -780,17 +780,39 @@ audio_io_handle_t AudioPolicyManager::getOutput(audio_stream_type_t stream)
    return output;
}

status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
status_t AudioPolicyManager::getAudioAttributes(audio_attributes_t *dstAttr,
                                                const audio_attributes_t *srcAttr,
                                                audio_stream_type_t srcStream)
{
    if (srcAttr != NULL) {
        if (!isValidAttributes(srcAttr)) {
            ALOGE("%s invalid attributes: usage=%d content=%d flags=0x%x tags=[%s]",
                    __func__,
                    srcAttr->usage, srcAttr->content_type, srcAttr->flags,
                    srcAttr->tags);
            return BAD_VALUE;
        }
        *dstAttr = *srcAttr;
    } else {
        if (srcStream < AUDIO_STREAM_MIN || srcStream >= AUDIO_STREAM_PUBLIC_CNT) {
            ALOGE("%s:  invalid stream type", __func__);
            return BAD_VALUE;
        }
        stream_type_to_audio_attributes(srcStream, dstAttr);
    }
    return NO_ERROR;
}

status_t AudioPolicyManager::getOutputForAttrInt(audio_attributes_t *resultAttr,
                                                 audio_io_handle_t *output,
                                                 audio_session_t session,
                                                 const audio_attributes_t *attr,
                                                 audio_stream_type_t *stream,
                                                 uid_t uid,
                                                 const audio_config_t *config,
                                                 audio_output_flags_t *flags,
                                              audio_port_handle_t *selectedDeviceId,
                                              audio_port_handle_t *portId)
                                                 audio_port_handle_t *selectedDeviceId)
{
    audio_attributes_t attributes;
    DeviceVector outputDevices;
    routing_strategy strategy;
    audio_devices_t device;
@@ -798,35 +820,20 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
    audio_devices_t msdDevice =
            getModuleDeviceTypes(mAvailableOutputDevices, AUDIO_HARDWARE_MODULE_ID_MSD);

    // The supplied portId must be AUDIO_PORT_HANDLE_NONE
    if (*portId != AUDIO_PORT_HANDLE_NONE) {
        return INVALID_OPERATION;
    }

    if (attr != NULL) {
        if (!isValidAttributes(attr)) {
            ALOGE("getOutputForAttr() invalid attributes: usage=%d content=%d flags=0x%x tags=[%s]",
                  attr->usage, attr->content_type, attr->flags,
                  attr->tags);
            return BAD_VALUE;
        }
        attributes = *attr;
    } else {
        if (*stream < AUDIO_STREAM_MIN || *stream >= AUDIO_STREAM_PUBLIC_CNT) {
            ALOGE("getOutputForAttr():  invalid stream type");
            return BAD_VALUE;
        }
        stream_type_to_audio_attributes(*stream, &attributes);
    status_t status = getAudioAttributes(resultAttr, attr, *stream);
    if (status != NO_ERROR) {
        return status;
    }

    ALOGV("getOutputForAttr() usage=%d, content=%d, tag=%s flags=%08x"
    ALOGV("%s usage=%d, content=%d, tag=%s flags=%08x"
          " session %d selectedDeviceId %d",
          attributes.usage, attributes.content_type, attributes.tags, attributes.flags,
          __func__,
          resultAttr->usage, resultAttr->content_type, resultAttr->tags, resultAttr->flags,
          session, requestedDeviceId);

    *stream = streamTypefromAttributesInt(&attributes);
    *stream = streamTypefromAttributesInt(resultAttr);

    strategy = getStrategyForAttr(&attributes);
    strategy = getStrategyForAttr(resultAttr);

    // First check for explicit routing (eg. setPreferredDevice)
    if (requestedDeviceId != AUDIO_PORT_HANDLE_NONE) {
@@ -836,30 +843,30 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
    } else {
        // If no explict route, is there a matching dynamic policy that applies?
        sp<SwAudioOutputDescriptor> desc;
        if (mPolicyMixes.getOutputForAttr(attributes, uid, desc) == NO_ERROR) {
        if (mPolicyMixes.getOutputForAttr(*resultAttr, uid, desc) == NO_ERROR) {
            ALOG_ASSERT(desc != 0, "Invalid desc returned by getOutputForAttr");
            if (!audio_has_proportional_frames(config->format)) {
                return BAD_VALUE;
            }
            *stream = streamTypefromAttributesInt(&attributes);
            *stream = streamTypefromAttributesInt(resultAttr);
            *output = desc->mIoHandle;
            AudioMix *mix = desc->mPolicyMix;
            sp<DeviceDescriptor> deviceDesc =
                mAvailableOutputDevices.getDevice(mix->mDeviceType, mix->mDeviceAddress);
            *selectedDeviceId = deviceDesc != 0 ? deviceDesc->getId() : AUDIO_PORT_HANDLE_NONE;
            ALOGV("getOutputForAttr() returns output %d", *output);
            goto exit;
            ALOGV("%s returns output %d", __func__, *output);
            return NO_ERROR;
        }

        // Virtual sources must always be dynamicaly or explicitly routed
        if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
            ALOGW("getOutputForAttr() no policy mix found for usage AUDIO_USAGE_VIRTUAL_SOURCE");
        if (resultAttr->usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
            ALOGW("%s no policy mix found for usage AUDIO_USAGE_VIRTUAL_SOURCE", __func__);
            return BAD_VALUE;
        }
        device = getDeviceForStrategy(strategy, false /*fromCache*/);
    }

    if ((attributes.flags & AUDIO_FLAG_HW_AV_SYNC) != 0) {
    if ((resultAttr->flags & AUDIO_FLAG_HW_AV_SYNC) != 0) {
        *flags = (audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
    }

@@ -869,7 +876,7 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
    // to getOutputForDevice.
    // TODO: Remove check of AUDIO_STREAM_MUSIC once migration is completed on the app side.
    if (device == AUDIO_DEVICE_OUT_TELEPHONY_TX &&
        (*stream == AUDIO_STREAM_MUSIC || attributes.usage == AUDIO_USAGE_VOICE_COMMUNICATION) &&
        (*stream == AUDIO_STREAM_MUSIC || resultAttr->usage == AUDIO_USAGE_VOICE_COMMUNICATION) &&
        audio_is_linear_pcm(config->format) &&
        isInCall()) {
        if (requestedDeviceId != AUDIO_PORT_HANDLE_NONE) {
@@ -880,9 +887,9 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
        }
    }

    ALOGV("getOutputForAttr() device 0x%x, sampling rate %d, format %#x, channel mask %#x, "
    ALOGV("%s device 0x%x, sampling rate %d, format %#x, channel mask %#x, "
          "flags %#x",
          device, config->sample_rate, config->format, config->channel_mask, *flags);
          __func__, device, config->sample_rate, config->format, config->channel_mask, *flags);

    *output = AUDIO_IO_HANDLE_NONE;
    if (msdDevice != AUDIO_DEVICE_NONE) {
@@ -906,22 +913,48 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
    *selectedDeviceId = outputDevices.size() > 0 ? outputDevices.itemAt(0)->getId()
            : AUDIO_PORT_HANDLE_NONE;

exit:
    ALOGV("%s returns output %d selectedDeviceId %d", __func__, *output, *selectedDeviceId);

    return NO_ERROR;
}

status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
                                              audio_io_handle_t *output,
                                              audio_session_t session,
                                              audio_stream_type_t *stream,
                                              uid_t uid,
                                              const audio_config_t *config,
                                              audio_output_flags_t *flags,
                                              audio_port_handle_t *selectedDeviceId,
                                              audio_port_handle_t *portId)
{
    // The supplied portId must be AUDIO_PORT_HANDLE_NONE
    if (*portId != AUDIO_PORT_HANDLE_NONE) {
        return INVALID_OPERATION;
    }
    const audio_port_handle_t requestedDeviceId = *selectedDeviceId;
    audio_attributes_t resultAttr;
    status_t status = getOutputForAttrInt(&resultAttr, output, session, attr, stream, uid,
            config, flags, selectedDeviceId);
    if (status != NO_ERROR) {
        return status;
    }

    audio_config_base_t clientConfig = {.sample_rate = config->sample_rate,
        .format = config->format,
        .channel_mask = config->channel_mask };
    *portId = AudioPort::getNextUniqueId();

    sp<TrackClientDescriptor> clientDesc =
        new TrackClientDescriptor(*portId, uid, session, attributes, clientConfig,
        new TrackClientDescriptor(*portId, uid, session, resultAttr, clientConfig,
                                  requestedDeviceId, *stream,
                                  getStrategyForAttr(&attributes),
                                  getStrategyForAttr(&resultAttr),
                                  *flags);
    sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(*output);
    outputDesc->addClient(clientDesc);

    ALOGV("  getOutputForAttr() returns output %d selectedDeviceId %d for port ID %d",
          *output, *selectedDeviceId, *portId);
    ALOGV("%s returns output %d selectedDeviceId %d for port ID %d",
          __func__, *output, requestedDeviceId, *portId);

    return NO_ERROR;
}
@@ -3400,11 +3433,20 @@ status_t AudioPolicyManager::connectAudioSource(const sp<SourceClientDescriptor>
            srcDeviceDesc->getAudioPort()->mModule->getHalVersionMajor() >= 3 &&
            srcDeviceDesc->getAudioPort()->mGains.size() > 0) {
        ALOGV("%s AUDIO_DEVICE_API_VERSION_3_0", __FUNCTION__);
        // TODO: may explicitly specify whether we should use HW or SW patch
        // create patch between src device and output device
        // create Hwoutput and add to mHwOutputs
    } else {
        SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(sinkDevice, mOutputs);
        audio_io_handle_t output = selectOutput(outputs);
        audio_attributes_t resultAttr;
        audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
        audio_config_t config = AUDIO_CONFIG_INITIALIZER;
        config.sample_rate = sourceDesc->config().sample_rate;
        config.channel_mask = sourceDesc->config().channel_mask;
        config.format = sourceDesc->config().format;
        audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
        audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
        getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE,
                &attributes, &stream, sourceDesc->uid(), &config, &flags, &selectedDeviceId);
        if (output == AUDIO_IO_HANDLE_NONE) {
            ALOGV("%s no output for device %08x", __FUNCTION__, sinkDevice);
            return INVALID_OPERATION;
@@ -3437,6 +3479,13 @@ status_t AudioPolicyManager::connectAudioSource(const sp<SourceClientDescriptor>
                  __FUNCTION__, status);
            return INVALID_OPERATION;
        }

        if (outputDesc->getClient(sourceDesc->portId()) != nullptr) {
            ALOGW("%s source portId has already been attached to outputDesc", __func__);
            return INVALID_OPERATION;
        }
        outputDesc->addClient(sourceDesc);

        uint32_t delayMs = 0;
        status = startSource(outputDesc, sourceDesc, &delayMs);

+15 −0
Original line number Diff line number Diff line
@@ -661,6 +661,21 @@ private:
                const String8& address /*in*/,
                SortedVector<audio_io_handle_t>& outputs /*out*/);
        uint32_t curAudioPortGeneration() const { return mAudioPortGeneration; }
        // internal method, get audio_attributes_t from either a source audio_attributes_t
        // or audio_stream_type_t, respectively.
        status_t getAudioAttributes(audio_attributes_t *dstAttr,
                const audio_attributes_t *srcAttr,
                audio_stream_type_t srcStream);
        // internal method, called by getOutputForAttr() and connectAudioSource.
        status_t getOutputForAttrInt(audio_attributes_t *resultAttr,
                audio_io_handle_t *output,
                audio_session_t session,
                const audio_attributes_t *attr,
                audio_stream_type_t *stream,
                uid_t uid,
                const audio_config_t *config,
                audio_output_flags_t *flags,
                audio_port_handle_t *selectedDeviceId);
        // internal method to return the output handle for the given device and format
        audio_io_handle_t getOutputForDevice(
                audio_devices_t device,