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

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

Merge changes Iaf44db2f,Iae8937ca,I414195a8,I2663d10f

* changes:
  AudioPolicyManager: keep track of activity for HW Audio Patches
  audiopolicy: Primary Output runtime management
  audio policy: audio source automatic re-connection
  AudioPolicy: remove devices while Sw bridge established
parents d9c6eb11 51c9ccd1
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -198,10 +198,18 @@ public:

    ~SourceClientDescriptor() override = default;

    void connect(audio_patch_handle_t patchHandle, const sp<DeviceDescriptor>& sinkDevice) {
        mPatchHandle = patchHandle;
        mSinkDevice = sinkDevice;
    }
    void disconnect() {
        mPatchHandle = AUDIO_PATCH_HANDLE_NONE;
        mSinkDevice = nullptr;
    }
    bool isConnected() const { return mPatchHandle != AUDIO_PATCH_HANDLE_NONE; }
    audio_patch_handle_t getPatchHandle() const { return mPatchHandle; }
    void setPatchHandle(audio_patch_handle_t patchHandle) { mPatchHandle = patchHandle; }

    sp<DeviceDescriptor> srcDevice() const { return mSrcDevice; }
    sp<DeviceDescriptor> sinkDevice() const { return mSinkDevice; }
    wp<SwAudioOutputDescriptor> swOutput() const { return mSwOutput; }
    void setSwOutput(const sp<SwAudioOutputDescriptor>& swOutput);
    wp<HwAudioOutputDescriptor> hwOutput() const { return mHwOutput; }
@@ -213,6 +221,7 @@ public:
 private:
    audio_patch_handle_t mPatchHandle = AUDIO_PATCH_HANDLE_NONE;
    const sp<DeviceDescriptor> mSrcDevice;
    sp<DeviceDescriptor> mSinkDevice;
    wp<SwAudioOutputDescriptor> mSwOutput;
    wp<HwAudioOutputDescriptor> mHwOutput;
};
+138 −67
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);
                    }
                }
@@ -384,7 +385,11 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescript
            DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, false /*fromCache*/);
            updateCallRouting(newDevices);
        }

        // Reconnect Audio Source
        for (const auto &strategy : mEngine->getOrderedProductStrategies()) {
            auto attributes = mEngine->getAllAttributesForProductStrategy(strategy).front();
            checkAudioSourceForAttributes(attributes);
        }
        if (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
            cleanUpForDevice(device);
        }
