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

Commit db1755bf authored by François Gaffie's avatar François Gaffie Committed by Eric Laurent
Browse files

AudioPolicyManager: voice call routing fail safe



Bug: 298609303
Test: make

When devices involved in a call are disconnected, since APM
does not expect such cases, assertion happens.
This CL allows to fail safe on voice call routing.

Change-Id: I14b1ec245e640eeae14390ea62d93a4bdfe5bade
Signed-off-by: default avatarFrançois Gaffie <francois.gaffie@renault.com>
parent 7e224c8d
Loading
Loading
Loading
Loading
+28 −15
Original line number Diff line number Diff line
@@ -658,7 +658,7 @@ DeviceVector AudioPolicyManager::selectBestRxSinkDevicesForCall(bool fromCache)

status_t AudioPolicyManager::updateCallRouting(bool fromCache, uint32_t delayMs, uint32_t *waitMs)
{
    if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
    if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL) {
        DeviceVector rxDevices = selectBestRxSinkDevicesForCall(fromCache);
        return updateCallRoutingInternal(rxDevices, delayMs, waitMs);
    }
@@ -671,14 +671,21 @@ status_t AudioPolicyManager::updateCallRoutingInternal(
    bool createTxPatch = false;
    bool createRxPatch = false;
    uint32_t muteWaitMs = 0;
    if(!hasPrimaryOutput() ||
    if (hasPrimaryOutput() &&
            mPrimaryOutput->devices().onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_STUB)) {
        return INVALID_OPERATION;
    }
    ALOG_ASSERT(!rxDevices.isEmpty(), "%s() no selected output device", __func__);

    audio_attributes_t attr = { .source = AUDIO_SOURCE_VOICE_COMMUNICATION };
    auto txSourceDevice = mEngine->getInputDeviceForAttributes(attr);

    disconnectTelephonyAudioSource(mCallRxSourceClient);
    disconnectTelephonyAudioSource(mCallTxSourceClient);

    if (rxDevices.isEmpty()) {
        ALOGW("%s() no selected output device", __func__);
        return INVALID_OPERATION;
    }
    if (txSourceDevice == nullptr) {
        ALOGE("%s() selected input device not available", __func__);
        return INVALID_OPERATION;
@@ -687,9 +694,6 @@ status_t AudioPolicyManager::updateCallRoutingInternal(
    ALOGV("%s device rxDevice %s txDevice %s", __func__,
          rxDevices.itemAt(0)->toString().c_str(), txSourceDevice->toString().c_str());

    disconnectTelephonyAudioSource(mCallRxSourceClient);
    disconnectTelephonyAudioSource(mCallTxSourceClient);

    auto telephonyRxModule =
        mHwModules.getModuleForDeviceType(AUDIO_DEVICE_IN_TELEPHONY_RX, AUDIO_FORMAT_DEFAULT);
    auto telephonyTxModule =
@@ -729,6 +733,10 @@ 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 (!hasPrimaryOutput()) {
            ALOGW("%s() no primary output available", __func__);
            return INVALID_OPERATION;
        }
        muteWaitMs = setOutputDevices(__func__, mPrimaryOutput, rxDevices, true, delayMs);
    } else { // create RX path audio patch
        connectTelephonyRxAudioSource();
@@ -875,20 +883,20 @@ void AudioPolicyManager::setPhoneState(audio_mode_t state)
        }
    }

    if (hasPrimaryOutput()) {
    if (state == AUDIO_MODE_IN_CALL) {
        (void)updateCallRouting(false /*fromCache*/, delayMs);
    } else {
        if (oldState == AUDIO_MODE_IN_CALL) {
            disconnectTelephonyAudioSource(mCallRxSourceClient);
            disconnectTelephonyAudioSource(mCallTxSourceClient);
        }
        if (hasPrimaryOutput()) {
            DeviceVector rxDevices = getNewOutputDevices(mPrimaryOutput, false /*fromCache*/);
            // force routing command to audio hardware when ending call
            // even if no device change is needed
            if (isStateInCall(oldState) && rxDevices.isEmpty()) {
                rxDevices = mPrimaryOutput->devices();
            }
            if (oldState == AUDIO_MODE_IN_CALL) {
                disconnectTelephonyAudioSource(mCallRxSourceClient);
                disconnectTelephonyAudioSource(mCallTxSourceClient);
            }
            setOutputDevices(__func__, mPrimaryOutput, rxDevices, force, 0);
        }
    }
@@ -6280,6 +6288,7 @@ void AudioPolicyManager::onNewAudioModulesAvailableInt(DeviceVector *newDevices)
            if (mPrimaryOutput == nullptr &&
                    outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
                mPrimaryOutput = outputDesc;
                mPrimaryModuleHandle = mPrimaryOutput->getModuleHandle();
            }
            if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
                outputDesc->close();
@@ -7114,7 +7123,9 @@ void AudioPolicyManager::checkA2dpSuspend()
DeviceVector AudioPolicyManager::getNewOutputDevices(const sp<SwAudioOutputDescriptor>& outputDesc,
                                                     bool fromCache)
{
    DeviceVector devices;
    if (outputDesc == nullptr) {
        return DeviceVector{};
    }

    ssize_t index = mAudioPatches.indexOfKey(outputDesc->getPatchHandle());
    if (index >= 0) {
@@ -7148,6 +7159,7 @@ DeviceVector AudioPolicyManager::getNewOutputDevices(const sp<SwAudioOutputDescr
        return DeviceVector(device);
    }

    DeviceVector devices;
    for (const auto &productStrategy : mEngine->getOrderedProductStrategies()) {
        StreamTypeVector streams = mEngine->getStreamTypesForProductStrategy(productStrategy);
        auto attr = mEngine->getAllAttributesForProductStrategy(productStrategy).front();
@@ -8442,6 +8454,7 @@ sp<SwAudioOutputDescriptor> AudioPolicyManager::openOutputWithProfileAndDevice(
    if (mPrimaryOutput == nullptr && profile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
        ALOGV("%s(): re-assigning mPrimaryOutput", __func__);
        mPrimaryOutput = desc;
        mPrimaryModuleHandle = mPrimaryOutput->getModuleHandle();
    }
    return desc;
}
+4 −2
Original line number Diff line number Diff line
@@ -820,10 +820,10 @@ protected:

        bool isPrimaryModule(const sp<HwModule> &module) const
        {
            if (module == 0 || !hasPrimaryOutput()) {
            if (module == nullptr || mPrimaryModuleHandle == AUDIO_MODULE_HANDLE_NONE) {
                return false;
            }
            return module->getHandle() == mPrimaryOutput->getModuleHandle();
            return module->getHandle() == mPrimaryModuleHandle;
        }
        DeviceVector availablePrimaryOutputDevices() const
        {
@@ -935,6 +935,8 @@ protected:
        EngineInstance mEngine;                         // Audio Policy Engine instance
        AudioPolicyClientInterface *mpClientInterface;  // audio policy client interface
        sp<SwAudioOutputDescriptor> mPrimaryOutput;     // primary output descriptor
        // mPrimaryModuleHandle is cached mPrimaryOutput->getModuleHandle();
        audio_module_handle_t mPrimaryModuleHandle = AUDIO_MODULE_HANDLE_NONE;
        // list of descriptors for outputs currently opened

        sp<SwAudioOutputDescriptor> mSpatializerOutput;