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 Original line Diff line number Diff line
@@ -38,11 +38,40 @@ void addDynamicAudioProfileAndSort(AudioProfileVector &audioProfileVector,
void appendAudioProfiles(AudioProfileVector &audioProfileVector,
void appendAudioProfiles(AudioProfileVector &audioProfileVector,
                         const AudioProfileVector &audioProfileVectorToAppend);
                         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,
status_t checkExactProfile(const AudioProfileVector &audioProfileVector,
                           const uint32_t samplingRate,
                           const uint32_t samplingRate,
                           audio_channel_mask_t channelMask,
                           audio_channel_mask_t channelMask,
                           audio_format_t format);
                           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,
status_t checkCompatibleProfile(const AudioProfileVector &audioProfileVector,
                                uint32_t &samplingRate,
                                uint32_t &samplingRate,
                                audio_channel_mask_t &channelMask,
                                audio_channel_mask_t &channelMask,
+12 −1
Original line number Original line Diff line number Diff line
@@ -56,9 +56,14 @@ public:
    // Audio port IDs are in a different namespace than AudioFlinger unique IDs
    // Audio port IDs are in a different namespace than AudioFlinger unique IDs
    static audio_port_handle_t getNextUniqueId();
    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;
    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
    // searches for a compatible match, currently implemented for input
    // parameters are input|output, returned value is the best match.
    // parameters are input|output, returned value is the best match.
    status_t checkCompatibleAudioProfile(uint32_t &samplingRate,
    status_t checkCompatibleAudioProfile(uint32_t &samplingRate,
@@ -100,6 +105,12 @@ private:
                         const ChannelMaskSet &channelMasks) const;
                         const ChannelMaskSet &channelMasks) const;
    void pickSamplingRate(uint32_t &rate, const SampleRateSet &samplingRates) 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
    sp<HwModule> mModule;     // audio HW module exposing this I/O stream
    AudioRouteVector mRoutes; // Routes involving this port
    AudioRouteVector mRoutes; // Routes involving this port
};
};
+38 −6
Original line number Original line Diff line number Diff line
@@ -190,6 +190,18 @@ status_t checkExact(const sp<AudioProfile> &audioProfile,
    return BAD_VALUE;
    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,
status_t checkCompatibleSamplingRate(const sp<AudioProfile> &audioProfile,
                                     uint32_t samplingRate,
                                     uint32_t samplingRate,
                                     uint32_t &updatedSamplingRate)
                                     uint32_t &updatedSamplingRate)
@@ -320,23 +332,43 @@ status_t checkCompatibleChannelMask(const sp<AudioProfile> &audioProfile,
    return bestMatch > 0 ? NO_ERROR : BAD_VALUE;
    return bestMatch > 0 ? NO_ERROR : BAD_VALUE;
}
}


status_t checkExactProfile(const AudioProfileVector& audioProfileVector,
namespace {

status_t checkProfile(const AudioProfileVector& audioProfileVector,
                      const uint32_t samplingRate,
                      const uint32_t samplingRate,
                      audio_channel_mask_t channelMask,
                      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()) {
    if (audioProfileVector.empty()) {
        return NO_ERROR;
        return NO_ERROR;
    }
    }


    for (const auto& profile : audioProfileVector) {
    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 NO_ERROR;
        }
        }
    }
    }
    return BAD_VALUE;
    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,
status_t checkCompatibleProfile(const AudioProfileVector &audioProfileVector,
                                uint32_t &samplingRate,
                                uint32_t &samplingRate,
                                audio_channel_mask_t &channelMask,
                                audio_channel_mask_t &channelMask,
+8 −2
Original line number Original line Diff line number Diff line
@@ -73,7 +73,7 @@ IOProfile::CompatibilityScore IOProfile::getCompatibilityScore(
    if (isRecordThread)
    if (isRecordThread)
    {
    {
        if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
        if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
            if (checkExactAudioProfile(&config) != NO_ERROR) {
            if (checkIdenticalAudioProfile(&config) != NO_ERROR) {
                return result;
                return result;
            }
            }
            result = EXACT_MATCH;
            result = EXACT_MATCH;
@@ -86,7 +86,13 @@ IOProfile::CompatibilityScore IOProfile::getCompatibilityScore(
            return result;
            return result;
        }
        }
    } else {
    } 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;
            result = EXACT_MATCH;
        } else {
        } else {
            return result;
            return result;
+29 −15
Original line number Original line 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 PolicyAudioPort::checkExactAudioProfile(const struct audio_port_config *config) const
{
{
    status_t status = NO_ERROR;
    return checkAudioProfile(config, checkExactProfile);
    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_t PolicyAudioPort::checkIdenticalAudioProfile(const struct audio_port_config *config) const {
        status = checkExactProfile(asAudioPort()->getAudioProfiles(), config->sample_rate,
    return checkAudioProfile(config, checkIdenticalProfile);
                config->channel_mask, config->format);
    }
    return status;
}
}


void PolicyAudioPort::pickSamplingRate(uint32_t &pickedRate,
void PolicyAudioPort::pickSamplingRate(uint32_t &pickedRate,
@@ -266,4 +256,28 @@ void PolicyAudioPort::pickAudioProfile(uint32_t &samplingRate,
            asAudioPort()->getName().c_str(), samplingRate, channelMask, format);
            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
} // namespace android