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

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

AudioPolicy: remove devices while Sw bridge established



When devices are disconnected while involved in a SwBridge,
the connectAudioSource function may be called while the cache
of the engine has not yet been updated with availability of devices.

This CL forces to retrieve sinkDevices from engine without using
the cache.

It also ensures that Audio Source using Direct Output are also
re routed while sink device has been made UNAVAILABLE then AVAILABLE
again. In this case, no SwOutput will keep track of the AudioSource.
Orphans Audio Source shall be handled independantly.

So far, robustness cases added to the following test.
In some case, fallback on speaker is allowed, in other,
device none is selected while given sink has been made unavailable:

Test: So far: adb shell /data/nativetest64/AudioPolicyEmulatorTests/AudioPolicyEmulatorTests --gtest_filter=AudioPatchTest/AudioModeBridgingTest.
adb shell /data/nativetest64/AudioPolicyEmulatorTests/AudioPolicyEmulatorTests --gtest_filter=AudioSourceTest/AudioSourceBridgingTest.UsingAudioSourceAPI/

Signed-off-by: default avatarFrancois Gaffie <francois.gaffie@renault.com>
Change-Id: I2663d10f08de3191de4d95bc81749ede9b8a360f
parent 89a23220
Loading
Loading
Loading
Loading
+30 −4
Original line number Diff line number Diff line
@@ -246,6 +246,7 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescript
                    if ((state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) ||
                            (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) &&
                                (desc->mDirectOpenCount == 0))) {
                        clearAudioSourcesForOutput(output);
                        closeOutput(output);
                    }
                }
@@ -4006,8 +4007,9 @@ status_t AudioPolicyManager::releaseAudioPatchInternal(audio_patch_handle_t hand
                sp<SwAudioOutputDescriptor> outputDesc =
                        mOutputs.getOutputFromId(patch->sources[1].id);
                if (outputDesc == NULL) {
                    ALOGE("%s output not found for id %d", __func__, patch->sources[0].id);
                    return BAD_VALUE;
                    ALOGW("%s output not found for id %d", __func__, patch->sources[0].id);
                    // releaseOutput has already called closeOuput in case of direct output
                    return NO_ERROR;
                }
                if (patchDesc->getHandle() != outputDesc->getPatchHandle()) {
                    // force SwOutput patch removal as AF counter part patch has already gone.
@@ -4271,12 +4273,13 @@ status_t AudioPolicyManager::connectAudioSource(const sp<SourceClientDescriptor>

    // make sure we only have one patch per source.
    disconnectAudioSource(sourceDesc);
    sourceDesc->setPatchHandle(AUDIO_PATCH_HANDLE_NONE);

    audio_attributes_t attributes = sourceDesc->attributes();
    sp<DeviceDescriptor> srcDevice = sourceDesc->srcDevice();

    DeviceVector sinkDevices =
            mEngine->getOutputDevicesForAttributes(attributes, nullptr, true);
            mEngine->getOutputDevicesForAttributes(attributes, nullptr, false /*fromCache*/);
    ALOG_ASSERT(!sinkDevices.isEmpty(), "connectAudioSource(): no device found for attributes");
    sp<DeviceDescriptor> sinkDevice = sinkDevices.itemAt(0);
    ALOG_ASSERT(mAvailableOutputDevices.contains(sinkDevice), "%s: Device %s not available",
@@ -5360,6 +5363,28 @@ bool AudioPolicyManager::followsSameRouting(const audio_attributes_t &lAttr,
            mEngine->getProductStrategyForAttributes(rAttr);
}

void AudioPolicyManager::checkAudioSourceForAttributes(const audio_attributes_t &attr)
{
    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) {
            connectAudioSource(sourceDesc);
        }
    }
}

void AudioPolicyManager::clearAudioSourcesForOutput(audio_io_handle_t output)
{
    for (size_t i = 0; i < mAudioSources.size(); i++)  {
        sp<SourceClientDescriptor> sourceDesc = mAudioSources.valueAt(i);
        if (sourceDesc != nullptr && sourceDesc->swOutput().promote() != nullptr
                && sourceDesc->swOutput().promote()->mIoHandle == output) {
            disconnectAudioSource(sourceDesc);
        }
    }
}

void AudioPolicyManager::checkOutputForAttributes(const audio_attributes_t &attr)
{
    auto psId = mEngine->getProductStrategyForAttributes(attr);
@@ -5456,7 +5481,7 @@ void AudioPolicyManager::checkOutputForAttributes(const audio_attributes_t &attr
                                newDevices.types());
            }
            sp<SourceClientDescriptor> source = getSourceForAttributesOnOutput(srcOut, attr);
            if (source != 0){
            if (source != nullptr) {
                connectAudioSource(source);
            }
        }
@@ -5479,6 +5504,7 @@ void AudioPolicyManager::checkOutputForAllStrategies()
    for (const auto &strategy : mEngine->getOrderedProductStrategies()) {
        auto attributes = mEngine->getAllAttributesForProductStrategy(strategy).front();
        checkOutputForAttributes(attributes);
        checkAudioSourceForAttributes(attributes);
    }
}

+11 −0
Original line number Diff line number Diff line
@@ -571,6 +571,16 @@ protected:
         */
        void checkOutputForAttributes(const audio_attributes_t &attr);

        /**
         * @brief checkAudioSourceForAttributes checks if any AudioSource following the same routing
         * as the given audio attributes is not routed and try to connect it.
         * It must be called once checkOutputForAttributes has been called for orphans AudioSource,
         * aka AudioSource not attached to any Audio Output (e.g. AudioSource connected to direct
         * Output which has been disconnected (and output closed) due to sink device unavailable).
         * @param attr to be considered
         */
        void checkAudioSourceForAttributes(const audio_attributes_t &attr);

        bool followsSameRouting(const audio_attributes_t &lAttr,
                                const audio_attributes_t &rAttr) const;

@@ -740,6 +750,7 @@ protected:

        sp<SourceClientDescriptor> getSourceForAttributesOnOutput(audio_io_handle_t output,
                                                                  const audio_attributes_t &attr);
        void clearAudioSourcesForOutput(audio_io_handle_t output);

        void cleanUpForDevice(const sp<DeviceDescriptor>& deviceDesc);