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

Commit 1e415c05 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes I05611b70,I6cd1a53e,Ic2e08efc,I13ac0673,I0d87fd76

* changes:
  Add AudioPortFoundation, AudioPortBase and AudioPortConfigBase.
  Copy AudioPort.h to libaudiofoundation.
  Make AudioProfile as a common class and create AudioProfileVectorBase.
  Preparation for moving AudioProfile to libaudiofoundation.
  Return DeviceDescriptor or DeviceVector in Engine.
parents 8121bf7c eaf09f08
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -10,17 +10,21 @@ cc_library_shared {

    srcs: [
        "AudioGain.cpp",
        "AudioPortBase.cpp",
        "AudioProfile.cpp",
    ],

    shared_libs: [
        "libbase",
        "libbinder",
        "liblog",
        "libmedia_helper",
        "libutils",
    ],

    header_libs: [
        "libaudio_system_headers",
        "libaudioclient_headers",
        "libaudiofoundation_headers",
    ],

+87 −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.
 */

#include <algorithm>

#include <android-base/stringprintf.h>
#include <media/AudioPortBase.h>
#include <utils/Log.h>

namespace android {

void AudioPortFoundation::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.
    FormatSet flatenedFormats;
    SampleRateSet flatenedRates;
    ChannelMaskSet flatenedChannels;
    for (const auto& profile : *getAudioProfileVectorBase()) {
        if (profile->isValid()) {
            audio_format_t formatToExport = profile->getFormat();
            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 (flatenedRates.size() > AUDIO_PORT_MAX_SAMPLING_RATES ||
                    flatenedChannels.size() > AUDIO_PORT_MAX_CHANNEL_MASKS ||
                    flatenedFormats.size() > AUDIO_PORT_MAX_FORMATS) {
                ALOGE("%s: bailing out: cannot export profiles to port config", __func__);
                return;
            }
        }
    }
    port->role = mRole;
    port->type = mType;
    strlcpy(port->name, mName.c_str(), AUDIO_PORT_MAX_NAME_LEN);
    port->num_sample_rates = flatenedRates.size();
    port->num_channel_masks = flatenedChannels.size();
    port->num_formats = flatenedFormats.size();
    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());

    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();
    }
}

void AudioPortFoundation::dump(std::string *dst, int spaces, bool verbose) const {
    if (!mName.empty()) {
        dst->append(base::StringPrintf("%*s- name: %s\n", spaces, "", mName.c_str()));
    }
    if (verbose) {
        std::string profilesStr;
        getAudioProfileVectorBase()->dump(&profilesStr, spaces);
        dst->append(profilesStr);

        if (mGains.size() != 0) {
            dst->append(base::StringPrintf("%*s- gains:\n", spaces, ""));
            for (size_t i = 0; i < mGains.size(); i++) {
                std::string gainStr;
                mGains[i]->dump(&gainStr, spaces + 2, i);
                dst->append(gainStr);
            }
        }
    }
}

}
 No newline at end of file
+222 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 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.
 */

#include <set>

#define LOG_TAG "AudioProfile"
//#define LOG_NDEBUG 0

#include <android-base/stringprintf.h>
#include <media/AudioContainers.h>
#include <media/AudioProfile.h>
#include <media/TypeConverter.h>
#include <utils/Errors.h>

