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

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

Merge "audio policy: create spatializer mixer only when needed" into tm-dev

parents 768f4c48 e191d1b6
Loading
Loading
Loading
Loading
+86 −55
Original line number Diff line number Diff line
@@ -287,9 +287,12 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescript
                    sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(output);
                    // close unused outputs after device disconnection or direct outputs that have
                    // been opened by checkOutputsForDevice() to query dynamic parameters
                    // "outputs" vector never contains duplicated outputs
                    if ((state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE)
                            || (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) &&
                                (desc->mDirectOpenCount == 0))) {
                                (desc->mDirectOpenCount == 0))
                            || (((desc->mFlags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0) &&
                                !isOutputOnlyAvailableRouteToSomeDevice(desc))) {
                        clearAudioSourcesForOutput(output);
                        closeOutput(output);
                    }
@@ -5361,6 +5364,29 @@ void AudioPolicyManager::checkVirtualizerClientRoutes() {
    }
}


bool AudioPolicyManager::isOutputOnlyAvailableRouteToSomeDevice(
        const sp<SwAudioOutputDescriptor>& outputDesc) {
    if (outputDesc->isDuplicated()) {
        return false;
    }
    DeviceVector devices = outputDesc->supportedDevices();
    for (size_t i = 0; i < mOutputs.size(); i++) {
        sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
        if (desc == outputDesc || desc->isDuplicated()) {
            continue;
        }
        DeviceVector sharedDevices = desc->filterSupportedDevices(devices);
        if (!sharedDevices.isEmpty()
                && (desc->devicesSupportEncodedFormats(sharedDevices.types())
                    == outputDesc->devicesSupportEncodedFormats(sharedDevices.types()))) {
            return false;
        }
    }
    return true;
}


