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

Commit 51c9ccd1 authored by Francois Gaffie's avatar Francois Gaffie Committed by Eric Laurent
Browse files

AudioPolicyManager: keep track of activity for HW Audio Patches



In order to allow volume management for all volume sources, this
CL adds Source Clients even in case of HW AudioPatches.
It uses the mixPort declared to reach the sink involved in the
HW Audio Patch to add this client.

Test: Manual: build & call & plays with HW / SW AudioBridges.
Auto: (Non-regression on emulator)
adb shell ./data/AudioPolicyEmulatorTests --gtest_filter=*AudioPatchTest*
adb shell ./data/AudioPolicyEmulatorTests --gtest_filter=*AudioSourceTest*

Signed-off-by: default avatarFrancois Gaffie <francois.gaffie@renault.com>
Change-Id: Iaf44db2fd9a90dde9ef8160869af73983a5feae4
parent bce7cd48
Loading
Loading
Loading
Loading
+71 −48
Original line number Diff line number Diff line
@@ -568,11 +568,7 @@ uint32_t AudioPolicyManager::updateCallRouting(const DeviceVector &rxDevices, ui
    ALOGV("updateCallRouting device rxDevice %s txDevice %s",
          rxDevices.itemAt(0)->toString().c_str(), txSourceDevice->toString().c_str());

    // release existing RX patch if any
    if (mCallRxPatch != 0) {
        releaseAudioPatchInternal(mCallRxPatch->getHandle());
        mCallRxPatch.clear();
    }
    disconnectTelephonyRxAudioSource();
    // release TX patch if any
    if (mCallTxPatch != 0) {
        releaseAudioPatchInternal(mCallTxPatch->getHandle());
@@ -620,8 +616,7 @@ uint32_t AudioPolicyManager::updateCallRouting(const DeviceVector &rxDevices, ui
    if (!createRxPatch) {
        muteWaitMs = setOutputDevices(mPrimaryOutput, rxDevices, true, delayMs);
    } else { // create RX path audio patch
        mCallRxPatch = createTelephonyPatch(true /*isRx*/, rxDevices.itemAt(0), delayMs);

        connectTelephonyRxAudioSource();
        // If the TX device is on the primary HW module but RX device is
        // on other HW module, SinkMetaData of telephony input should handle it
        // assuming the device uses audio HAL V5.0 and above
@@ -684,6 +679,24 @@ bool AudioPolicyManager::isDeviceOfModule(
    return false;
}

void AudioPolicyManager::connectTelephonyRxAudioSource()
{
    disconnectTelephonyRxAudioSource();
    const struct audio_port_config source = {
        .role = AUDIO_PORT_ROLE_SOURCE, .type = AUDIO_PORT_TYPE_DEVICE,
        .ext.device.type = AUDIO_DEVICE_IN_TELEPHONY_RX, .ext.device.address = ""
    };
    const auto aa = mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL);
    status_t status = startAudioSource(&source, &aa, &mCallRxSourceClientPort, 0/*uid*/);
    ALOGE_IF(status != NO_ERROR, "%s failed to start Telephony Rx AudioSource", __func__);
}

void AudioPolicyManager::disconnectTelephonyRxAudioSource()
{
    stopAudioSource(mCallRxSourceClientPort);
    mCallRxSourceClientPort = AUDIO_PORT_HANDLE_NONE;
}

void AudioPolicyManager::setPhoneState(audio_mode_t state)
{
    ALOGV("setPhoneState() state %d", state);
@@ -751,10 +764,7 @@ void AudioPolicyManager::setPhoneState(audio_mode_t state)
        if (state == AUDIO_MODE_IN_CALL) {
            updateCallRouting(rxDevices, delayMs);
        } else if (oldState == AUDIO_MODE_IN_CALL) {
            if (mCallRxPatch != 0) {
                releaseAudioPatchInternal(mCallRxPatch->getHandle());
                mCallRxPatch.clear();
            }
            disconnectTelephonyRxAudioSource();
            if (mCallTxPatch != 0) {
                releaseAudioPatchInternal(mCallTxPatch->getHandle());
                mCallTxPatch.clear();
@@ -3863,22 +3873,12 @@ status_t AudioPolicyManager::createAudioPatchInternal(const struct audio_patch *
                sinkDevice->toAudioPortConfig(&sinkPortConfig, &patch->sinks[i]);
                patchBuilder.addSink(sinkPortConfig);

                // create a software bridge in PatchPanel if:
                // - source and sink devices are on different HW modules OR
                // - audio HAL version is < 3.0
                // - audio HAL version is >= 3.0 but no route has been declared between devices
                // - called from startAudioSource (aka sourceDesc != nullptr) and source device does
                //   not have a gain controller
                if (!srcDevice->hasSameHwModuleAs(sinkDevice) ||
                        (srcDevice->getModuleVersionMajor() < 3) ||
                        !srcDevice->getModule()->supportsPatch(srcDevice, sinkDevice) ||
                        (sourceDesc != nullptr &&
                         srcDevice->getAudioPort()->getGains().size() == 0)) {
                    // support only one sink device for now to simplify output selection logic
                    if (patch->num_sinks > 1) {
                        return INVALID_OPERATION;
                    }
                // Whatever Sw or Hw bridge, we do attach an SwOutput to an Audio Source for
                // volume management purpose (tracking activity)
                // In case of Hw bridge, it is a Work Around. The mixPort used is the one declared
                // in config XML to reach the sink so that is can be declared as available.
                audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
                sp<SwAudioOutputDescriptor> outputDesc = nullptr;
                if (sourceDesc != nullptr) {
                    // take care of dynamic routing for SwOutput selection,
                    audio_attributes_t attributes = sourceDesc->attributes();
@@ -3901,26 +3901,47 @@ status_t AudioPolicyManager::createAudioPatchInternal(const struct audio_patch *
                              __FUNCTION__, sinkDevice->toString().c_str());
                        return INVALID_OPERATION;
                    }
                    } else {
                    outputDesc = mOutputs.valueFor(output);
                    if (outputDesc->isDuplicated()) {
                        ALOGE("%s output is duplicated", __func__);
                        return INVALID_OPERATION;
                    }
                    sourceDesc->setSwOutput(outputDesc);
                }
                // create a software bridge in PatchPanel if:
                // - source and sink devices are on different HW modules OR
                // - audio HAL version is < 3.0
                // - audio HAL version is >= 3.0 but no route has been declared between devices
                // - called from startAudioSource (aka sourceDesc != nullptr) and source device does
                //   not have a gain controller
                if (!srcDevice->hasSameHwModuleAs(sinkDevice) ||
                        (srcDevice->getModuleVersionMajor() < 3) ||
                        !srcDevice->getModule()->supportsPatch(srcDevice, sinkDevice) ||
                        (sourceDesc != nullptr &&
                         srcDevice->getAudioPort()->getGains().size() == 0)) {
                    // support only one sink device for now to simplify output selection logic
                    if (patch->num_sinks > 1) {
                        return INVALID_OPERATION;
                    }
                    if (sourceDesc == nullptr) {
                        SortedVector<audio_io_handle_t> outputs =
                                getOutputsForDevices(DeviceVector(sinkDevice), mOutputs);
                        // if the sink device is reachable via an opened output stream, request to
                        // go via this output stream by adding a second source to the patch
                        // description
                        output = selectOutput(outputs);
                    }
                        if (output != AUDIO_IO_HANDLE_NONE) {
                        sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
                            outputDesc = mOutputs.valueFor(output);
                            if (outputDesc->isDuplicated()) {
                                ALOGV("%s output for device %s is duplicated",
                                      __FUNCTION__, sinkDevice->toString().c_str());
                                return INVALID_OPERATION;
                            }
                        }
                    }
                    if (outputDesc != nullptr) {
                        audio_port_config srcMixPortConfig = {};
                        outputDesc->toAudioPortConfig(&srcMixPortConfig, &patch->sources[0]);
                        if (sourceDesc != nullptr) {
                            sourceDesc->setSwOutput(outputDesc);
                        }
                        // for volume control, we may need a valid stream
                        srcMixPortConfig.ext.mix.usecase.stream = sourceDesc != nullptr ?
                                    sourceDesc->stream() : AUDIO_STREAM_PATCH;
@@ -5382,7 +5403,8 @@ void AudioPolicyManager::checkAudioSourceForAttributes(const audio_attributes_t
    for (size_t i = 0; i < mAudioSources.size(); i++)  {
        sp<SourceClientDescriptor> sourceDesc = mAudioSources.valueAt(i);
        if (sourceDesc != nullptr && followsSameRouting(attr, sourceDesc->attributes())
                && sourceDesc->getPatchHandle() == AUDIO_PATCH_HANDLE_NONE) {
                && sourceDesc->getPatchHandle() == AUDIO_PATCH_HANDLE_NONE
                && !isCallRxAudioSource(sourceDesc)) {
            connectAudioSource(sourceDesc);
        }
    }
@@ -5495,7 +5517,7 @@ void AudioPolicyManager::checkOutputForAttributes(const audio_attributes_t &attr
                                newDevices.types());
            }
            sp<SourceClientDescriptor> source = getSourceForAttributesOnOutput(srcOut, attr);
            if (source != nullptr) {
            if (source != nullptr && !isCallRxAudioSource(source)) {
                connectAudioSource(source);
            }
        }
@@ -6491,7 +6513,8 @@ void AudioPolicyManager::cleanUpForDevice(const sp<DeviceDescriptor>& deviceDesc
    for (ssize_t i = (ssize_t)mAudioSources.size() - 1; i >= 0; i--)  {
        sp<SourceClientDescriptor> sourceDesc = mAudioSources.valueAt(i);
        if (sourceDesc->isConnected() && (sourceDesc->srcDevice()->equals(deviceDesc) ||
                                          sourceDesc->sinkDevice()->equals(deviceDesc))) {
                                          sourceDesc->sinkDevice()->equals(deviceDesc))
                && !isCallRxAudioSource(sourceDesc)) {
            disconnectAudioSource(sourceDesc);
        }
    }
+13 −1
Original line number Diff line number Diff line
@@ -556,6 +556,15 @@ protected:
         */
        void updateCallAndOutputRouting(bool forceVolumeReeval = true, uint32_t delayMs = 0);

        bool isCallRxAudioSource(const sp<SourceClientDescriptor> &source) {
            return mCallRxSourceClientPort != AUDIO_PORT_HANDLE_NONE
                && source == mAudioSources.valueFor(mCallRxSourceClientPort);
        }

        void connectTelephonyRxAudioSource();

        void disconnectTelephonyRxAudioSource();

        /**
         * @brief updates routing for all inputs.
         */
@@ -797,7 +806,6 @@ protected:
        SoundTriggerSessionCollection mSoundTriggerSessions;

        sp<AudioPatch> mCallTxPatch;
        sp<AudioPatch> mCallRxPatch;

        HwAudioOutputCollection mHwOutputs;
        SourceClientCollection mAudioSources;
@@ -836,6 +844,10 @@ protected:
        // Cached product strategy ID corresponding to legacy strategy STRATEGY_PHONE
        product_strategy_t mCommunnicationStrategy;

        // The port handle of the hardware audio source created internally for the Call RX audio
        // end point.
        audio_port_handle_t mCallRxSourceClientPort = AUDIO_PORT_HANDLE_NONE;

private:
        void onNewAudioModulesAvailableInt(DeviceVector *newDevices);