@@ -469,7 +474,7 @@ status_t AudioPolicyManager::handleDeviceConfigChange(audio_devices_t device,
    // Case 1: A2DP active device switches from primary to primary
    // module
    // Case 2: A2DP device config changes on primary module.
    if (audio_is_a2dp_out_device(device)) {
    if (audio_is_a2dp_out_device(device) && hasPrimaryOutput()) {
        sp<HwModule> module = mHwModules.getModuleForDeviceType(device, encodedFormat);
        audio_module_handle_t primaryHandle = mPrimaryOutput->getModuleHandle();
        if (availablePrimaryOutputDevices().contains(devDesc) &&
@@ -563,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());
@@ -615,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
@@ -679,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);
@@ -746,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();
@@ -3858,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();
@@ -3896,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;
@@ -4006,8 +4032,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.
@@ -4273,15 +4300,19 @@ status_t AudioPolicyManager::connectAudioSource(const sp<SourceClientDescriptor>
    disconnectAudioSource(sourceDesc);

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

    // May the device (dynamic) have been disconnected/reconnected, id has changed.
    sp<DeviceDescriptor> srcDevice = mAvailableInputDevices.getDevice(
                sourceDesc->srcDevice()->type(),
                String8(sourceDesc->srcDevice()->address().c_str()),
                AUDIO_FORMAT_DEFAULT);
    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",
                __FUNCTION__, sinkDevice->toString().c_str());

    if (!mAvailableOutputDevices.contains(sinkDevice)) {
        ALOGE("%s Device %s not available", __func__, sinkDevice->toString().c_str());
        return INVALID_OPERATION;
    }
    PatchBuilder patchBuilder;
    patchBuilder.addSink(sinkDevice).addSource(srcDevice);
    audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
@@ -4291,7 +4322,7 @@ status_t AudioPolicyManager::connectAudioSource(const sp<SourceClientDescriptor>
        ALOGW("%s patch panel could not connect device patch, error %d", __func__, status);
        return INVALID_OPERATION;
    }
    sourceDesc->setPatchHandle(handle);
    sourceDesc->connect(handle, sinkDevice);
    // SW Bridge? (@todo: HW bridge, keep track of HwOutput for device selection "reconsideration")
    sp<SwAudioOutputDescriptor> swOutput = sourceDesc->swOutput().promote();
    if (swOutput != 0) {
@@ -4588,6 +4619,10 @@ bool AudioPolicyManager::isCallScreenModeSupported()
status_t AudioPolicyManager::disconnectAudioSource(const sp<SourceClientDescriptor>& sourceDesc)
{
    ALOGV("%s port Id %d", __FUNCTION__, sourceDesc->portId());
    if (!sourceDesc->isConnected()) {
        ALOGV("%s port Id %d already disconnected", __FUNCTION__, sourceDesc->portId());
        return NO_ERROR;
    }
    sp<SwAudioOutputDescriptor> swOutput = sourceDesc->swOutput().promote();
    if (swOutput != 0) {
        status_t status = stopSource(swOutput, sourceDesc);
@@ -4607,7 +4642,9 @@ status_t AudioPolicyManager::disconnectAudioSource(const sp<SourceClientDescript
            ALOGW("%s source has neither SW nor HW output", __FUNCTION__);
        }
    }
    return releaseAudioPatchInternal(sourceDesc->getPatchHandle());
    status_t status = releaseAudioPatchInternal(sourceDesc->getPatchHandle());
    sourceDesc->disconnect();
    return status;
}

sp<SourceClientDescriptor> AudioPolicyManager::getSourceForAttributesOnOutput(
@@ -4722,10 +4759,7 @@ status_t AudioPolicyManager::initialize() {
        }
    }

    if (mPrimaryOutput == 0) {
        ALOGE("Failed to open primary output");
        status = NO_INIT;
    }
    ALOGW_IF(mPrimaryOutput == nullptr, "The policy configuration does not declare a primary output");

    // Silence ALOGV statements
    property_set("log.tag." LOG_TAG, "D");
@@ -4835,7 +4869,7 @@ void AudioPolicyManager::onNewAudioModulesAvailableInt(DeviceVector *newDevices)
                    setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
                }
            }
            if (mPrimaryOutput == 0 &&
            if (mPrimaryOutput == nullptr &&
                    outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
                mPrimaryOutput = outputDesc;
            }
@@ -4912,6 +4946,10 @@ void AudioPolicyManager::addOutput(audio_io_handle_t output,

void AudioPolicyManager::removeOutput(audio_io_handle_t output)
{
    if (mPrimaryOutput != 0 && mPrimaryOutput == mOutputs.valueFor(output)) {
        ALOGV("%s: removing primary output", __func__);
        mPrimaryOutput = nullptr;
    }
    mOutputs.removeItem(output);
    selectOutputForMusicEffects();
}
@@ -5360,6 +5398,29 @@ 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
                && !isCallRxAudioSource(sourceDesc)) {
            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 +5517,7 @@ void AudioPolicyManager::checkOutputForAttributes(const audio_attributes_t &attr
                                newDevices.types());
            }
            sp<SourceClientDescriptor> source = getSourceForAttributesOnOutput(srcOut, attr);
            if (source != 0){
            if (source != nullptr && !isCallRxAudioSource(source)) {
                connectAudioSource(source);
            }
        }
@@ -5479,6 +5540,7 @@ void AudioPolicyManager::checkOutputForAllStrategies()
    for (const auto &strategy : mEngine->getOrderedProductStrategies()) {
        auto attributes = mEngine->getAllAttributesForProductStrategy(strategy).front();
        checkOutputForAttributes(attributes);
        checkAudioSourceForAttributes(attributes);
    }
}

@@ -6450,9 +6512,10 @@ 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->srcDevice()->equals(deviceDesc)) {
            ALOGV("%s releasing audio source %d", __FUNCTION__, sourceDesc->portId());
            stopAudioSource(sourceDesc->portId());
        if (sourceDesc->isConnected() && (sourceDesc->srcDevice()->equals(deviceDesc) ||
                                          sourceDesc->sinkDevice()->equals(deviceDesc))
                && !isCallRxAudioSource(sourceDesc)) {
            disconnectAudioSource(sourceDesc);
        }
    }

@@ -6466,10 +6529,14 @@ void AudioPolicyManager::cleanUpForDevice(const sp<DeviceDescriptor>& deviceDesc
                release = true;
            }
        }
        const char *address = deviceDesc->address().c_str();
        for (size_t j = 0; j < patchDesc->mPatch.num_sinks && !release; j++)  {
            const struct audio_port_config *sink = &patchDesc->mPatch.sinks[j];
            if (sink->type == AUDIO_PORT_TYPE_DEVICE &&
                    sink->ext.device.type == deviceDesc->type()) {
                    sink->ext.device.type == deviceDesc->type() &&
                    (strnlen(address, AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0
                     || strncmp(sink->ext.device.address, address,
                                 AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0)) {
                release = true;
            }
        }
@@ -6810,6 +6877,10 @@ sp<SwAudioOutputDescriptor> AudioPolicyManager::openOutputWithProfileAndDevice(
            return nullptr;
        }
    }
    if (mPrimaryOutput == nullptr && profile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
        ALOGV("%s(): re-assigning mPrimaryOutput", __func__);
        mPrimaryOutput = desc;
    }
    return desc;
}

+24 −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.
         */
@@ -571,6 +580,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 +759,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);

@@ -786,7 +806,6 @@ protected:
        SoundTriggerSessionCollection mSoundTriggerSessions;

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

        HwAudioOutputCollection mHwOutputs;
        SourceClientCollection mAudioSources;
@@ -825,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);