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

Commit d5e18052 authored by Mikhail Naganov's avatar Mikhail Naganov
Browse files

Audio Policy: Parametrize encoded formats supported by device

For various reasons, we need to store the list of audio
formats supported by devices. Here we add support for this
into DeviceDescriptor. We don't read them yet from
the APM config file, but we will eventually.

Also in this change, use the formats list for parametrizing
the behavior of surround sound configuration. The special
logic for AC3 and IEC69137 formats used to be hardcoded
into 'filterSurroundFormats' function, now it is
parametrized by the device descriptor information.

Fix behavior of 'filterSurroundFormats' in 'manual'
mode, where it was removing PCM formats from the list.

Rename 'filterSurround...' functions to 'modifySurround...'
since they can both add and remove items from the provided
list.

Bug: 67479735
Bug: 117602867
Test: compare A/B APM dumps while modifying Surround Sound
      settings; tested with a HDMI sink that doesn't support
      any surround, and with an AV receiver
Change-Id: Ie46480d5e9519366b1f3553645c9ca20f64bdc80
parent 71738ebf
Loading
Loading
Loading
Loading
+5 −0
Original line number Original line Diff line number Diff line
@@ -31,6 +31,8 @@ class DeviceDescriptor : public AudioPort, public AudioPortConfig
public:
public:
     // Note that empty name refers by convention to a generic device.
     // Note that empty name refers by convention to a generic device.
    explicit DeviceDescriptor(audio_devices_t type, const String8 &tagName = String8(""));
    explicit DeviceDescriptor(audio_devices_t type, const String8 &tagName = String8(""));
    DeviceDescriptor(audio_devices_t type, const FormatVector &encodedFormats,
            const String8 &tagName = String8(""));


    virtual ~DeviceDescriptor() {}
    virtual ~DeviceDescriptor() {}


@@ -38,6 +40,8 @@ public:


    audio_devices_t type() const { return mDeviceType; }
    audio_devices_t type() const { return mDeviceType; }


    const FormatVector& encodedFormats() const { return mEncodedFormats; }

    bool equals(const sp<DeviceDescriptor>& other) const;
    bool equals(const sp<DeviceDescriptor>& other) const;


    // AudioPortConfig
    // AudioPortConfig
@@ -59,6 +63,7 @@ public:
private:
private:
    String8 mTagName; // Unique human readable identifier for a device port found in conf file.
    String8 mTagName; // Unique human readable identifier for a device port found in conf file.
    audio_devices_t     mDeviceType;
    audio_devices_t     mDeviceType;
    FormatVector        mEncodedFormats;
    audio_port_handle_t mId;
    audio_port_handle_t mId;


friend class DeviceVector;
friend class DeviceVector;
+12 −1
Original line number Original line Diff line number Diff line
@@ -26,14 +26,25 @@
namespace android {
namespace android {


DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const String8 &tagName) :
DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const String8 &tagName) :
        DeviceDescriptor(type, FormatVector{}, tagName)
{
}

DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const FormatVector &encodedFormats,
        const String8 &tagName) :
    AudioPort(String8(""), AUDIO_PORT_TYPE_DEVICE,
    AudioPort(String8(""), AUDIO_PORT_TYPE_DEVICE,
              audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
              audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
                                             AUDIO_PORT_ROLE_SOURCE),
                                             AUDIO_PORT_ROLE_SOURCE),
    mAddress(""), mTagName(tagName), mDeviceType(type), mId(0)
    mAddress(""), mTagName(tagName), mDeviceType(type), mEncodedFormats(encodedFormats), mId(0)
{
{
    if (type == AUDIO_DEVICE_IN_REMOTE_SUBMIX || type == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ) {
    if (type == AUDIO_DEVICE_IN_REMOTE_SUBMIX || type == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ) {
        mAddress = String8("0");
        mAddress = String8("0");
    }
    }
    /* FIXME: read from APM config file */
    if (type == AUDIO_DEVICE_OUT_HDMI) {
        mEncodedFormats.add(AUDIO_FORMAT_AC3);
        mEncodedFormats.add(AUDIO_FORMAT_IEC61937);
    }
}
}


