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

Commit 8248fbb8 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes I9efa7144,Id005aad9

* changes:
  audiopolicy: Add support for the MSD prototype
  audiopolicy: Add AudioProfileVector::findBestMatchingOutputConfig
parents 615fc5ce 15be9d2b
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

#pragma once

#include <vector>

#include <system/audio.h>
#include <utils/RefBase.h>
#include <utils/SortedVector.h>
@@ -139,6 +141,16 @@ public:
                                    audio_port_type_t portType,
                                    audio_port_role_t portRole) const;
    void clearProfiles();
    // Assuming that this profile vector contains input profiles,
    // find the best matching config from 'outputProfiles', according to
    // the given preferences for audio formats and channel masks.
    // Note: std::vectors are used because specialized containers for formats
    //       and channels can be sorted and use their own ordering.
    status_t findBestMatchingOutputConfig(const AudioProfileVector& outputProfiles,
            const std::vector<audio_format_t>& preferredFormats, // order: most pref -> least pref
            const std::vector<audio_channel_mask_t>& preferredOutputChannels,
            bool preferHigherSamplingRates,
            audio_config_base *bestOutputConfig) const;

    sp<AudioProfile> getFirstValidProfile() const;
    sp<AudioProfile> getFirstValidProfileFor(audio_format_t format) const;
+72 −0
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@
 * limitations under the License.
 */

#include <algorithm>
#include <set>
#include <string>

#define LOG_TAG "APM::AudioProfile"
@@ -406,6 +408,76 @@ void AudioProfileVector::clearProfiles()
    }
}

// Returns an intersection between two possibly unsorted vectors and the contents of 'order'.
// The result is ordered according to 'order'.
template<typename T, typename Order>
std::vector<typename T::value_type> intersectFilterAndOrder(
        const T& input1, const T& input2, const Order& order)
{
    std::set<typename T::value_type> set1{input1.begin(), input1.end()};
    std::set<typename T::value_type> set2{input2.begin(), input2.end()};
    std::set<typename T::value_type> common;
    std::set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(),
            std::inserter(common, common.begin()));
    std::vector<typename T::value_type> result;
    for (const auto& e : order) {
        if (common.find(e) != common.end()) result.push_back(e);
    }
    return result;
}

// Intersect two possibly unsorted vectors, return common elements according to 'comp' ordering.
// 'comp' is a comparator function.
template<typename T, typename Compare>
std::vector<typename T::value_type> intersectAndOrder(
        const T& input1, const T& input2, Compare comp)
{
    std::set<typename T::value_type, Compare> set1{input1.begin(), input1.end(), comp};
    std::set<typename T::value_type, Compare> set2{input2.begin(), input2.end(), comp};
    std::vector<typename T::value_type> result;
    std::set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(),
            std::back_inserter(result), comp);
    return result;
}

status_t AudioProfileVector::findBestMatchingOutputConfig(const AudioProfileVector& outputProfiles,
            const std::vector<audio_format_t>& preferredFormats,
            const std::vector<audio_channel_mask_t>& preferredOutputChannels,
            bool preferHigherSamplingRates,
            audio_config_base *bestOutputConfig) const
{
    auto formats = intersectFilterAndOrder(getSupportedFormats(),
            outputProfiles.getSupportedFormats(), preferredFormats);
    // Pick the best compatible profile.
    for (const auto& f : formats) {
        sp<AudioProfile> inputProfile = getFirstValidProfileFor(f);
        sp<AudioProfile> outputProfile = outputProfiles.getFirstValidProfileFor(f);
        if (inputProfile == nullptr || outputProfile == nullptr) {
            continue;
        }
        auto channels = intersectFilterAndOrder(inputProfile->getChannels().asOutMask(),
                outputProfile->getChannels(), preferredOutputChannels);
        if (channels.empty()) {
            continue;
        }
        auto sampleRates = preferHigherSamplingRates ?
                intersectAndOrder(inputProfile->getSampleRates(), outputProfile->getSampleRates(),
                        std::greater<typename SampleRateVector::value_type>()) :
                intersectAndOrder(inputProfile->getSampleRates(), outputProfile->getSampleRates(),
                        std::less<typename SampleRateVector::value_type>());
        if (sampleRates.empty()) {
            continue;
        }
        ALOGD("%s() found channel mask %#x and sample rate %d for format %#x.",
                __func__, *channels.begin(), *sampleRates.begin(), f);
        bestOutputConfig->format = f;
        bestOutputConfig->sample_rate = *sampleRates.begin();
        bestOutputConfig->channel_mask = *channels.begin();
        return NO_ERROR;
    }
    return BAD_VALUE;
}

