Loading media/libaudiofoundation/Android.bp +4 −0 Original line number Diff line number Diff line Loading @@ -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", ], Loading media/libaudiofoundation/AudioPortBase.cpp 0 → 100644 +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 media/libaudiofoundation/AudioProfile.cpp 0 → 100644 +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 media/libaudiofoundation/include/media/AudioPortBase.h 0 → 100644 +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 services/audiopolicy/common/managerdefinitions/include/AudioProfile.h→media/libaudiofoundation/include/media/AudioProfile.h +17 −52 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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(); } Loading @@ -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; Loading @@ -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; Loading @@ -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 Loading
media/libaudiofoundation/Android.bp +4 −0 Original line number Diff line number Diff line Loading @@ -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", ], Loading
media/libaudiofoundation/AudioPortBase.cpp 0 → 100644 +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
media/libaudiofoundation/AudioProfile.cpp 0 → 100644 +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
media/libaudiofoundation/include/media/AudioPortBase.h 0 → 100644 +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
services/audiopolicy/common/managerdefinitions/include/AudioProfile.h→media/libaudiofoundation/include/media/AudioProfile.h +17 −52 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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(); } Loading @@ -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; Loading @@ -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; Loading @@ -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