audio_port_handle_t DeviceDescriptor::getId() const
audio_port_handle_t DeviceDescriptor::getId() const
+41 −91
Original line number Original line Diff line number Diff line
@@ -36,6 +36,7 @@


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


#include <AudioPolicyManagerInterface.h>
#include <AudioPolicyManagerInterface.h>
@@ -4114,7 +4115,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor>& d
                    mpClientInterface->setParameters(output, String8(param));
                    mpClientInterface->setParameters(output, String8(param));
                    free(param);
                    free(param);
                }
                }
                updateAudioProfiles(device, output, profile->getAudioProfiles());
                updateAudioProfiles(devDesc, output, profile->getAudioProfiles());
                if (!profile->hasValidAudioProfile()) {
                if (!profile->hasValidAudioProfile()) {
                    ALOGW("checkOutputsForDevice() missing param");
                    ALOGW("checkOutputsForDevice() missing param");
                    desc->close();
                    desc->close();
@@ -4322,7 +4323,7 @@ status_t AudioPolicyManager::checkInputsForDevice(const sp<DeviceDescriptor>& de
                    mpClientInterface->setParameters(input, String8(param));
                    mpClientInterface->setParameters(input, String8(param));
                    free(param);
                    free(param);
                }
                }
                updateAudioProfiles(device, input, profile->getAudioProfiles());
                updateAudioProfiles(devDesc, input, profile->getAudioProfiles());
                if (!profile->hasValidAudioProfile()) {
                if (!profile->hasValidAudioProfile()) {
                    ALOGW("checkInputsForDevice() direct input missing param");
                    ALOGW("checkInputsForDevice() direct input missing param");
                    desc->close();
                    desc->close();
@@ -5661,117 +5662,65 @@ void AudioPolicyManager::cleanUpForDevice(const sp<DeviceDescriptor>& deviceDesc
    }
    }
}
}


