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

Commit 46c30e4c authored by jiabin's avatar jiabin
Browse files

Require matching identically when checking compatibility for mmap and

bit-perfect.

For MMAP and bit-perfect use case, the IOProfile must support the
identical configuration that is required by the client, which means
the IOProfile must contain an audio profile whose audio format is the
same as the client's request and the audio profile must contain the
requested channel mask and sample rate.

Bug: 337286288
Test: atest AAudioTests audiopolicy_tests
Change-Id: Ib1e28ced350e48c148f221233af23123b58de33e
parent f61ea2ad
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -38,11 +38,40 @@ void addDynamicAudioProfileAndSort(AudioProfileVector &audioProfileVector,
void appendAudioProfiles(AudioProfileVector &audioProfileVector,
                         const AudioProfileVector &audioProfileVectorToAppend);

/**
 * Check if the profile vector contains a profile that matches the given sampling rate, channel
 * mask and format. Note that this method uses `audio_formats_match` from policy.h, which will
 * consider PCM formats match if their bytes per sample are greater than 2.
 *
 * @param audioProfileVector
 * @param samplingRate
 * @param channelMask
 * @param format
 * @return NO_ERROR if the given profile vector is empty or it contains a profile that matches the
 *         given sampling rate, channel mask and format. Otherwise, returns BAD_VALUE.
 */
status_t checkExactProfile(const AudioProfileVector &audioProfileVector,
                           const uint32_t samplingRate,
                           audio_channel_mask_t channelMask,
                           audio_format_t format);

/**
 * Check if the profile vector contains a profile that has exactly the same sampling rate, channel
 * mask and format as the given values.
 *
 * @param audioProfileVector
 * @param samplingRate
 * @param channelMask
 * @param format
 * @return NO_ERROR if the given profile vector is empty or it contains a profile that that has
 *         exactly the same sampling rate, channel mask and format as the given values. Otherwise,
 *         returns BAD_VALUE.
 */
status_t checkIdenticalProfile(const AudioProfileVector &audioProfileVector,
                               const uint32_t samplingRate,
                               audio_channel_mask_t channelMask,
                               audio_format_t format);

status_t checkCompatibleProfile(const AudioProfileVector &audioProfileVector,
                                uint32_t &samplingRate,
                                audio_channel_mask_t &channelMask,
+12 −1
Original line number Diff line number Diff line
@@ -56,9 +56,14 @@ public:
    // Audio port IDs are in a different namespace than AudioFlinger unique IDs
    static audio_port_handle_t getNextUniqueId();

    // searches for an exact match
    // searches for an exact match, note that this method use `audio_formats_match` from policy.h,
    // which will consider PCM formats match if their bytes per sample are greater than 2.
    virtual status_t checkExactAudioProfile(const struct audio_port_config *config) const;

    // searches for an identical match, unlike `checkExactAudioProfile` above, this will also
    // require the formats to be exactly the same.
    virtual status_t checkIdenticalAudioProfile(const struct audio_port_config *config) const;

    // searches for a compatible match, currently implemented for input
    // parameters are input|output, returned value is the best match.
    status_t checkCompatibleAudioProfile(uint32_t &samplingRate,
@@ -100,6 +105,12 @@ private:
                         const ChannelMaskSet &channelMasks) const;
    void pickSamplingRate(uint32_t &rate, const SampleRateSet &samplingRates) const;

    status_t checkAudioProfile(const struct audio_port_config *config,
                               std::function<status_t(const AudioProfileVector&,
                                                      const uint32_t samplingRate,
                                                      audio_channel_mask_t,
                                                      audio_format_t)> checkProfile) const;

    sp<HwModule> mModule;     // audio HW module exposing this I/O stream
    AudioRouteVector mRoutes; // Routes involving this port
};
+38 −6
Original line number Diff line number Diff line
@@ -190,6 +190,18 @@ status_t checkExact(const sp<AudioProfile> &audioProfile,
    return BAD_VALUE;
}

status_t checkIdentical(const sp<AudioProfile> &audioProfile,
                        uint32_t samplingRate,
                        audio_channel_mask_t channelMask,
                        audio_format_t format) {
    if(audioProfile->getFormat() == format &&
        audioProfile->supportsChannels(channelMask) &&
        audioProfile->supportsRate(samplingRate)) {
        return NO_ERROR;
    }
    return BAD_VALUE;
}

status_t checkCompatibleSamplingRate(const sp<AudioProfile> &audioProfile,
                                     uint32_t samplingRate,
                                     uint32_t &updatedSamplingRate)
@@ -320,23 +332,43 @@ status_t checkCompatibleChannelMask(const sp<AudioProfile> &audioProfile,
    return bestMatch > 0 ? NO_ERROR : BAD_VALUE;
}

status_t checkExactProfile(const AudioProfileVector& audioProfileVector,
namespace {

status_t checkProfile(const AudioProfileVector& audioProfileVector,
                      const uint32_t samplingRate,
                      audio_channel_mask_t channelMask,
                           audio_format_t format)
{
                      audio_format_t format,
                      std::function<status_t(const sp<AudioProfile> &, uint32_t,
                                             audio_channel_mask_t, audio_format_t)> check) {
    if (audioProfileVector.empty()) {
        return NO_ERROR;
    }

    for (const auto& profile : audioProfileVector) {
        if (checkExact(profile, samplingRate, channelMask, format) == NO_ERROR) {
        if (check(profile, samplingRate, channelMask, format) == NO_ERROR) {
            return NO_ERROR;
        }
    }
    return BAD_VALUE;
}

} // namespace

status_t checkExactProfile(const AudioProfileVector& audioProfileVector,
                           const uint32_t samplingRate,
                           audio_channel_mask_t channelMask,
                           audio_format_t format)
{
    return checkProfile(audioProfileVector, samplingRate, channelMask, format, checkExact);
}

status_t checkIdenticalProfile(const AudioProfileVector &audioProfileVector,
                               const uint32_t samplingRate,
                               audio_channel_mask_t channelMask,
                               audio_format_t format) {
    return checkProfile(audioProfileVector, samplingRate, channelMask, format, checkIdentical);
}

status_t checkCompatibleProfile(const AudioProfileVector &audioProfileVector,
                                uint32_t &samplingRate,
                                audio_channel_mask_t &channelMask,
+8 −2
Original line number Diff line number Diff line
@@ -73,7 +73,7 @@ IOProfile::CompatibilityScore IOProfile::getCompatibilityScore(
    if (isRecordThread)
    {
        if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
            if (checkExactAudioProfile(&config) != NO_ERROR) {
            if (checkIdenticalAudioProfile(&config) != NO_ERROR) {
                return result;
            }
            result = EXACT_MATCH;
@@ -86,7 +86,13 @@ IOProfile::CompatibilityScore IOProfile::getCompatibilityScore(
            return result;
        }
    } else {
        if (checkExactAudioProfile(&config) == NO_ERROR) {
        if ((flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) != 0 ||
            (flags & AUDIO_OUTPUT_FLAG_BIT_PERFECT) != 0) {
            if (checkIdenticalAudioProfile(&config) != NO_ERROR) {
                return result;
            }
            result = EXACT_MATCH;
        } else if (checkExactAudioProfile(&config) == NO_ERROR) {
            result = EXACT_MATCH;
        } else {
            return result;
+29 −15
Original line number Diff line number Diff line
@@ -63,21 +63,11 @@ const char *PolicyAudioPort::getModuleName() const

status_t PolicyAudioPort::checkExactAudioProfile(const struct audio_port_config *config) const
{
    status_t status = NO_ERROR;
    auto config_mask = config->config_mask;
    if (config_mask & AUDIO_PORT_CONFIG_GAIN) {
        config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
        status = asAudioPort()->checkGain(&config->gain, config->gain.index);
        if (status != NO_ERROR) {
            return status;
        }
    return checkAudioProfile(config, checkExactProfile);
}
    if (config_mask != 0) {
        // TODO should we check sample_rate / channel_mask / format separately?
        status = checkExactProfile(asAudioPort()->getAudioProfiles(), config->sample_rate,
                config->channel_mask, config->format);
    }
    return status;

status_t PolicyAudioPort::checkIdenticalAudioProfile(const struct audio_port_config *config) const {
    return checkAudioProfile(config, checkIdenticalProfile);
}

void PolicyAudioPort::pickSamplingRate(uint32_t &pickedRate,
@@ -266,4 +256,28 @@ void PolicyAudioPort::pickAudioProfile(uint32_t &samplingRate,
            asAudioPort()->getName().c_str(), samplingRate, channelMask, format);
}

status_t PolicyAudioPort::checkAudioProfile(
        const struct audio_port_config *config,
        std::function<status_t(const AudioProfileVector &,
                               const uint32_t,
                               audio_channel_mask_t,
                               audio_format_t)> checkProfile) const {
    status_t status = NO_ERROR;
    auto config_mask = config->config_mask;
    if (config_mask & AUDIO_PORT_CONFIG_GAIN) {
        config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
        status = asAudioPort()->checkGain(&config->gain, config->gain.index);
        if (status != NO_ERROR) {
            return status;
        }
    }
    if (config_mask != 0) {
        // TODO should we check sample_rate / channel_mask / format separately?
        status = checkProfile(asAudioPort()->getAudioProfiles(), config->sample_rate,
                   config->channel_mask, config->format);
    }
    return status;

}

} // namespace android