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

Commit 4562b3b9 authored by jiabin's avatar jiabin
Browse files

Use standard containers for audio stuff in audio framework

1. Add SampleRateSet, FormatSet, ChannelMaskSet, FormatVector
using std::vector and std::set in libaudiofoundation.
2. Use SampleRateSet, FormatSet, ChannelMaskSet, FormatVector in
audio framework.

Bug: 135621476
Test: make, CTS for AudioRecord, AudioTrack, AudioManagerTest
Test: play and record audio
Change-Id: Ic04e637bcc6ba9df84c5e7561ec3c03f18a7d242
Merged-In: Ic04e637bcc6ba9df84c5e7561ec3c03f18a7d242
parent 41502b24
Loading
Loading
Loading
Loading
+52 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <set>
#include <vector>

#include <system/audio.h>

namespace android {

using ChannelMaskSet = std::set<audio_channel_mask_t>;
using FormatSet = std::set<audio_format_t>;
using SampleRateSet = std::set<uint32_t>;

using FormatVector = std::vector<audio_format_t>;

static inline ChannelMaskSet asInMask(const ChannelMaskSet& channelMasks) {
    ChannelMaskSet inMaskSet;
    for (const auto &channel : channelMasks) {
        if (audio_channel_mask_out_to_in(channel) != AUDIO_CHANNEL_INVALID) {
            inMaskSet.insert(audio_channel_mask_out_to_in(channel));
        }
    }
    return inMaskSet;
}

static inline ChannelMaskSet asOutMask(const ChannelMaskSet& channelMasks) {
    ChannelMaskSet outMaskSet;
    for (const auto &channel : channelMasks) {
        if (audio_channel_mask_in_to_out(channel) != AUDIO_CHANNEL_INVALID) {
            outMaskSet.insert(audio_channel_mask_in_to_out(channel));
        }
    }
    return outMaskSet;
}

} // namespace android
 No newline at end of file
+11 −17
Original line number Diff line number Diff line
@@ -17,10 +17,11 @@
#ifndef ANDROID_TYPE_CONVERTER_H_
#define ANDROID_TYPE_CONVERTER_H_

#include <set>
#include <string>
#include <string.h>

#include <vector>

#include <system/audio.h>
#include <utils/Log.h>
#include <utils/Vector.h>
@@ -42,37 +43,37 @@ struct DefaultTraits
    }
};
template <typename T>
struct VectorTraits
struct SortedVectorTraits
{
    typedef T Type;
    typedef Vector<Type> Collection;
    typedef SortedVector<Type> Collection;
    static void add(Collection &collection, Type value)
    {
        collection.add(value);
    }
};
template <typename T>
struct SortedVectorTraits
struct SetTraits
{
    typedef T Type;
    typedef SortedVector<Type> Collection;
    typedef std::set<Type> Collection;
    static void add(Collection &collection, Type value)
    {
        collection.add(value);
        collection.insert(value);
    }
};

using SampleRateTraits = SortedVectorTraits<uint32_t>;
using SampleRateTraits = SetTraits<uint32_t>;
using DeviceTraits = DefaultTraits<audio_devices_t>;
struct OutputDeviceTraits : public DeviceTraits {};
struct InputDeviceTraits : public DeviceTraits {};
using ChannelTraits = SortedVectorTraits<audio_channel_mask_t>;
using ChannelTraits = SetTraits<audio_channel_mask_t>;
struct OutputChannelTraits : public ChannelTraits {};
struct InputChannelTraits : public ChannelTraits {};
struct ChannelIndexTraits : public ChannelTraits {};
using InputFlagTraits = DefaultTraits<audio_input_flags_t>;
using OutputFlagTraits = DefaultTraits<audio_output_flags_t>;
using FormatTraits = VectorTraits<audio_format_t>;
using FormatTraits = DefaultTraits<audio_format_t>;
using GainModeTraits = DefaultTraits<audio_gain_mode_t>;
using StreamTraits = DefaultTraits<audio_stream_type_t>;
using AudioModeTraits = DefaultTraits<audio_mode_t>;
@@ -259,6 +260,7 @@ template <typename T, std::enable_if_t<std::is_same<T, audio_content_type_t>::va
                                    || std::is_same<T, audio_source_t>::value
                                    || std::is_same<T, audio_stream_type_t>::value
                                    || std::is_same<T, audio_usage_t>::value
                                    || std::is_same<T, audio_format_t>::value
                                    , int> = 0>
static inline std::string toString(const T& value)
{
@@ -291,14 +293,6 @@ static inline std::string toString(const audio_devices_t& devices)
    return result;
}

// TODO: Remove when FormatTraits uses DefaultTraits.
static inline std::string toString(const audio_format_t& format)
{
    std::string result;
    return TypeConverter<VectorTraits<audio_format_t>>::toString(format, result)
            ? result : std::to_string(static_cast<int>(format));
}

