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

Commit b2fb410a authored by Eric Laurent's avatar Eric Laurent
Browse files

audio policy: fix redundant call routing

Do not teardown and re-create the call RX and RX audio sources
if call routing remains unchanged.

Bug: 292492229
Flag: com.android.media.audioserver.fix_call_audio_patch
Test: make
Change-Id: Ia6fca5cb9776dae4e5942e99f1490550aba42dc4
parent 83cea7c0
Loading
Loading
Loading
Loading
+49 −8
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ using android::media::audio::common::AudioDevice;
using android::media::audio::common::AudioDeviceAddress;
using android::media::audio::common::AudioPortDeviceExt;
using android::media::audio::common::AudioPortExt;
using com::android::media::audioserver::fix_call_audio_patch;
using content::AttributionSourceState;

//FIXME: workaround for truncated touch sounds
@@ -704,8 +705,10 @@ status_t AudioPolicyManager::updateCallRoutingInternal(
    audio_attributes_t attr = { .source = AUDIO_SOURCE_VOICE_COMMUNICATION };
    auto txSourceDevice = mEngine->getInputDeviceForAttributes(attr);

    if (!fix_call_audio_patch()) {
        disconnectTelephonyAudioSource(mCallRxSourceClient);
        disconnectTelephonyAudioSource(mCallTxSourceClient);
    }

    if (rxDevices.isEmpty()) {
        ALOGW("%s() no selected output device", __func__);
@@ -758,6 +761,9 @@ status_t AudioPolicyManager::updateCallRoutingInternal(
    // Use legacy routing method for voice calls via setOutputDevice() on primary output.
    // Otherwise, create two audio patches for TX and RX path.
    if (!createRxPatch) {
        if (fix_call_audio_patch()) {
            disconnectTelephonyAudioSource(mCallRxSourceClient);
        }
        if (!hasPrimaryOutput()) {
            ALOGW("%s() no primary output available", __func__);
            return INVALID_OPERATION;
@@ -780,6 +786,8 @@ status_t AudioPolicyManager::updateCallRoutingInternal(
            }
        }
        connectTelephonyTxAudioSource(txSourceDevice, txSinkDevice, delayMs);
    } else if (fix_call_audio_patch()) {
        disconnectTelephonyAudioSource(mCallTxSourceClient);
    }
    if (waitMs != nullptr) {
        *waitMs = muteWaitMs;
@@ -801,18 +809,38 @@ bool AudioPolicyManager::isDeviceOfModule(

void AudioPolicyManager::connectTelephonyRxAudioSource()
{
    const auto aa = mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL);

    if (fix_call_audio_patch()) {
        if (mCallRxSourceClient != nullptr) {
            DeviceVector rxDevices =
                  mEngine->getOutputDevicesForAttributes(aa, nullptr, false /*fromCache*/);
            ALOG_ASSERT(!rxDevices.isEmpty() || !mCallRxSourceClient->isConnected(),
                        "connectTelephonyRxAudioSource(): no device found for call RX source");
            sp<DeviceDescriptor> rxDevice = rxDevices.itemAt(0);
            if (mCallRxSourceClient->isConnected()
                    && mCallRxSourceClient->sinkDevice()->equals(rxDevice)) {
                return;
            }
            disconnectTelephonyAudioSource(mCallRxSourceClient);
        }
    } else {
        disconnectTelephonyAudioSource(mCallRxSourceClient);
    }

    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);

    audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;

    status_t status = startAudioSourceInternal(&source, &aa, &portId, 0 /*uid*/,
                                       true /*internal*/, true /*isCallRx*/);
    ALOGE_IF(status != OK, "%s: failed to start audio source (%d)", __func__, status);
    mCallRxSourceClient = mAudioSources.valueFor(portId);
    ALOGV("%s portdID %d between source %s and sink %s", __func__, portId,
        mCallRxSourceClient->srcDevice()->toString().c_str(),
        mCallRxSourceClient->sinkDevice()->toString().c_str());
    ALOGE_IF(mCallRxSourceClient == nullptr,
             "%s failed to start Telephony Rx AudioSource", __func__);
}
@@ -831,15 +859,26 @@ void AudioPolicyManager::connectTelephonyTxAudioSource(
        const sp<DeviceDescriptor> &srcDevice, const sp<DeviceDescriptor> &sinkDevice,
        uint32_t delayMs)
{
    disconnectTelephonyAudioSource(mCallTxSourceClient);
    if (srcDevice == nullptr || sinkDevice == nullptr) {
        ALOGW("%s could not create patch, invalid sink and/or source device(s)", __func__);
        return;
    }

    if (fix_call_audio_patch()) {
        if (mCallTxSourceClient != nullptr) {
            if (mCallTxSourceClient->isConnected()
                    && mCallTxSourceClient->srcDevice()->equals(srcDevice)) {
                return;
            }
            disconnectTelephonyAudioSource(mCallTxSourceClient);
        }
    } else {
        disconnectTelephonyAudioSource(mCallTxSourceClient);
    }

    PatchBuilder patchBuilder;
    patchBuilder.addSource(srcDevice).addSink(sinkDevice);
    ALOGV("%s between source %s and sink %s", __func__,
            srcDevice->toString().c_str(), sinkDevice->toString().c_str());

    auto callTxSourceClientPortId = PolicyAudioPort::getNextUniqueId();
    const auto aa = mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL);

@@ -856,6 +895,8 @@ void AudioPolicyManager::connectTelephonyTxAudioSource(
                mCallTxSourceClient, sinkDevice, patchBuilder.patch(), patchHandle, mUidCached,
                delayMs);
    ALOGE_IF(status != NO_ERROR, "%s() error %d creating TX audio patch", __func__, status);
    ALOGV("%s portdID %d between source %s and sink %s", __func__, callTxSourceClientPortId,
        srcDevice->toString().c_str(), sinkDevice->toString().c_str());
    if (status == NO_ERROR) {
        mAudioSources.add(callTxSourceClientPortId, mCallTxSourceClient);
    }