namespace android {

bool operator == (const AudioProfile &left, const AudioProfile &right)
{
    return (left.getFormat() == right.getFormat()) &&
            (left.getChannels() == right.getChannels()) &&
            (left.getSampleRates() == right.getSampleRates());
}

// static
sp<AudioProfile> AudioProfile::createFullDynamic(audio_format_t dynamicFormat)
{
    AudioProfile* dynamicProfile = new AudioProfile(dynamicFormat,
            ChannelMaskSet(), SampleRateSet());
    dynamicProfile->setDynamicFormat(true);
    dynamicProfile->setDynamicChannels(true);
    dynamicProfile->setDynamicRate(true);
    return dynamicProfile;
}

AudioProfile::AudioProfile(audio_format_t format,
                           audio_channel_mask_t channelMasks,
                           uint32_t samplingRate) :
        mName(""),
        mFormat(format)
{
    mChannelMasks.insert(channelMasks);
    mSamplingRates.insert(samplingRate);
}

AudioProfile::AudioProfile(audio_format_t format,
                           const ChannelMaskSet &channelMasks,
                           const SampleRateSet &samplingRateCollection) :
        mName(""),
        mFormat(format),
        mChannelMasks(channelMasks),
        mSamplingRates(samplingRateCollection) {}

void AudioProfile::setChannels(const ChannelMaskSet &channelMasks)
{
    if (mIsDynamicChannels) {
        mChannelMasks = channelMasks;
    }
}

void AudioProfile::setSampleRates(const SampleRateSet &sampleRates)
{
    if (mIsDynamicRate) {
        mSamplingRates = sampleRates;
    }
}

void AudioProfile::clear()
{
    if (mIsDynamicChannels) {
        mChannelMasks.clear();
    }
    if (mIsDynamicRate) {
        mSamplingRates.clear();
    }
}

void AudioProfile::dump(std::string *dst, int spaces) const
{
    dst->append(base::StringPrintf("%s%s%s\n", mIsDynamicFormat ? "[dynamic format]" : "",
             mIsDynamicChannels ? "[dynamic channels]" : "",
             mIsDynamicRate ? "[dynamic rates]" : ""));
    if (mName.length() != 0) {
        dst->append(base::StringPrintf("%*s- name: %s\n", spaces, "", mName.c_str()));
    }
    std::string formatLiteral;
    if (FormatConverter::toString(mFormat, formatLiteral)) {
        dst->append(base::StringPrintf("%*s- format: %s\n", spaces, "", formatLiteral.c_str()));
    }
    if (!mSamplingRates.empty()) {
        dst->append(base::StringPrintf("%*s- sampling rates:", spaces, ""));
        for (auto it = mSamplingRates.begin(); it != mSamplingRates.end();) {
            dst->append(base::StringPrintf("%d", *it));
            dst->append(++it == mSamplingRates.end() ? "" : ", ");
        }
        dst->append("\n");
    }

    if (!mChannelMasks.empty()) {
        dst->append(base::StringPrintf("%*s- channel masks:", spaces, ""));
        for (auto it = mChannelMasks.begin(); it != mChannelMasks.end();) {
            dst->append(base::StringPrintf("0x%04x", *it));
            dst->append(++it == mChannelMasks.end() ? "" : ", ");
        }
        dst->append("\n");
    }
}

ssize_t AudioProfileVectorBase::add(const sp<AudioProfile> &profile)
{
    ssize_t index = size();
    push_back(profile);
    return index;
}

void AudioProfileVectorBase::clearProfiles()
{
    for (auto it = begin(); it != end();) {
        if ((*it)->isDynamicFormat() && (*it)->hasValidFormat()) {
            it = erase(it);
        } else {
            (*it)->clear();
            ++it;
        }
    }
}

sp<AudioProfile> AudioProfileVectorBase::getFirstValidProfile() const
{
    for (const auto &profile : *this) {
        if (profile->isValid()) {
            return profile;
        }
    }
    return nullptr;
}

sp<AudioProfile> AudioProfileVectorBase::getFirstValidProfileFor(audio_format_t format) const
{
    for (const auto &profile : *this) {
        if (profile->isValid() && profile->getFormat() == format) {
            return profile;
        }
    }
    return nullptr;
}

FormatVector AudioProfileVectorBase::getSupportedFormats() const
{
    FormatVector supportedFormats;
    for (const auto &profile : *this) {
        if (profile->hasValidFormat()) {
            supportedFormats.push_back(profile->getFormat());
        }
    }
    return supportedFormats;
}

bool AudioProfileVectorBase::hasDynamicChannelsFor(audio_format_t format) const
{
    for (const auto &profile : *this) {
        if (profile->getFormat() == format && profile->isDynamicChannels()) {
            return true;
        }
    }
    return false;
}

bool AudioProfileVectorBase::hasDynamicFormat() const
{
    for (const auto &profile : *this) {
        if (profile->isDynamicFormat()) {
            return true;
        }
    }
    return false;
}

bool AudioProfileVectorBase::hasDynamicProfile() const
{
    for (const auto &profile : *this) {
        if (profile->isDynamic()) {
            return true;
        }
    }
    return false;
}

bool AudioProfileVectorBase::hasDynamicRateFor(audio_format_t format) const
{
    for (const auto &profile : *this) {
        if (profile->getFormat() == format && profile->isDynamicRate()) {
            return true;
        }
    }
    return false;
}

void AudioProfileVectorBase::dump(std::string *dst, int spaces) const
{
    dst->append(base::StringPrintf("%*s- Profiles:\n", spaces, ""));
    for (size_t i = 0; i < size(); i++) {
        dst->append(base::StringPrintf("%*sProfile %zu:", spaces + 4, "", i));
        std::string profileStr;
        at(i)->dump(&profileStr, spaces + 8);
        dst->append(profileStr);
    }
}

} // namespace android
+130 −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 <string>