static inline std::string toString(const audio_attributes_t& attributes)
{
    std::ostringstream result;
+5 −4
Original line number Diff line number Diff line
@@ -143,8 +143,9 @@ public:
    AudioGains mGains; // gain controllers

private:
    void pickChannelMask(audio_channel_mask_t &channelMask, const ChannelsVector &channelMasks) const;
    void pickSamplingRate(uint32_t &rate,const SampleRateVector &samplingRates) const;
    void pickChannelMask(audio_channel_mask_t &channelMask,
                         const ChannelMaskSet &channelMasks) const;
    void pickSamplingRate(uint32_t &rate, const SampleRateSet &samplingRates) const;

    sp<HwModule> mModule;                 // audio HW module exposing this I/O stream
    String8  mName;
+19 −58
Original line number Diff line number Diff line
@@ -16,55 +16,15 @@

#pragma once

#include <vector>

#include <media/AudioContainers.h>
#include <system/audio.h>
#include <utils/RefBase.h>
#include <utils/SortedVector.h>
#include <utils/String8.h>

#include "policy.h"

namespace android {

typedef SortedVector<uint32_t> SampleRateVector;
typedef Vector<audio_format_t> FormatVector;

template <typename T>
bool operator== (const SortedVector<T> &left, const SortedVector<T> &right)
{
    if (left.size() != right.size()) {
        return false;
    }
    for (size_t index = 0; index < right.size(); index++) {
        if (left[index] != right[index]) {
            return false;
        }
    }
    return true;
}

template <typename T>
bool operator!= (const SortedVector<T> &left, const SortedVector<T> &right)
{
    return !(left == right);
}

class ChannelsVector : public SortedVector<audio_channel_mask_t>
{
public:
    ChannelsVector() = default;
    ChannelsVector(const ChannelsVector&) = default;
    ChannelsVector(const SortedVector<audio_channel_mask_t>& sv) :
            SortedVector<audio_channel_mask_t>(sv) {}
    ChannelsVector& operator=(const ChannelsVector&) = default;

    // Applies audio_channel_mask_out_to_in to all elements and returns the result.
    ChannelsVector asInMask() const;
    // Applies audio_channel_mask_in_to_out to all elements and returns the result.
    ChannelsVector asOutMask() const;
};

class AudioProfile : public virtual RefBase
{
public:
@@ -72,22 +32,22 @@ public:

    AudioProfile(audio_format_t format, audio_channel_mask_t channelMasks, uint32_t samplingRate);
    AudioProfile(audio_format_t format,
                 const ChannelsVector &channelMasks,
                 const SampleRateVector &samplingRateCollection);
                 const ChannelMaskSet &channelMasks,
                 const SampleRateSet &samplingRateCollection);

    audio_format_t getFormat() const { return mFormat; }
    const ChannelsVector &getChannels() const { return mChannelMasks; }
    const SampleRateVector &getSampleRates() const { return mSamplingRates; }
    void setChannels(const ChannelsVector &channelMasks);
    void setSampleRates(const SampleRateVector &sampleRates);
    const ChannelMaskSet &getChannels() const { return mChannelMasks; }
    const SampleRateSet &getSampleRates() const { return mSamplingRates; }
    void setChannels(const ChannelMaskSet &channelMasks);
    void setSampleRates(const SampleRateSet &sampleRates);

    void clear();
    bool isValid() const { return hasValidFormat() && hasValidRates() && hasValidChannels(); }
    bool supportsChannels(audio_channel_mask_t channels) const
    {
        return mChannelMasks.indexOf(channels) >= 0;
        return mChannelMasks.count(channels) != 0;
    }
    bool supportsRate(uint32_t rate) const { return mSamplingRates.indexOf(rate) >= 0; }
    bool supportsRate(uint32_t rate) const { return mSamplingRates.count(rate) != 0; }

    status_t checkExact(uint32_t rate, audio_channel_mask_t channels, audio_format_t format) const;
    status_t checkCompatibleChannelMask(audio_channel_mask_t channelMask,
@@ -98,8 +58,8 @@ public:
                                         uint32_t &updatedSamplingRate) const;

    bool hasValidFormat() const { return mFormat != AUDIO_FORMAT_DEFAULT; }
    bool hasValidRates() const { return !mSamplingRates.isEmpty(); }
    bool hasValidChannels() const { return !mChannelMasks.isEmpty(); }
    bool hasValidRates() const { return !mSamplingRates.empty(); }
    bool hasValidChannels() const { return !mChannelMasks.empty(); }

    void setDynamicChannels(bool dynamic) { mIsDynamicChannels = dynamic; }
    bool isDynamicChannels() const { return mIsDynamicChannels; }
@@ -117,8 +77,8 @@ public:
private:
    String8  mName;
    audio_format_t mFormat;
    ChannelsVector mChannelMasks;
    SampleRateVector mSamplingRates;
    ChannelMaskSet mChannelMasks;
    SampleRateSet mSamplingRates;

    bool mIsDynamicFormat = false;
    bool mIsDynamicChannels = false;
@@ -126,13 +86,16 @@ private:
};


class AudioProfileVector : public Vector<sp<AudioProfile> >
class AudioProfileVector : public std::vector<sp<AudioProfile> >
{
public:
    ssize_t add(const sp<AudioProfile> &profile);
    // This API is intended to be used by the policy manager once retrieving capabilities
    // for a profile with dynamic format, rate and channels attributes
    ssize_t addProfileFromHal(const sp<AudioProfile> &profileToAdd);
    void appendProfiles(const AudioProfileVector& audioProfiles) {
        insert(end(), audioProfiles.begin(), audioProfiles.end());
    }

    status_t checkExactProfile(uint32_t samplingRate, audio_channel_mask_t channelMask,
                               audio_format_t format) const;
@@ -169,10 +132,8 @@ public:

private:
    sp<AudioProfile> getProfileFor(audio_format_t format) const;
    void setSampleRatesFor(const SampleRateVector &sampleRates, audio_format_t format);
    void setChannelsFor(const ChannelsVector &channelMasks, audio_format_t format);

    static int compareFormats(const sp<AudioProfile> *profile1, const sp<AudioProfile> *profile2);
    void setSampleRatesFor(const SampleRateSet &sampleRates, audio_format_t format);
    void setChannelsFor(const ChannelMaskSet &channelMasks, audio_format_t format);
};

bool operator == (const AudioProfile &left, const AudioProfile &right);
+30 −48
Original line number Diff line number Diff line
@@ -64,30 +64,19 @@ void AudioPort::toAudioPort(struct audio_port *port) const
{
    // TODO: update this function once audio_port structure reflects the new profile definition.
    // For compatibility reason: flatening the AudioProfile into audio_port structure.
    SortedVector<audio_format_t> flatenedFormats;
    SampleRateVector flatenedRates;
    ChannelsVector flatenedChannels;
    FormatSet flatenedFormats;
    SampleRateSet flatenedRates;
    ChannelMaskSet flatenedChannels;
    for (const auto& profile : mProfiles) {
        if (profile->isValid()) {
            audio_format_t formatToExport = profile->getFormat();
            const SampleRateVector &ratesToExport = profile->getSampleRates();
            const ChannelsVector &channelsToExport = profile->getChannels();
            const SampleRateSet &ratesToExport = profile->getSampleRates();
            const ChannelMaskSet &channelsToExport = profile->getChannels();

            flatenedFormats.insert(formatToExport);
            flatenedRates.insert(ratesToExport.begin(), ratesToExport.end());
            flatenedChannels.insert(channelsToExport.begin(), channelsToExport.end());

            if (flatenedFormats.indexOf(formatToExport) < 0) {
                flatenedFormats.add(formatToExport);
            }
            for (size_t rateIndex = 0; rateIndex < ratesToExport.size(); rateIndex++) {
                uint32_t rate = ratesToExport[rateIndex];
                if (flatenedRates.indexOf(rate) < 0) {
                    flatenedRates.add(rate);
                }
            }
            for (size_t chanIndex = 0; chanIndex < channelsToExport.size(); chanIndex++) {
                audio_channel_mask_t channels = channelsToExport[chanIndex];
                if (flatenedChannels.indexOf(channels) < 0) {
                    flatenedChannels.add(channels);
                }
            }
            if (flatenedRates.size() > AUDIO_PORT_MAX_SAMPLING_RATES ||
                    flatenedChannels.size() > AUDIO_PORT_MAX_CHANNEL_MASKS ||
                    flatenedFormats.size() > AUDIO_PORT_MAX_FORMATS) {
@@ -102,23 +91,16 @@ void AudioPort::toAudioPort(struct audio_port *port) const
    port->num_sample_rates = flatenedRates.size();
    port->num_channel_masks = flatenedChannels.size();
    port->num_formats = flatenedFormats.size();
    for (size_t i = 0; i < flatenedRates.size(); i++) {
        port->sample_rates[i] = flatenedRates[i];
    }
    for (size_t i = 0; i < flatenedChannels.size(); i++) {
        port->channel_masks[i] = flatenedChannels[i];
    }
    for (size_t i = 0; i < flatenedFormats.size(); i++) {
        port->formats[i] = flatenedFormats[i];
    }
    std::copy(flatenedRates.begin(), flatenedRates.end(), port->sample_rates);
    std::copy(flatenedChannels.begin(), flatenedChannels.end(), port->channel_masks);
    std::copy(flatenedFormats.begin(), flatenedFormats.end(), port->formats);

    ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size());

    uint32_t i;
    for (i = 0; i < mGains.size() && i < AUDIO_PORT_MAX_GAINS; i++) {
    port->num_gains = std::min(mGains.size(), (size_t) AUDIO_PORT_MAX_GAINS);
    for (size_t i = 0; i < port->num_gains; i++) {
        port->gains[i] = mGains[i]->getGain();
    }
    port->num_gains = i;
}

void AudioPort::importAudioPort(const sp<AudioPort>& port, bool force __unused)
@@ -162,7 +144,7 @@ status_t AudioPort::checkExactAudioProfile(const struct audio_port_config *confi
    return status;
}

void AudioPort::pickSamplingRate(uint32_t &pickedRate,const SampleRateVector &samplingRates) const
void AudioPort::pickSamplingRate(uint32_t &pickedRate,const SampleRateSet &samplingRates) const
{
    pickedRate = 0;
    // For direct outputs, pick minimum sampling rate: this helps ensuring that the
@@ -170,9 +152,9 @@ void AudioPort::pickSamplingRate(uint32_t &pickedRate,const SampleRateVector &sa
    // sink
    if (isDirectOutput()) {
        uint32_t samplingRate = UINT_MAX;
        for (size_t i = 0; i < samplingRates.size(); i ++) {
            if ((samplingRates[i] < samplingRate) && (samplingRates[i] > 0)) {
                samplingRate = samplingRates[i];
        for (const auto rate : samplingRates) {
            if ((rate < samplingRate) && (rate > 0)) {
                samplingRate = rate;
            }
        }
        pickedRate = (samplingRate == UINT_MAX) ? 0 : samplingRate;
@@ -188,16 +170,16 @@ void AudioPort::pickSamplingRate(uint32_t &pickedRate,const SampleRateVector &sa
        // TODO: should mSamplingRates[] be ordered in terms of our preference
        // and we return the first (and hence most preferred) match?  This is of concern if
        // we want to choose 96kHz over 192kHz for USB driver stability or resource constraints.
        for (size_t i = 0; i < samplingRates.size(); i ++) {
            if ((samplingRates[i] > pickedRate) && (samplingRates[i] <= maxRate)) {
                pickedRate = samplingRates[i];
        for (const auto rate : samplingRates) {
            if ((rate > pickedRate) && (rate <= maxRate)) {
                pickedRate = rate;
            }
        }
    }
}

void AudioPort::pickChannelMask(audio_channel_mask_t &pickedChannelMask,
                                const ChannelsVector &channelMasks) const
                                const ChannelMaskSet &channelMasks) const
{
    pickedChannelMask = AUDIO_CHANNEL_NONE;
    // For direct outputs, pick minimum channel count: this helps ensuring that the
@@ -205,15 +187,15 @@ void AudioPort::pickChannelMask(audio_channel_mask_t &pickedChannelMask,
    // sink
    if (isDirectOutput()) {
        uint32_t channelCount = UINT_MAX;
        for (size_t i = 0; i < channelMasks.size(); i ++) {
        for (const auto channelMask : channelMasks) {
            uint32_t cnlCount;
            if (useInputChannelMask()) {
                cnlCount = audio_channel_count_from_in_mask(channelMasks[i]);
                cnlCount = audio_channel_count_from_in_mask(channelMask);
            } else {
                cnlCount = audio_channel_count_from_out_mask(channelMasks[i]);
                cnlCount = audio_channel_count_from_out_mask(channelMask);
            }
            if ((cnlCount < channelCount) && (cnlCount > 0)) {
                pickedChannelMask = channelMasks[i];
                pickedChannelMask = channelMask;
                channelCount = cnlCount;
            }
        }
@@ -226,15 +208,15 @@ void AudioPort::pickChannelMask(audio_channel_mask_t &pickedChannelMask,
        if (mType != AUDIO_PORT_TYPE_MIX) {
            maxCount = UINT_MAX;
        }
        for (size_t i = 0; i < channelMasks.size(); i ++) {
        for (const auto channelMask : channelMasks) {
            uint32_t cnlCount;
            if (useInputChannelMask()) {
                cnlCount = audio_channel_count_from_in_mask(channelMasks[i]);
                cnlCount = audio_channel_count_from_in_mask(channelMask);
            } else {
                cnlCount = audio_channel_count_from_out_mask(channelMasks[i]);
                cnlCount = audio_channel_count_from_out_mask(channelMask);
            }
            if ((cnlCount > channelCount) && (cnlCount <= maxCount)) {
                pickedChannelMask = channelMasks[i];
                pickedChannelMask = channelMask;
                channelCount = cnlCount;
            }
        }
Loading