status_t AudioPolicyManager::getSpatializerOutput(const audio_config_base_t *mixerConfig,
                                                        const audio_attributes_t *attr,
                                                        audio_io_handle_t *output) {
@@ -5376,80 +5402,67 @@ status_t AudioPolicyManager::getSpatializerOutput(const audio_config_base_t *mix
    }
    if (!canBeSpatializedInt(
            attr, configPtr, devicesTypeAddress)) {
        ALOGW("%s provided attributes or mixer config cannot be spatialized", __func__);
        ALOGV("%s provided attributes or mixer config cannot be spatialized", __func__);
        return BAD_VALUE;
    }

    sp<IOProfile> profile =
            getSpatializerOutputProfile(configPtr, devicesTypeAddress);
    if (profile == nullptr) {
        ALOGW("%s no suitable output profile for provided attributes or mixer config", __func__);
        ALOGV("%s no suitable output profile for provided attributes or mixer config", __func__);
        return BAD_VALUE;
    }

    if (mSpatializerOutput != nullptr && mSpatializerOutput->mProfile == profile
            && configPtr != nullptr
            && configPtr->channel_mask == mSpatializerOutput->mMixerChannelMask) {
        *output = mSpatializerOutput->mIoHandle;
        ALOGV("%s returns current spatializer output %d", __func__, *output);
        return NO_ERROR;
    }
    mSpatializerOutput.clear();
    std::vector<sp<SwAudioOutputDescriptor>> spatializerOutputs;
    for (size_t i = 0; i < mOutputs.size(); i++) {
        sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
        if (!desc->isDuplicated() && desc->mProfile == profile) {
            ALOGV("%s found output %d for spatializer profile", __func__, desc->mIoHandle);
            mSpatializerOutput = desc;
            break;
        if (!desc->isDuplicated()
                && (desc->mFlags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0) {
            spatializerOutputs.push_back(desc);
            ALOGV("%s adding opened spatializer Output %d", __func__, desc->mIoHandle);
        }
    }
    if (mSpatializerOutput == nullptr) {
        ALOGW("%s no opened spatializer output for profile %s",
                __func__, profile->getName().c_str());
        return BAD_VALUE;
    mSpatializerOutput.clear();
    bool outputsChanged = false;
    for (const auto& desc : spatializerOutputs) {
        if (desc->mProfile == profile
                && (configPtr == nullptr
                   || configPtr->channel_mask == desc->mMixerChannelMask)) {
            mSpatializerOutput = desc;
            ALOGV("%s reusing current spatializer output %d", __func__, desc->mIoHandle);
        } else {
            ALOGV("%s closing spatializerOutput output %d to match channel mask %#x"
                    " and devices %s", __func__, desc->mIoHandle,
                    configPtr != nullptr ? configPtr->channel_mask : 0,
                    devices.toString().c_str());
            closeOutput(desc->mIoHandle);
            outputsChanged = true;
        }
    }

    if (configPtr != nullptr
            && configPtr->channel_mask != mSpatializerOutput->mMixerChannelMask) {
        audio_config_base_t savedMixerConfig = {
            .sample_rate = mSpatializerOutput->getSamplingRate(),
            .format = mSpatializerOutput->getFormat(),
            .channel_mask = mSpatializerOutput->mMixerChannelMask,
        };
        DeviceVector savedDevices = mSpatializerOutput->devices();

        ALOGV("%s reopening spatializer output to match channel mask %#x (current mask %#x)",
            __func__, configPtr->channel_mask, mSpatializerOutput->mMixerChannelMask);

        closeOutput(mSpatializerOutput->mIoHandle);
        //from now on mSpatializerOutput is null

    if (mSpatializerOutput == nullptr) {
        sp<SwAudioOutputDescriptor> desc =
                openOutputWithProfileAndDevice(profile, devices, mixerConfig);
        if (desc == nullptr) {
            // re open the spatializer output with previous channel mask
            desc = openOutputWithProfileAndDevice(profile, savedDevices, &savedMixerConfig);
            if (desc == nullptr) {
                ALOGE("%s failed to restore mSpatializerOutput with previous config", __func__);
            } else {
        if (desc != nullptr) {
            mSpatializerOutput = desc;
            outputsChanged = true;
        }
            mPreviousOutputs = mOutputs;
            mpClientInterface->onAudioPortListUpdate();
            *output = AUDIO_IO_HANDLE_NONE;
            ALOGW("%s could not open spatializer output with requested config", __func__);
            return BAD_VALUE;
    }
        mSpatializerOutput = desc;

    checkVirtualizerClientRoutes();

    if (outputsChanged) {
        mPreviousOutputs = mOutputs;
        mpClientInterface->onAudioPortListUpdate();
    }

    checkVirtualizerClientRoutes();

    if (mSpatializerOutput == nullptr) {
        ALOGV("%s could not open spatializer output with requested config", __func__);
        return BAD_VALUE;
    }
    *output = mSpatializerOutput->mIoHandle;
    ALOGV("%s returns new spatializer output %d", __func__, *output);
    return NO_ERROR;
    ALOGV("%s returning new spatializer output %d", __func__, *output);
    return OK;
}

status_t AudioPolicyManager::releaseSpatializerOutput(audio_io_handle_t output) {
@@ -5460,9 +5473,12 @@ status_t AudioPolicyManager::releaseSpatializerOutput(audio_io_handle_t output)
        return BAD_VALUE;
    }

    mSpatializerOutput.clear();

    if (!isOutputOnlyAvailableRouteToSomeDevice(mSpatializerOutput)) {
        ALOGV("%s closing spatializer output %d", __func__, mSpatializerOutput->mIoHandle);
        closeOutput(mSpatializerOutput->mIoHandle);
        //from now on mSpatializerOutput is null
        checkVirtualizerClientRoutes();
    }

    return NO_ERROR;
}
@@ -5739,6 +5755,21 @@ void AudioPolicyManager::onNewAudioModulesAvailableInt(DeviceVector *newDevices)
            inputDesc->close();
        }
    }

    // Check if spatializer outputs can be closed until used.
    // mOutputs vector never contains duplicated outputs at this point.
    std::vector<audio_io_handle_t> outputsClosed;
    for (size_t i = 0; i < mOutputs.size(); i++) {
        sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
        if ((desc->mFlags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0
                && !isOutputOnlyAvailableRouteToSomeDevice(desc)) {
            outputsClosed.push_back(desc->mIoHandle);
            desc->close();
        }
    }
    for (auto output : outputsClosed) {
        removeOutput(output);
    }
}

void AudioPolicyManager::addOutput(audio_io_handle_t output,
+10 −0
Original line number Diff line number Diff line
@@ -1096,6 +1096,16 @@ private:

        void checkVirtualizerClientRoutes();

        /**
         * @brief Returns true if at least one device can only be reached via the output passed
         * as argument. Always returns false for duplicated outputs.
         * This can be used to decide if an output can be closed without forbidding
         * playback to any given device.
         * @param outputDesc the output to consider
         * @return true if at least one device can only be reached via the output.
         */
        bool isOutputOnlyAvailableRouteToSomeDevice(const sp<SwAudioOutputDescriptor>& outputDesc);

        /**
         * @brief getInputForDevice selects an input handle for a given input device and
         * requester context