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

Commit fca8d2fa authored by Eric Laurent's avatar Eric Laurent Committed by Android (Google) Code Review
Browse files

Merge changes I84209b8e,I14b1ec24 into main

* changes:
  audiopolicy: fix audioflinger patch release while using SwBridge
  AudioPolicyManager: voice call routing fail safe
parents 2ebf4a61 150fcc6f
Loading
Loading
Loading
Loading
+50 −9
Original line number Diff line number Diff line
@@ -412,7 +412,23 @@ status_t PatchPanel::createAudioPatch_l(const struct audio_patch* patch,
                mAfPatchPanelCallback->updateOutDevicesForRecordThreads_l(devices);
            }

            // For endpoint patches, we do not need to re-evaluate the device effect state
            // if the same HAL patch is reused (see calls to mAfPatchPanelCallback below)
            if (endpointPatch) {
                for (auto& p : mPatches) {
                    // end point patches are skipped so we do not compare against this patch
                    if (!p.second.mIsEndpointPatch && patchesHaveSameRoute(
                            newPatch.mAudioPatch, p.second.mAudioPatch)) {
                        ALOGV("%s() Sw Bridge endpoint reusing halHandle=%d", __func__,
                              p.second.mHalHandle);
                        halHandle = p.second.mHalHandle;
                        reuseExistingHalPatch = true;
                        break;
                    }
                }
            }
            mAfPatchPanelCallback->mutex().unlock();

            status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
            mAfPatchPanelCallback->mutex().lock();
            if (status == NO_ERROR) {
@@ -442,11 +458,18 @@ exit:
        *handle = static_cast<audio_patch_handle_t>(
                mAfPatchPanelCallback->nextUniqueId(AUDIO_UNIQUE_ID_USE_PATCH));
        newPatch.mHalHandle = halHandle;
        // Skip device effect:
        //  -for sw bridge as effect are likely held by endpoint patches
        //  -for endpoint reusing a HalPatch handle
        if (!(newPatch.isSoftware()
                || (endpointPatch && reuseExistingHalPatch))) {
            if (reuseExistingHalPatch) {
                mAfPatchPanelCallback->getPatchCommandThread()->updateAudioPatch(
                        oldhandle, *handle, newPatch);
            } else {
            mAfPatchPanelCallback->getPatchCommandThread()->createAudioPatch(*handle, newPatch);
                 mAfPatchPanelCallback->getPatchCommandThread()->createAudioPatch(
                        *handle, newPatch);
            }
        }
        if (insertedModule != AUDIO_MODULE_HANDLE_NONE) {
            addSoftwarePatchToInsertedModules_l(insertedModule, *handle, &newPatch.mAudioPatch);
@@ -734,12 +757,14 @@ status_t PatchPanel::releaseAudioPatch_l(audio_patch_handle_t handle)
 {
    ALOGV("%s handle %d", __func__, handle);
    status_t status = NO_ERROR;
    bool doReleasePatch = true;

    auto iter = mPatches.find(handle);
    if (iter == mPatches.end()) {
        return BAD_VALUE;
    }
    Patch &removedPatch = iter->second;
    const bool isSwBridge = removedPatch.isSoftware();
    const struct audio_patch &patch = removedPatch.mAudioPatch;

    const struct audio_port_config &src = patch.sources[0];
@@ -791,15 +816,31 @@ status_t PatchPanel::releaseAudioPatch_l(audio_patch_handle_t handle)
                    break;
                }
            }
            // Check whether the removed patch Hal Handle is used in another non-Endpoint patch.
            // Since this is a non-Endpoint patch, the removed patch is not considered (it is
            // removed later from mPatches).
            if (removedPatch.mIsEndpointPatch) {
                for (auto& p: mPatches) {
                    if (!p.second.mIsEndpointPatch
                            && p.second.mHalHandle == removedPatch.mHalHandle) {
                        ALOGV("%s() Sw Bridge endpoint used existing halHandle=%d, do not release",
                              __func__,  p.second.mHalHandle);
                        doReleasePatch = false;
                        break;
                    }
                }
            }
            if (doReleasePatch) {
                mAfPatchPanelCallback->mutex().unlock();
                status = thread->sendReleaseAudioPatchConfigEvent(removedPatch.mHalHandle);
                mAfPatchPanelCallback->mutex().lock();
            }
        } break;
        default:
            status = BAD_VALUE;
    }

    erasePatch(handle);
    erasePatch(handle, /* reuseExistingHalPatch= */ !doReleasePatch || isSwBridge);
    return status;
}

+29 −21
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);
        }
    }
@@ -5250,14 +5258,9 @@ status_t AudioPolicyManager::releaseAudioPatchInternal(audio_patch_handle_t hand
                return NO_ERROR;
            }
            patchHandle = outputDesc->getPatchHandle();
            // When a Sw bridge is released, the mixer used by this bridge will release its
            // patch at AudioFlinger side. Hence, the mixer audio patch must be recreated
            // Reuse patch handle to force audio flinger removing initial mixer patch removal
            // updating hal patch handle (prevent leaks).
            // While using a HwBridge, force reconsidering device only if not reusing an existing
            // output and no more activity on output (will force to close).
            bool force = sourceDesc->useSwBridge() ||
                    (sourceDesc->canCloseOutput() && !outputDesc->isActive());
            const bool force = sourceDesc->canCloseOutput() && !outputDesc->isActive();
            // APM pattern is to have always outputs opened / patch realized for reachable devices.
            // Update device may result to NONE (empty), coupled with force, it releases the patch.
            // Reconsider device only for cases:
@@ -6280,6 +6283,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 +7118,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 +7154,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 +8449,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;