// Modify the list of surround sound formats supported.
void AudioPolicyManager::modifySurroundFormats(
void AudioPolicyManager::filterSurroundFormats(FormatVector *formatsPtr) {
        const sp<DeviceDescriptor>& devDesc, FormatVector *formatsPtr) {
    FormatVector &formats = *formatsPtr;
    // Use a set because FormatVector is unsorted.
    // TODO Set this based on Config properties.
    std::unordered_set<audio_format_t> enforcedSurround(
    const bool alwaysForceAC3 = true;
            devDesc->encodedFormats().begin(), devDesc->encodedFormats().end());


    audio_policy_forced_cfg_t forceUse = mEngine->getForceUse(
    audio_policy_forced_cfg_t forceUse = mEngine->getForceUse(
            AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND);
            AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND);
    ALOGD("%s: forced use = %d", __FUNCTION__, forceUse);
    ALOGD("%s: forced use = %d", __FUNCTION__, forceUse);


    std::unordered_set<audio_format_t> formatSet;
    if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL
            || forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER) {
        // Only copy non-surround formats to formatSet.
        for (auto formatIter = formatsPtr->begin(); formatIter != formatsPtr->end(); ++formatIter) {
            if (mConfig.getSurroundFormats().count(*formatIter) == 0 &&
                    enforcedSurround.count(*formatIter) == 0) {
                formatSet.insert(*formatIter);
            }
        }
    } else {
        formatSet.insert(formatsPtr->begin(), formatsPtr->end());
    }
    formatsPtr->clear();  // Re-filled from the formatSet in the end.

    // If MANUAL, keep the supported surround sound formats as current enabled ones.
    // If MANUAL, keep the supported surround sound formats as current enabled ones.
    if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL) {
    if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL) {
        formats.clear();
        formatSet.insert(mSurroundFormats.begin(), mSurroundFormats.end());
        for (auto it = mSurroundFormats.begin(); it != mSurroundFormats.end(); it++) {
        // Enable IEC61937 when in MANUAL mode if it's enforced for this device.
            formats.add(*it);
        if (enforcedSurround.count(AUDIO_FORMAT_IEC61937) != 0) {
            formatSet.insert(AUDIO_FORMAT_IEC61937);
        }
        }
        // Always enable IEC61937 when in MANUAL mode.
        formats.add(AUDIO_FORMAT_IEC61937);
    } else { // NEVER, AUTO or ALWAYS
    } else { // NEVER, AUTO or ALWAYS
        // Analyze original support for various formats.
        bool supportsAC3 = false;
        bool supportsOtherSurround = false;
        bool supportsIEC61937 = false;
        mSurroundFormats.clear();
        mSurroundFormats.clear();
        for (ssize_t formatIndex = 0; formatIndex < (ssize_t)formats.size(); formatIndex++) {
            audio_format_t format = formats[formatIndex];
            switch (format) {
                case AUDIO_FORMAT_AC3:
                    supportsAC3 = true;
                    break;
                case AUDIO_FORMAT_E_AC3:
                case AUDIO_FORMAT_DTS:
                case AUDIO_FORMAT_DTS_HD:
                    // If ALWAYS, remove all other surround formats here
                    // since we will add them later.
                    if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS) {
                        formats.removeAt(formatIndex);
                        formatIndex--;
                    }
                    supportsOtherSurround = true;
                    break;
                case AUDIO_FORMAT_IEC61937:
                    supportsIEC61937 = true;
                    break;
                default:
                    break;
            }
        }

        // Modify formats based on surround preferences.
        // Modify formats based on surround preferences.
        // If NEVER, remove support for surround formats.
        if (forceUse != AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER) { // AUTO or ALWAYS
        if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER) {
            if (supportsAC3 || supportsOtherSurround || supportsIEC61937) {
                // Remove surround sound related formats.
                for (size_t formatIndex = 0; formatIndex < formats.size(); ) {
                    audio_format_t format = formats[formatIndex];
                    switch(format) {
                        case AUDIO_FORMAT_AC3:
                        case AUDIO_FORMAT_E_AC3:
                        case AUDIO_FORMAT_DTS:
                        case AUDIO_FORMAT_DTS_HD:
                        case AUDIO_FORMAT_IEC61937:
                            formats.removeAt(formatIndex);
                            break;
                        default:
                            formatIndex++; // keep it
                            break;
                    }
                }
                supportsAC3 = false;
                supportsOtherSurround = false;
                supportsIEC61937 = false;
            }
        } else { // AUTO or ALWAYS
            // Most TVs support AC3 even if they do not report it in the EDID.
            if ((alwaysForceAC3 || (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS))
                    && !supportsAC3) {
                formats.add(AUDIO_FORMAT_AC3);
                supportsAC3 = true;
            }

            // If ALWAYS, add support for raw surround formats if all are missing.
            // If ALWAYS, add support for raw surround formats if all are missing.
            // This assumes that if any of these formats are reported by the HAL
            // This assumes that if any of these formats are reported by the HAL
            // then the report is valid and should not be modified.
            // then the report is valid and should not be modified.
            if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS) {
            if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS) {
                formats.add(AUDIO_FORMAT_E_AC3);
                for (const auto& format : mConfig.getSurroundFormats()) {
                formats.add(AUDIO_FORMAT_DTS);
                    formatSet.insert(format.first);
                formats.add(AUDIO_FORMAT_DTS_HD);
                supportsOtherSurround = true;
                }
                }

            // Add support for IEC61937 if any raw surround supported.
            // The HAL could do this but add it here, just in case.
            if ((supportsAC3 || supportsOtherSurround) && !supportsIEC61937) {
                formats.add(AUDIO_FORMAT_IEC61937);
                supportsIEC61937 = true;
            }
            }
            formatSet.insert(enforcedSurround.begin(), enforcedSurround.end());


            // Add reported surround sound formats to enabled surround formats.
            for (const auto& format : formatSet) {
            for (size_t formatIndex = 0; formatIndex < formats.size(); formatIndex++) {
                audio_format_t format = formats[formatIndex];
                if (mConfig.getSurroundFormats().count(format) != 0) {
                if (mConfig.getSurroundFormats().count(format) != 0) {
                    mSurroundFormats.insert(format);
                    mSurroundFormats.insert(format);
                }
                }
            }
            }
        }
        }
    }
    }
    for (const auto& format : formatSet) {
        formatsPtr->push(format);
    }
}
}