#include <media/AudioGain.h>
#include <media/AudioProfile.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <system/audio.h>
#include <cutils/config_utils.h>

namespace android {

class AudioPortFoundation : public virtual RefBase
{
public:
    AudioPortFoundation(const std::string& name, audio_port_type_t type,  audio_port_role_t role) :
            mName(name), mType(type), mRole(role) {}

    virtual ~AudioPortFoundation() = default;

    void setName(const std::string &name) { mName = name; }
    const std::string &getName() const { return mName; }

    audio_port_type_t getType() const { return mType; }
    audio_port_role_t getRole() const { return mRole; }

    virtual const std::string getTagName() const = 0;

    void setGains(const AudioGains &gains) { mGains = gains; }
    const AudioGains &getGains() const { return mGains; }

    virtual void toAudioPort(struct audio_port *port) const;

    virtual AudioProfileVectorBase* getAudioProfileVectorBase() const = 0;
    virtual void addAudioProfile(const sp<AudioProfile> &profile) {
        getAudioProfileVectorBase()->add(profile);
    }
    virtual void clearAudioProfiles() {
        getAudioProfileVectorBase()->clearProfiles();
    }

    bool hasValidAudioProfile() const { return getAudioProfileVectorBase()->hasValidProfile(); }

    status_t checkGain(const struct audio_gain_config *gainConfig, int index) const {
        if (index < 0 || (size_t)index >= mGains.size()) {
            return BAD_VALUE;
        }
        return mGains[index]->checkConfig(gainConfig);
    }

    bool useInputChannelMask() const
    {
        return ((mType == AUDIO_PORT_TYPE_DEVICE) && (mRole == AUDIO_PORT_ROLE_SOURCE)) ||
                ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SINK));
    }

    void dump(std::string *dst, int spaces, bool verbose = true) const;

    AudioGains mGains; // gain controllers
protected:
    std::string  mName;
    audio_port_type_t mType;
    audio_port_role_t mRole;
};

template <typename ProfileVector,
          typename = typename std::enable_if<std::is_base_of<
                  AudioProfileVectorBase, ProfileVector>::value>::type>
class AudioPortBase : public AudioPortFoundation
{
public:
    AudioPortBase(const std::string& name, audio_port_type_t type,  audio_port_role_t role) :
            AudioPortFoundation(name, type, role) {}

    virtual ~AudioPortBase() {}

    AudioProfileVectorBase* getAudioProfileVectorBase() const override {
        return static_cast<AudioProfileVectorBase*>(const_cast<ProfileVector*>(&mProfiles));
    }

    void addAudioProfile(const sp<AudioProfile> &profile) override { mProfiles.add(profile); }
    void clearAudioProfiles() override { return mProfiles.clearProfiles(); }

    void setAudioProfiles(const ProfileVector &profiles) { mProfiles = profiles; }
    ProfileVector &getAudioProfiles() { return mProfiles; }

protected:
    ProfileVector mProfiles; // AudioProfiles supported by this port (format, Rates, Channels)
};


class AudioPortConfigBase : public virtual RefBase
{
public:
    virtual ~AudioPortConfigBase() = default;