sp<AudioProfile> AudioProfileVector::getFirstValidProfile() const
{
    for (size_t i = 0; i < size(); i++) {
+192 −10
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@

#include <inttypes.h>
#include <math.h>
#include <vector>

#include <AudioPolicyManagerInterface.h>
#include <AudioPolicyEngineInstance.h>
@@ -38,7 +39,6 @@
#include <utils/Log.h>
#include <media/AudioParameter.h>
#include <media/AudioPolicyHelper.h>
#include <media/PatchBuilder.h>
#include <private/android_filesystem_config.h>
#include <soundtrigger/SoundTrigger.h>
#include <system/audio.h>
@@ -82,6 +82,16 @@ static const audio_format_t AAC_FORMATS[] = {
    AUDIO_FORMAT_AAC_XHE,
};

// Compressed formats for MSD module, ordered from most preferred to least preferred.
static const std::vector<audio_format_t> compressedFormatsOrder = {{
        AUDIO_FORMAT_MAT_2_1, AUDIO_FORMAT_MAT_2_0, AUDIO_FORMAT_E_AC3,
        AUDIO_FORMAT_AC3, AUDIO_FORMAT_PCM_16_BIT }};
// Channel masks for MSD module, 3D > 2D > 1D ordering (most preferred to least preferred).
static const std::vector<audio_channel_mask_t> surroundChannelMasksOrder = {{
        AUDIO_CHANNEL_OUT_3POINT1POINT2, AUDIO_CHANNEL_OUT_3POINT0POINT2,
        AUDIO_CHANNEL_OUT_2POINT1POINT2, AUDIO_CHANNEL_OUT_2POINT0POINT2,
        AUDIO_CHANNEL_OUT_5POINT1, AUDIO_CHANNEL_OUT_STEREO }};

// ----------------------------------------------------------------------------
// AudioPolicyInterface implementation
// ----------------------------------------------------------------------------
@@ -225,6 +235,7 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device,
            audio_devices_t newDevice = getNewOutputDevice(mPrimaryOutput, false /*fromCache*/);
            updateCallRouting(newDevice);
        }
        const audio_devices_t msdOutDevice = getMsdAudioOutDeviceTypes();
        for (size_t i = 0; i < mOutputs.size(); i++) {
            sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
            if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (desc != mPrimaryOutput)) {
@@ -232,7 +243,8 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device,
                // do not force device change on duplicated output because if device is 0, it will
                // also force a device 0 for the two outputs it is duplicated to which may override
                // a valid device selection on those outputs.
                bool force = !desc->isDuplicated()
                bool force = (msdOutDevice == AUDIO_DEVICE_NONE || msdOutDevice != desc->device())
                        && !desc->isDuplicated()
                        && (!device_distinguishes_on_address(device)
                                // always force when disconnecting (a non-duplicated device)
                                || (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
@@ -525,7 +537,7 @@ sp<AudioPatch> AudioPolicyManager::createTelephonyPatch(
}

sp<DeviceDescriptor> AudioPolicyManager::findDevice(
        const DeviceVector& devices, audio_devices_t device) {
        const DeviceVector& devices, audio_devices_t device) const {
    DeviceVector deviceList = devices.getDevicesFromTypeMask(device);
    ALOG_ASSERT(!deviceList.isEmpty(),
            "%s() selected device type %#x is not in devices list", __func__, device);
@@ -777,6 +789,7 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
    routing_strategy strategy;
    audio_devices_t device;
    audio_port_handle_t requestedDeviceId = *selectedDeviceId;
    audio_devices_t msdDevice = getMsdAudioOutDeviceTypes();

    if (attr != NULL) {
        if (!isValidAttributes(attr)) {
@@ -869,7 +882,20 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
          "flags %#x",
          device, config->sample_rate, config->format, config->channel_mask, *flags);

    *output = AUDIO_IO_HANDLE_NONE;
    if (msdDevice != AUDIO_DEVICE_NONE) {
        *output = getOutputForDevice(msdDevice, session, *stream, config, flags);
        if (*output != AUDIO_IO_HANDLE_NONE && setMsdPatch(device) == NO_ERROR) {
            ALOGV("%s() Using MSD device 0x%x instead of device 0x%x",
                    __func__, msdDevice, device);
            device = msdDevice;
        } else {
            *output = AUDIO_IO_HANDLE_NONE;
        }
    }
    if (*output == AUDIO_IO_HANDLE_NONE) {
        *output = getOutputForDevice(device, session, *stream, config, flags);
    }
    if (*output == AUDIO_IO_HANDLE_NONE) {
        mOutputRoutes.removeRoute(session);
        return INVALID_OPERATION;
@@ -1052,6 +1078,164 @@ non_direct_output:
    return output;
}

sp<DeviceDescriptor> AudioPolicyManager::getMsdAudioInDevice() const {
    sp<HwModule> msdModule = mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD);
    if (msdModule != 0) {
        DeviceVector msdInputDevices = mAvailableInputDevices.getDevicesFromHwModule(
                msdModule->getHandle());
        if (!msdInputDevices.isEmpty()) return msdInputDevices.itemAt(0);
    }
    return 0;
}

audio_devices_t AudioPolicyManager::getMsdAudioOutDeviceTypes() const {
    sp<HwModule> msdModule = mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD);
    if (msdModule != 0) {
        return mAvailableOutputDevices.getDeviceTypesFromHwModule(msdModule->getHandle());
    }
    return AUDIO_DEVICE_NONE;
}

const AudioPatchCollection AudioPolicyManager::getMsdPatches() const {
    AudioPatchCollection msdPatches;
    audio_module_handle_t msdModuleHandle = mHwModules.getModuleFromName(
            AUDIO_HARDWARE_MODULE_ID_MSD)->getHandle();
    if (msdModuleHandle == AUDIO_MODULE_HANDLE_NONE) return msdPatches;
    for (size_t i = 0; i < mAudioPatches.size(); ++i) {
        sp<AudioPatch> patch = mAudioPatches.valueAt(i);
        for (size_t j = 0; j < patch->mPatch.num_sources; ++j) {
            const struct audio_port_config *source = &patch->mPatch.sources[j];
            if (source->type == AUDIO_PORT_TYPE_DEVICE &&
                    source->ext.device.hw_module == msdModuleHandle) {
                msdPatches.addAudioPatch(patch->mHandle, patch);
            }
        }
    }
    return msdPatches;
}

status_t AudioPolicyManager::getBestMsdAudioProfileFor(audio_devices_t outputDevice,
        bool hwAvSync, audio_port_config *sourceConfig, audio_port_config *sinkConfig) const
{
    sp<HwModule> msdModule = mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD);
    if (msdModule == nullptr) {
        ALOGE("%s() unable to get MSD module", __func__);
        return NO_INIT;
    }
    sp<HwModule> deviceModule = mHwModules.getModuleForDevice(outputDevice);
    if (deviceModule == nullptr) {
        ALOGE("%s() unable to get module for %#x", __func__, outputDevice);
        return NO_INIT;
    }
    const InputProfileCollection &inputProfiles = msdModule->getInputProfiles();
    if (inputProfiles.isEmpty()) {
        ALOGE("%s() no input profiles for MSD module", __func__);
        return NO_INIT;
    }
    const OutputProfileCollection &outputProfiles = deviceModule->getOutputProfiles();
    if (outputProfiles.isEmpty()) {
        ALOGE("%s() no output profiles for device %#x", __func__, outputDevice);
        return NO_INIT;
    }
    AudioProfileVector msdProfiles;
    // Each IOProfile represents a MixPort from audio_policy_configuration.xml
    for (const auto &inProfile : inputProfiles) {
        if (hwAvSync == ((inProfile->getFlags() & AUDIO_INPUT_FLAG_HW_AV_SYNC) != 0)) {
            msdProfiles.appendVector(inProfile->getAudioProfiles());
        }
    }
    AudioProfileVector deviceProfiles;
    for (const auto &outProfile : outputProfiles) {
        if (hwAvSync == ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0)) {
            deviceProfiles.appendVector(outProfile->getAudioProfiles());
        }
    }
    struct audio_config_base bestSinkConfig;
    status_t result = msdProfiles.findBestMatchingOutputConfig(deviceProfiles,
            compressedFormatsOrder, surroundChannelMasksOrder, true /*preferHigherSamplingRates*/,
            &bestSinkConfig);
    if (result != NO_ERROR) {
        return result;
        ALOGD("%s() no matching profiles found for device: %#x, hwAvSync: %d",
                __func__, outputDevice, hwAvSync);
    }
    sinkConfig->sample_rate = bestSinkConfig.sample_rate;
    sinkConfig->channel_mask = bestSinkConfig.channel_mask;
    sinkConfig->format = bestSinkConfig.format;
    // For encoded streams force direct flag to prevent downstream mixing.
    sinkConfig->flags.output = static_cast<audio_output_flags_t>(
            sinkConfig->flags.output | AUDIO_OUTPUT_FLAG_DIRECT);
    sourceConfig->sample_rate = bestSinkConfig.sample_rate;
    // Specify exact channel mask to prevent guessing by bit count in PatchPanel.
    sourceConfig->channel_mask = audio_channel_mask_out_to_in(bestSinkConfig.channel_mask);
    sourceConfig->format = bestSinkConfig.format;
    // Copy input stream directly without any processing (e.g. resampling).
    sourceConfig->flags.input = static_cast<audio_input_flags_t>(
            sourceConfig->flags.input | AUDIO_INPUT_FLAG_DIRECT);
    if (hwAvSync) {
        sinkConfig->flags.output = static_cast<audio_output_flags_t>(
                sinkConfig->flags.output | AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
        sourceConfig->flags.input = static_cast<audio_input_flags_t>(
                sourceConfig->flags.input | AUDIO_INPUT_FLAG_HW_AV_SYNC);
    }
    const unsigned int config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE |
            AUDIO_PORT_CONFIG_CHANNEL_MASK | AUDIO_PORT_CONFIG_FORMAT | AUDIO_PORT_CONFIG_FLAGS;
    sinkConfig->config_mask |= config_mask;
    sourceConfig->config_mask |= config_mask;
    return NO_ERROR;
}

PatchBuilder AudioPolicyManager::buildMsdPatch(audio_devices_t outputDevice) const
{
    PatchBuilder patchBuilder;
    patchBuilder.addSource(getMsdAudioInDevice()).
            addSink(findDevice(mAvailableOutputDevices, outputDevice));
    audio_port_config sourceConfig = patchBuilder.patch()->sources[0];
    audio_port_config sinkConfig = patchBuilder.patch()->sinks[0];
    // TODO: Figure out whether MSD module has HW_AV_SYNC flag set in the AP config file.
    // For now, we just forcefully try with HwAvSync first.
    status_t res = getBestMsdAudioProfileFor(outputDevice, true /*hwAvSync*/,
            &sourceConfig, &sinkConfig) == NO_ERROR ? NO_ERROR :
            getBestMsdAudioProfileFor(
                    outputDevice, false /*hwAvSync*/, &sourceConfig, &sinkConfig);
    if (res == NO_ERROR) {
        // Found a matching profile for encoded audio. Re-create PatchBuilder with this config.
        return (PatchBuilder()).addSource(sourceConfig).addSink(sinkConfig);
    }
    ALOGV("%s() no matching profile found. Fall through to default PCM patch"
            " supporting PCM format conversion.", __func__);
    return patchBuilder;
}

status_t AudioPolicyManager::setMsdPatch(audio_devices_t outputDevice) {
    ALOGV("%s() for outputDevice %#x", __func__, outputDevice);
    if (outputDevice == AUDIO_DEVICE_NONE) {
        // Use media strategy for unspecified output device. This should only
        // occur on checkForDeviceAndOutputChanges(). Device connection events may
        // therefore invalidate explicit routing requests.
        outputDevice = getDeviceForStrategy(STRATEGY_MEDIA, false /*fromCache*/);
    }
    PatchBuilder patchBuilder = buildMsdPatch(outputDevice);
    const struct audio_patch* patch = patchBuilder.patch();
    const AudioPatchCollection msdPatches = getMsdPatches();
    if (!msdPatches.isEmpty()) {
        LOG_ALWAYS_FATAL_IF(msdPatches.size() > 1,
                "The current MSD prototype only supports one output patch");
        sp<AudioPatch> currentPatch = msdPatches.valueAt(0);
        if (audio_patches_are_equal(&currentPatch->mPatch, patch)) {
            return NO_ERROR;
        }
        releaseAudioPatch(currentPatch->mHandle, mUidCached);
    }
    status_t status = installPatch(__func__, -1 /*index*/, nullptr /*patchHandle*/,
            patch, 0 /*delayMs*/, mUidCached, nullptr /*patchDescPtr*/);
    ALOGE_IF(status != NO_ERROR, "%s() error %d creating MSD audio patch", __func__, status);
    ALOGI_IF(status == NO_ERROR, "%s() Patch created from MSD_IN to "
           "device:%#x (format:%#x channels:%#x samplerate:%d)", __func__, outputDevice,
           patch->sources[0].format, patch->sources[0].channel_mask, patch->sources[0].sample_rate);
    return status;
}

audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_handle_t>& outputs,
                                                       audio_output_flags_t flags,
                                                       audio_format_t format)
@@ -4600,19 +4784,17 @@ SortedVector<audio_io_handle_t> AudioPolicyManager::getOutputsForDevice(
    return outputs;
}

void AudioPolicyManager::checkForDeviceAndOutputChanges()
{
    checkForDeviceAndOutputChanges([](){ return false; });
}

void AudioPolicyManager::checkForDeviceAndOutputChanges(std::function<bool()> onOutputsChecked)
{
    // checkA2dpSuspend must run before checkOutputForAllStrategies so that A2DP
    // output is suspended before any tracks are moved to it
    checkA2dpSuspend();
    checkOutputForAllStrategies();
    if (onOutputsChecked()) checkA2dpSuspend();
    if (onOutputsChecked != nullptr && onOutputsChecked()) checkA2dpSuspend();
    updateDevicesAndOutputs();
    if (mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD) != 0) {
        setMsdPatch();
    }
}

void AudioPolicyManager::checkOutputForStrategy(routing_strategy strategy)
+14 −3
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#include <utils/SortedVector.h>
#include <media/AudioParameter.h>
#include <media/AudioPolicy.h>
#include <media/PatchBuilder.h>
#include "AudioPolicyInterface.h"

#include <AudioPolicyManagerInterface.h>
@@ -407,8 +408,7 @@ protected:
        // if 'onOutputsChecked' callback is provided, it is executed after the outputs
        // check via 'checkOutputForAllStrategies'. If the callback returns 'true',
        // A2DP suspend status is rechecked.
        void checkForDeviceAndOutputChanges();
        void checkForDeviceAndOutputChanges(std::function<bool()> onOutputsChecked);
        void checkForDeviceAndOutputChanges(std::function<bool()> onOutputsChecked = nullptr);

        // checks and if necessary changes outputs used for all strategies.
        // must be called every time a condition that affects the output choice for a given strategy
@@ -506,7 +506,7 @@ protected:
        uint32_t updateCallRouting(audio_devices_t rxDevice, uint32_t delayMs = 0);
        sp<AudioPatch> createTelephonyPatch(bool isRx, audio_devices_t device, uint32_t delayMs);
        sp<DeviceDescriptor> findDevice(
                const DeviceVector& devices, audio_devices_t device);
                const DeviceVector& devices, audio_devices_t device) const;

        // if argument "device" is different from AUDIO_DEVICE_NONE,  startSource() will force
        // the re-evaluation of the output device.
@@ -620,6 +620,17 @@ private:

        status_t getSupportedFormats(audio_io_handle_t ioHandle, FormatVector& formats);

        // Support for Multi-Stream Decoder (MSD) module
        sp<DeviceDescriptor> getMsdAudioInDevice() const;
        audio_devices_t getMsdAudioOutDeviceTypes() const;
        const AudioPatchCollection getMsdPatches() const;
        status_t getBestMsdAudioProfileFor(audio_devices_t outputDevice,
                                           bool hwAvSync,
                                           audio_port_config *sourceConfig,
                                           audio_port_config *sinkConfig) const;
        PatchBuilder buildMsdPatch(audio_devices_t outputDevice) const;
        status_t setMsdPatch(audio_devices_t outputDevice = AUDIO_DEVICE_NONE);

        // If any, resolve any "dynamic" fields of an Audio Profiles collection
        void updateAudioProfiles(audio_devices_t device, audio_io_handle_t ioHandle,
                AudioProfileVector &profiles);