// Modify the list of channel masks supported.
void AudioPolicyManager::modifySurroundChannelMasks(ChannelsVector *channelMasksPtr) {
void AudioPolicyManager::filterSurroundChannelMasks(ChannelsVector *channelMasksPtr) {
    ChannelsVector &channelMasks = *channelMasksPtr;
    ChannelsVector &channelMasks = *channelMasksPtr;
    audio_policy_forced_cfg_t forceUse = mEngine->getForceUse(
    audio_policy_forced_cfg_t forceUse = mEngine->getForceUse(
            AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND);
            AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND);
@@ -5806,11 +5755,12 @@ void AudioPolicyManager::filterSurroundChannelMasks(ChannelsVector *channelMasks
    }
    }
}
}


void AudioPolicyManager::updateAudioProfiles(audio_devices_t device,
void AudioPolicyManager::updateAudioProfiles(const sp<DeviceDescriptor>& devDesc,
                                             audio_io_handle_t ioHandle,
                                             audio_io_handle_t ioHandle,
                                             AudioProfileVector &profiles)
                                             AudioProfileVector &profiles)
{
{
    String8 reply;
    String8 reply;
    audio_devices_t device = devDesc->type();


    // Format MUST be checked first to update the list of AudioProfile
    // Format MUST be checked first to update the list of AudioProfile
    if (profiles.hasDynamicFormat()) {
    if (profiles.hasDynamicFormat()) {
@@ -5825,7 +5775,7 @@ void AudioPolicyManager::updateAudioProfiles(audio_devices_t device,
        }
        }
        FormatVector formats = formatsFromString(reply.string());
        FormatVector formats = formatsFromString(reply.string());
        if (device == AUDIO_DEVICE_OUT_HDMI) {
        if (device == AUDIO_DEVICE_OUT_HDMI) {
            filterSurroundFormats(&formats);
            modifySurroundFormats(devDesc, &formats);
        }
        }
        profiles.setFormats(formats);
        profiles.setFormats(formats);
    }
    }
@@ -5858,7 +5808,7 @@ void AudioPolicyManager::updateAudioProfiles(audio_devices_t device,
                    String8(AudioParameter::keyStreamSupportedChannels), reply) == NO_ERROR) {
                    String8(AudioParameter::keyStreamSupportedChannels), reply) == NO_ERROR) {
                channelMasks = channelMasksFromString(reply.string());
                channelMasks = channelMasksFromString(reply.string());
                if (device == AUDIO_DEVICE_OUT_HDMI) {
                if (device == AUDIO_DEVICE_OUT_HDMI) {
                    filterSurroundChannelMasks(&channelMasks);
                    modifySurroundChannelMasks(&channelMasks);
                }
                }
            }
            }
        }
        }
+3 −3
Original line number Original line Diff line number Diff line
@@ -608,8 +608,8 @@ protected:
        std::unordered_set<audio_format_t> mSurroundFormats;
        std::unordered_set<audio_format_t> mSurroundFormats;
private:
private:
        // Add or remove AC3 DTS encodings based on user preferences.
        // Add or remove AC3 DTS encodings based on user preferences.
        void filterSurroundFormats(FormatVector *formatsPtr);
        void modifySurroundFormats(const sp<DeviceDescriptor>& devDesc, FormatVector *formatsPtr);
        void filterSurroundChannelMasks(ChannelsVector *channelMasksPtr);
        void modifySurroundChannelMasks(ChannelsVector *channelMasksPtr);


        // Support for Multi-Stream Decoder (MSD) module
        // Support for Multi-Stream Decoder (MSD) module
        sp<DeviceDescriptor> getMsdAudioInDevice() const;
        sp<DeviceDescriptor> getMsdAudioInDevice() const;
@@ -623,7 +623,7 @@ private:
        status_t setMsdPatch(audio_devices_t outputDevice = AUDIO_DEVICE_NONE);
        status_t setMsdPatch(audio_devices_t outputDevice = AUDIO_DEVICE_NONE);


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


        // Notify the policy client of any change of device state with AUDIO_IO_HANDLE_NONE,
        // Notify the policy client of any change of device state with AUDIO_IO_HANDLE_NONE,