    virtual status_t applyAudioPortConfig(const struct audio_port_config *config,
                                          struct audio_port_config *backupConfig = NULL) = 0;
    virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
                                   const struct audio_port_config *srcConfig = NULL) const = 0;

    unsigned int getSamplingRate() const { return mSamplingRate; }
    audio_format_t getFormat() const { return mFormat; }
    audio_channel_mask_t getChannelMask() const { return mChannelMask; }

protected:
    unsigned int mSamplingRate = 0u;
    audio_format_t mFormat = AUDIO_FORMAT_INVALID;
    audio_channel_mask_t mChannelMask = AUDIO_CHANNEL_NONE;
    struct audio_gain_config mGain = { .index = -1 };
};

} // namespace android
+17 −52
Original line number Diff line number Diff line
@@ -16,19 +16,19 @@

#pragma once

#include <string>
#include <vector>

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

#include "policy.h"

namespace android {

class AudioProfile : public virtual RefBase
class AudioProfile final : public RefBase
{
public:
    static sp<AudioProfile> createFullDynamic();
    static sp<AudioProfile> createFullDynamic(audio_format_t dynamicFormat = AUDIO_FORMAT_DEFAULT);

    AudioProfile(audio_format_t format, audio_channel_mask_t channelMasks, uint32_t samplingRate);
    AudioProfile(audio_format_t format,
@@ -49,14 +49,6 @@ public:
    }
    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,
                                        audio_channel_mask_t &updatedChannelMask,
                                        audio_port_type_t portType,
                                        audio_port_role_t portRole) const;
    status_t checkCompatibleSamplingRate(uint32_t samplingRate,
                                         uint32_t &updatedSamplingRate) const;

    bool hasValidFormat() const { return mFormat != AUDIO_FORMAT_DEFAULT; }
    bool hasValidRates() const { return !mSamplingRates.empty(); }
    bool hasValidChannels() const { return !mChannelMasks.empty(); }
@@ -72,11 +64,11 @@ public:

    bool isDynamic() { return mIsDynamicFormat || mIsDynamicChannels || mIsDynamicRate; }

    void dump(String8 *dst, int spaces) const;
    void dump(std::string *dst, int spaces) const;

private:
    String8  mName;
    audio_format_t mFormat;
    std::string  mName;
    audio_format_t mFormat; // The format for an audio profile should only be set when initialized.
    ChannelMaskSet mChannelMasks;
    SampleRateSet mSamplingRates;

@@ -85,35 +77,16 @@ private:
    bool mIsDynamicRate = false;
};


class AudioProfileVector : public std::vector<sp<AudioProfile> >
class AudioProfileVectorBase : 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());
    }
    virtual ~AudioProfileVectorBase() = default;

    status_t checkExactProfile(uint32_t samplingRate, audio_channel_mask_t channelMask,
                               audio_format_t format) const;
    status_t checkCompatibleProfile(uint32_t &samplingRate, audio_channel_mask_t &channelMask,
                                    audio_format_t &format,
                                    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;
    virtual ssize_t add(const sp<AudioProfile> &profile);

    // If the profile is dynamic format and has valid format, it will be removed when doing
    // clearProfiles(). Otherwise, AudioProfile::clear() will be called.
    virtual void clearProfiles();

    sp<AudioProfile> getFirstValidProfile() const;
    sp<AudioProfile> getFirstValidProfileFor(audio_format_t format) const;
@@ -121,19 +94,11 @@ public:

    FormatVector getSupportedFormats() const;
    bool hasDynamicChannelsFor(audio_format_t format) const;
    bool hasDynamicFormat() const { return getProfileFor(gDynamicFormat) != 0; }
    bool hasDynamicFormat() const;
    bool hasDynamicProfile() const;
    bool hasDynamicRateFor(audio_format_t format) const;

    // One audio profile will be added for each format supported by Audio HAL
    void setFormats(const FormatVector &formats);

    void dump(String8 *dst, int spaces) const;

private:
    sp<AudioProfile> getProfileFor(audio_format_t format) const;
    void setSampleRatesFor(const SampleRateSet &sampleRates, audio_format_t format);
    void setChannelsFor(const ChannelMaskSet &channelMasks, audio_format_t format);
    virtual void dump(std::string *dst, int spaces) const;
};

bool operator == (const AudioProfile &left, const AudioProfile &right);
Loading