Loading services/audiopolicy/common/managerdefinitions/include/AudioProfile.h +28 −255 Original line number Diff line number Diff line Loading @@ -16,13 +16,12 @@ #pragma once #include "policy.h" #include <utils/String8.h> #include <utils/SortedVector.h> #include <utils/RefBase.h> #include <utils/Errors.h> #include <system/audio.h> #include <cutils/config_utils.h> #include <utils/RefBase.h> #include <utils/SortedVector.h> #include <utils/String8.h> #include "policy.h" namespace android { Loading Loading @@ -69,71 +68,30 @@ class AudioProfile : public virtual RefBase public: static sp<AudioProfile> createFullDynamic(); AudioProfile(audio_format_t format, audio_channel_mask_t channelMasks, uint32_t samplingRate) : mName(String8("")), mFormat(format) { mChannelMasks.add(channelMasks); mSamplingRates.add(samplingRate); } AudioProfile(audio_format_t format, audio_channel_mask_t channelMasks, uint32_t samplingRate); AudioProfile(audio_format_t format, const ChannelsVector &channelMasks, const SampleRateVector &samplingRateCollection) : mName(String8("")), mFormat(format), mChannelMasks(channelMasks), mSamplingRates(samplingRateCollection) {} const SampleRateVector &samplingRateCollection); audio_format_t getFormat() const { return mFormat; } void setChannels(const ChannelsVector &channelMasks) { if (mIsDynamicChannels) { mChannelMasks = channelMasks; } } const ChannelsVector &getChannels() const { return mChannelMasks; } void setSampleRates(const SampleRateVector &sampleRates) { if (mIsDynamicRate) { mSamplingRates = sampleRates; } } const SampleRateVector &getSampleRates() const { return mSamplingRates; } void setChannels(const ChannelsVector &channelMasks); void setSampleRates(const SampleRateVector &sampleRates); void clear(); bool isValid() const { return hasValidFormat() && hasValidRates() && hasValidChannels(); } void clear() { if (mIsDynamicChannels) { mChannelMasks.clear(); } if (mIsDynamicRate) { mSamplingRates.clear(); } } inline bool supportsChannels(audio_channel_mask_t channels) const bool supportsChannels(audio_channel_mask_t channels) const { return mChannelMasks.indexOf(channels) >= 0; } inline bool supportsRate(uint32_t rate) const { return mSamplingRates.indexOf(rate) >= 0; } bool supportsRate(uint32_t rate) const { return mSamplingRates.indexOf(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; Loading Loading @@ -169,223 +127,38 @@ private: class AudioProfileVector : public Vector<sp<AudioProfile> > { public: ssize_t add(const sp<AudioProfile> &profile) { ssize_t index = Vector::add(profile); // we sort from worst to best, so that AUDIO_FORMAT_DEFAULT is always the first entry. // TODO: compareFormats could be a lambda to convert between pointer-to-format to format: // [](const audio_format_t *format1, const audio_format_t *format2) { // return compareFormats(*format1, *format2); // } sort(compareFormats); return index; } 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) { // Check valid profile to add: if (!profileToAdd->hasValidFormat()) { return -1; } if (!profileToAdd->hasValidChannels() && !profileToAdd->hasValidRates()) { FormatVector formats; formats.add(profileToAdd->getFormat()); setFormats(FormatVector(formats)); return 0; } if (!profileToAdd->hasValidChannels() && profileToAdd->hasValidRates()) { setSampleRatesFor(profileToAdd->getSampleRates(), profileToAdd->getFormat()); return 0; } if (profileToAdd->hasValidChannels() && !profileToAdd->hasValidRates()) { setChannelsFor(profileToAdd->getChannels(), profileToAdd->getFormat()); return 0; } // Go through the list of profile to avoid duplicates for (size_t profileIndex = 0; profileIndex < size(); profileIndex++) { const sp<AudioProfile> &profile = itemAt(profileIndex); if (profile->isValid() && profile == profileToAdd) { // Nothing to do return profileIndex; } } profileToAdd->setDynamicFormat(true); // set the format as dynamic to allow removal return add(profileToAdd); } sp<AudioProfile> getFirstValidProfile() const { for (size_t i = 0; i < size(); i++) { if (itemAt(i)->isValid()) { return itemAt(i); } } return 0; } sp<AudioProfile> getFirstValidProfileFor(audio_format_t format) const { for (size_t i = 0; i < size(); i++) { if (itemAt(i)->isValid() && itemAt(i)->getFormat() == format) { return itemAt(i); } } return 0; } bool hasValidProfile() const { return getFirstValidProfile() != 0; } ssize_t addProfileFromHal(const sp<AudioProfile> &profileToAdd); 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(); FormatVector getSupportedFormats() const { FormatVector supportedFormats; for (size_t i = 0; i < size(); i++) { if (itemAt(i)->hasValidFormat()) { supportedFormats.add(itemAt(i)->getFormat()); } } return supportedFormats; } bool hasDynamicProfile() const { for (size_t i = 0; i < size(); i++) { if (itemAt(i)->isDynamic()) { return true; } } return false; } bool hasDynamicFormat() const { return getProfileFor(gDynamicFormat) != 0; } bool hasDynamicChannelsFor(audio_format_t format) const { for (size_t i = 0; i < size(); i++) { sp<AudioProfile> profile = itemAt(i); if (profile->getFormat() == format && profile->isDynamicChannels()) { return true; } } return false; } sp<AudioProfile> getFirstValidProfile() const; sp<AudioProfile> getFirstValidProfileFor(audio_format_t format) const; bool hasValidProfile() const { return getFirstValidProfile() != 0; } bool hasDynamicRateFor(audio_format_t format) const { for (size_t i = 0; i < size(); i++) { sp<AudioProfile> profile = itemAt(i); if (profile->getFormat() == format && profile->isDynamicRate()) { return true; } } return false; } FormatVector getSupportedFormats() const; bool hasDynamicChannelsFor(audio_format_t format) const; bool hasDynamicFormat() const { return getProfileFor(gDynamicFormat) != 0; } 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) { // Only allow to change the format of dynamic profile sp<AudioProfile> dynamicFormatProfile = getProfileFor(gDynamicFormat); if (dynamicFormatProfile == 0) { return; } for (size_t i = 0; i < formats.size(); i++) { sp<AudioProfile> profile = new AudioProfile(formats[i], dynamicFormatProfile->getChannels(), dynamicFormatProfile->getSampleRates()); profile->setDynamicFormat(true); profile->setDynamicChannels(dynamicFormatProfile->isDynamicChannels()); profile->setDynamicRate(dynamicFormatProfile->isDynamicRate()); add(profile); } } void clearProfiles() { for (size_t i = size(); i != 0; ) { sp<AudioProfile> profile = itemAt(--i); if (profile->isDynamicFormat() && profile->hasValidFormat()) { removeAt(i); continue; } profile->clear(); } } void setFormats(const FormatVector &formats); void dump(int fd, int spaces) const { const size_t SIZE = 256; char buffer[SIZE]; snprintf(buffer, SIZE, "%*s- Profiles:\n", spaces, ""); write(fd, buffer, strlen(buffer)); for (size_t i = 0; i < size(); i++) { snprintf(buffer, SIZE, "%*sProfile %zu:", spaces + 4, "", i); write(fd, buffer, strlen(buffer)); itemAt(i)->dump(fd, spaces + 8); } } void dump(int fd, int spaces) const; private: void setSampleRatesFor(const SampleRateVector &sampleRates, audio_format_t format) { for (size_t i = 0; i < size(); i++) { sp<AudioProfile> profile = itemAt(i); if (profile->getFormat() == format && profile->isDynamicRate()) { if (profile->hasValidRates()) { // Need to create a new profile with same format sp<AudioProfile> profileToAdd = new AudioProfile(format, profile->getChannels(), sampleRates); profileToAdd->setDynamicFormat(true); // need to set to allow cleaning add(profileToAdd); } else { profile->setSampleRates(sampleRates); } return; } } } void setChannelsFor(const ChannelsVector &channelMasks, audio_format_t format) { for (size_t i = 0; i < size(); i++) { sp<AudioProfile> profile = itemAt(i); if (profile->getFormat() == format && profile->isDynamicChannels()) { if (profile->hasValidChannels()) { // Need to create a new profile with same format sp<AudioProfile> profileToAdd = new AudioProfile(format, channelMasks, profile->getSampleRates()); profileToAdd->setDynamicFormat(true); // need to set to allow cleaning add(profileToAdd); } else { profile->setChannels(channelMasks); } return; } } } sp<AudioProfile> getProfileFor(audio_format_t format) const { for (size_t i = 0; i < size(); i++) { if (itemAt(i)->getFormat() == format) { return itemAt(i); } } return 0; } 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); }; Loading services/audiopolicy/common/managerdefinitions/src/AudioProfile.cpp +257 −12 Original line number Diff line number Diff line Loading @@ -14,17 +14,19 @@ * limitations under the License. */ #include <string> #define LOG_TAG "APM::AudioProfile" //#define LOG_NDEBUG 0 #include "AudioProfile.h" #include <media/AudioResamplerPublic.h> #include <utils/Errors.h> #include "AudioGain.h" #include "AudioPort.h" #include "AudioProfile.h" #include "HwModule.h" #include "AudioGain.h" #include <utils/SortedVector.h> #include "TypeConverter.h" #include <media/AudioResamplerPublic.h> #include <algorithm> namespace android { Loading @@ -50,6 +52,13 @@ ChannelsVector ChannelsVector::asOutMask() const return outMaskVector; } bool operator == (const AudioProfile &left, const AudioProfile &compareTo) { return (left.getFormat() == compareTo.getFormat()) && (left.getChannels() == compareTo.getChannels()) && (left.getSampleRates() == compareTo.getSampleRates()); } static AudioProfile* createFullDynamicImpl() { AudioProfile* dynamicProfile = new AudioProfile(gDynamicFormat, Loading @@ -67,6 +76,48 @@ sp<AudioProfile> AudioProfile::createFullDynamic() return dynamicProfile; } AudioProfile::AudioProfile(audio_format_t format, audio_channel_mask_t channelMasks, uint32_t samplingRate) : mName(String8("")), mFormat(format) { mChannelMasks.add(channelMasks); mSamplingRates.add(samplingRate); } AudioProfile::AudioProfile(audio_format_t format, const ChannelsVector &channelMasks, const SampleRateVector &samplingRateCollection) : mName(String8("")), mFormat(format), mChannelMasks(channelMasks), mSamplingRates(samplingRateCollection) {} void AudioProfile::setChannels(const ChannelsVector &channelMasks) { if (mIsDynamicChannels) { mChannelMasks = channelMasks; } } void AudioProfile::setSampleRates(const SampleRateVector &sampleRates) { if (mIsDynamicRate) { mSamplingRates = sampleRates; } } void AudioProfile::clear() { if (mIsDynamicChannels) { mChannelMasks.clear(); } if (mIsDynamicRate) { mSamplingRates.clear(); } } status_t AudioProfile::checkExact(uint32_t samplingRate, audio_channel_mask_t channelMask, audio_format_t format) const { Loading @@ -78,13 +129,6 @@ status_t AudioProfile::checkExact(uint32_t samplingRate, audio_channel_mask_t ch return BAD_VALUE; } bool operator == (const AudioProfile &left, const AudioProfile &compareTo) { return (left.getFormat() == compareTo.getFormat()) && (left.getChannels() == compareTo.getChannels()) && (left.getSampleRates() == compareTo.getSampleRates()); } status_t AudioProfile::checkCompatibleSamplingRate(uint32_t samplingRate, uint32_t &updatedSamplingRate) const { Loading Loading @@ -250,6 +294,50 @@ void AudioProfile::dump(int fd, int spaces) const write(fd, result.string(), result.size()); } ssize_t AudioProfileVector::add(const sp<AudioProfile> &profile) { ssize_t index = Vector::add(profile); // we sort from worst to best, so that AUDIO_FORMAT_DEFAULT is always the first entry. // TODO: compareFormats could be a lambda to convert between pointer-to-format to format: // [](const audio_format_t *format1, const audio_format_t *format2) { // return compareFormats(*format1, *format2); // } sort(compareFormats); return index; } ssize_t AudioProfileVector::addProfileFromHal(const sp<AudioProfile> &profileToAdd) { // Check valid profile to add: if (!profileToAdd->hasValidFormat()) { return -1; } if (!profileToAdd->hasValidChannels() && !profileToAdd->hasValidRates()) { FormatVector formats; formats.add(profileToAdd->getFormat()); setFormats(FormatVector(formats)); return 0; } if (!profileToAdd->hasValidChannels() && profileToAdd->hasValidRates()) { setSampleRatesFor(profileToAdd->getSampleRates(), profileToAdd->getFormat()); return 0; } if (profileToAdd->hasValidChannels() && !profileToAdd->hasValidRates()) { setChannelsFor(profileToAdd->getChannels(), profileToAdd->getFormat()); return 0; } // Go through the list of profile to avoid duplicates for (size_t profileIndex = 0; profileIndex < size(); profileIndex++) { const sp<AudioProfile> &profile = itemAt(profileIndex); if (profile->isValid() && profile == profileToAdd) { // Nothing to do return profileIndex; } } profileToAdd->setDynamicFormat(true); // set the format as dynamic to allow removal return add(profileToAdd); } status_t AudioProfileVector::checkExactProfile(uint32_t samplingRate, audio_channel_mask_t channelMask, audio_format_t format) const Loading Loading @@ -306,6 +394,163 @@ status_t AudioProfileVector::checkCompatibleProfile(uint32_t &samplingRate, return BAD_VALUE; } void AudioProfileVector::clearProfiles() { for (size_t i = size(); i != 0; ) { sp<AudioProfile> profile = itemAt(--i); if (profile->isDynamicFormat() && profile->hasValidFormat()) { removeAt(i); continue; } profile->clear(); } } sp<AudioProfile> AudioProfileVector::getFirstValidProfile() const { for (size_t i = 0; i < size(); i++) { if (itemAt(i)->isValid()) { return itemAt(i); } } return 0; } sp<AudioProfile> AudioProfileVector::getFirstValidProfileFor(audio_format_t format) const { for (size_t i = 0; i < size(); i++) { if (itemAt(i)->isValid() && itemAt(i)->getFormat() == format) { return itemAt(i); } } return 0; } FormatVector AudioProfileVector::getSupportedFormats() const { FormatVector supportedFormats; for (size_t i = 0; i < size(); i++) { if (itemAt(i)->hasValidFormat()) { supportedFormats.add(itemAt(i)->getFormat()); } } return supportedFormats; } bool AudioProfileVector::hasDynamicChannelsFor(audio_format_t format) const { for (size_t i = 0; i < size(); i++) { sp<AudioProfile> profile = itemAt(i); if (profile->getFormat() == format && profile->isDynamicChannels()) { return true; } } return false; } bool AudioProfileVector::hasDynamicProfile() const { for (size_t i = 0; i < size(); i++) { if (itemAt(i)->isDynamic()) { return true; } } return false; } bool AudioProfileVector::hasDynamicRateFor(audio_format_t format) const { for (size_t i = 0; i < size(); i++) { sp<AudioProfile> profile = itemAt(i); if (profile->getFormat() == format && profile->isDynamicRate()) { return true; } } return false; } void AudioProfileVector::setFormats(const FormatVector &formats) { // Only allow to change the format of dynamic profile sp<AudioProfile> dynamicFormatProfile = getProfileFor(gDynamicFormat); if (dynamicFormatProfile == 0) { return; } for (size_t i = 0; i < formats.size(); i++) { sp<AudioProfile> profile = new AudioProfile(formats[i], dynamicFormatProfile->getChannels(), dynamicFormatProfile->getSampleRates()); profile->setDynamicFormat(true); profile->setDynamicChannels(dynamicFormatProfile->isDynamicChannels()); profile->setDynamicRate(dynamicFormatProfile->isDynamicRate()); add(profile); } } void AudioProfileVector::dump(int fd, int spaces) const { const size_t SIZE = 256; char buffer[SIZE]; snprintf(buffer, SIZE, "%*s- Profiles:\n", spaces, ""); write(fd, buffer, strlen(buffer)); for (size_t i = 0; i < size(); i++) { snprintf(buffer, SIZE, "%*sProfile %zu:", spaces + 4, "", i); write(fd, buffer, strlen(buffer)); itemAt(i)->dump(fd, spaces + 8); } } sp<AudioProfile> AudioProfileVector::getProfileFor(audio_format_t format) const { for (size_t i = 0; i < size(); i++) { if (itemAt(i)->getFormat() == format) { return itemAt(i); } } return 0; } void AudioProfileVector::setSampleRatesFor( const SampleRateVector &sampleRates, audio_format_t format) { for (size_t i = 0; i < size(); i++) { sp<AudioProfile> profile = itemAt(i); if (profile->getFormat() == format && profile->isDynamicRate()) { if (profile->hasValidRates()) { // Need to create a new profile with same format sp<AudioProfile> profileToAdd = new AudioProfile(format, profile->getChannels(), sampleRates); profileToAdd->setDynamicFormat(true); // need to set to allow cleaning add(profileToAdd); } else { profile->setSampleRates(sampleRates); } return; } } } void AudioProfileVector::setChannelsFor(const ChannelsVector &channelMasks, audio_format_t format) { for (size_t i = 0; i < size(); i++) { sp<AudioProfile> profile = itemAt(i); if (profile->getFormat() == format && profile->isDynamicChannels()) { if (profile->hasValidChannels()) { // Need to create a new profile with same format sp<AudioProfile> profileToAdd = new AudioProfile(format, channelMasks, profile->getSampleRates()); profileToAdd->setDynamicFormat(true); // need to set to allow cleaning add(profileToAdd); } else { profile->setChannels(channelMasks); } return; } } } // static int AudioProfileVector::compareFormats(const sp<AudioProfile> *profile1, const sp<AudioProfile> *profile2) { Loading Loading
services/audiopolicy/common/managerdefinitions/include/AudioProfile.h +28 −255 Original line number Diff line number Diff line Loading @@ -16,13 +16,12 @@ #pragma once #include "policy.h" #include <utils/String8.h> #include <utils/SortedVector.h> #include <utils/RefBase.h> #include <utils/Errors.h> #include <system/audio.h> #include <cutils/config_utils.h> #include <utils/RefBase.h> #include <utils/SortedVector.h> #include <utils/String8.h> #include "policy.h" namespace android { Loading Loading @@ -69,71 +68,30 @@ class AudioProfile : public virtual RefBase public: static sp<AudioProfile> createFullDynamic(); AudioProfile(audio_format_t format, audio_channel_mask_t channelMasks, uint32_t samplingRate) : mName(String8("")), mFormat(format) { mChannelMasks.add(channelMasks); mSamplingRates.add(samplingRate); } AudioProfile(audio_format_t format, audio_channel_mask_t channelMasks, uint32_t samplingRate); AudioProfile(audio_format_t format, const ChannelsVector &channelMasks, const SampleRateVector &samplingRateCollection) : mName(String8("")), mFormat(format), mChannelMasks(channelMasks), mSamplingRates(samplingRateCollection) {} const SampleRateVector &samplingRateCollection); audio_format_t getFormat() const { return mFormat; } void setChannels(const ChannelsVector &channelMasks) { if (mIsDynamicChannels) { mChannelMasks = channelMasks; } } const ChannelsVector &getChannels() const { return mChannelMasks; } void setSampleRates(const SampleRateVector &sampleRates) { if (mIsDynamicRate) { mSamplingRates = sampleRates; } } const SampleRateVector &getSampleRates() const { return mSamplingRates; } void setChannels(const ChannelsVector &channelMasks); void setSampleRates(const SampleRateVector &sampleRates); void clear(); bool isValid() const { return hasValidFormat() && hasValidRates() && hasValidChannels(); } void clear() { if (mIsDynamicChannels) { mChannelMasks.clear(); } if (mIsDynamicRate) { mSamplingRates.clear(); } } inline bool supportsChannels(audio_channel_mask_t channels) const bool supportsChannels(audio_channel_mask_t channels) const { return mChannelMasks.indexOf(channels) >= 0; } inline bool supportsRate(uint32_t rate) const { return mSamplingRates.indexOf(rate) >= 0; } bool supportsRate(uint32_t rate) const { return mSamplingRates.indexOf(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; Loading Loading @@ -169,223 +127,38 @@ private: class AudioProfileVector : public Vector<sp<AudioProfile> > { public: ssize_t add(const sp<AudioProfile> &profile) { ssize_t index = Vector::add(profile); // we sort from worst to best, so that AUDIO_FORMAT_DEFAULT is always the first entry. // TODO: compareFormats could be a lambda to convert between pointer-to-format to format: // [](const audio_format_t *format1, const audio_format_t *format2) { // return compareFormats(*format1, *format2); // } sort(compareFormats); return index; } 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) { // Check valid profile to add: if (!profileToAdd->hasValidFormat()) { return -1; } if (!profileToAdd->hasValidChannels() && !profileToAdd->hasValidRates()) { FormatVector formats; formats.add(profileToAdd->getFormat()); setFormats(FormatVector(formats)); return 0; } if (!profileToAdd->hasValidChannels() && profileToAdd->hasValidRates()) { setSampleRatesFor(profileToAdd->getSampleRates(), profileToAdd->getFormat()); return 0; } if (profileToAdd->hasValidChannels() && !profileToAdd->hasValidRates()) { setChannelsFor(profileToAdd->getChannels(), profileToAdd->getFormat()); return 0; } // Go through the list of profile to avoid duplicates for (size_t profileIndex = 0; profileIndex < size(); profileIndex++) { const sp<AudioProfile> &profile = itemAt(profileIndex); if (profile->isValid() && profile == profileToAdd) { // Nothing to do return profileIndex; } } profileToAdd->setDynamicFormat(true); // set the format as dynamic to allow removal return add(profileToAdd); } sp<AudioProfile> getFirstValidProfile() const { for (size_t i = 0; i < size(); i++) { if (itemAt(i)->isValid()) { return itemAt(i); } } return 0; } sp<AudioProfile> getFirstValidProfileFor(audio_format_t format) const { for (size_t i = 0; i < size(); i++) { if (itemAt(i)->isValid() && itemAt(i)->getFormat() == format) { return itemAt(i); } } return 0; } bool hasValidProfile() const { return getFirstValidProfile() != 0; } ssize_t addProfileFromHal(const sp<AudioProfile> &profileToAdd); 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(); FormatVector getSupportedFormats() const { FormatVector supportedFormats; for (size_t i = 0; i < size(); i++) { if (itemAt(i)->hasValidFormat()) { supportedFormats.add(itemAt(i)->getFormat()); } } return supportedFormats; } bool hasDynamicProfile() const { for (size_t i = 0; i < size(); i++) { if (itemAt(i)->isDynamic()) { return true; } } return false; } bool hasDynamicFormat() const { return getProfileFor(gDynamicFormat) != 0; } bool hasDynamicChannelsFor(audio_format_t format) const { for (size_t i = 0; i < size(); i++) { sp<AudioProfile> profile = itemAt(i); if (profile->getFormat() == format && profile->isDynamicChannels()) { return true; } } return false; } sp<AudioProfile> getFirstValidProfile() const; sp<AudioProfile> getFirstValidProfileFor(audio_format_t format) const; bool hasValidProfile() const { return getFirstValidProfile() != 0; } bool hasDynamicRateFor(audio_format_t format) const { for (size_t i = 0; i < size(); i++) { sp<AudioProfile> profile = itemAt(i); if (profile->getFormat() == format && profile->isDynamicRate()) { return true; } } return false; } FormatVector getSupportedFormats() const; bool hasDynamicChannelsFor(audio_format_t format) const; bool hasDynamicFormat() const { return getProfileFor(gDynamicFormat) != 0; } 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) { // Only allow to change the format of dynamic profile sp<AudioProfile> dynamicFormatProfile = getProfileFor(gDynamicFormat); if (dynamicFormatProfile == 0) { return; } for (size_t i = 0; i < formats.size(); i++) { sp<AudioProfile> profile = new AudioProfile(formats[i], dynamicFormatProfile->getChannels(), dynamicFormatProfile->getSampleRates()); profile->setDynamicFormat(true); profile->setDynamicChannels(dynamicFormatProfile->isDynamicChannels()); profile->setDynamicRate(dynamicFormatProfile->isDynamicRate()); add(profile); } } void clearProfiles() { for (size_t i = size(); i != 0; ) { sp<AudioProfile> profile = itemAt(--i); if (profile->isDynamicFormat() && profile->hasValidFormat()) { removeAt(i); continue; } profile->clear(); } } void setFormats(const FormatVector &formats); void dump(int fd, int spaces) const { const size_t SIZE = 256; char buffer[SIZE]; snprintf(buffer, SIZE, "%*s- Profiles:\n", spaces, ""); write(fd, buffer, strlen(buffer)); for (size_t i = 0; i < size(); i++) { snprintf(buffer, SIZE, "%*sProfile %zu:", spaces + 4, "", i); write(fd, buffer, strlen(buffer)); itemAt(i)->dump(fd, spaces + 8); } } void dump(int fd, int spaces) const; private: void setSampleRatesFor(const SampleRateVector &sampleRates, audio_format_t format) { for (size_t i = 0; i < size(); i++) { sp<AudioProfile> profile = itemAt(i); if (profile->getFormat() == format && profile->isDynamicRate()) { if (profile->hasValidRates()) { // Need to create a new profile with same format sp<AudioProfile> profileToAdd = new AudioProfile(format, profile->getChannels(), sampleRates); profileToAdd->setDynamicFormat(true); // need to set to allow cleaning add(profileToAdd); } else { profile->setSampleRates(sampleRates); } return; } } } void setChannelsFor(const ChannelsVector &channelMasks, audio_format_t format) { for (size_t i = 0; i < size(); i++) { sp<AudioProfile> profile = itemAt(i); if (profile->getFormat() == format && profile->isDynamicChannels()) { if (profile->hasValidChannels()) { // Need to create a new profile with same format sp<AudioProfile> profileToAdd = new AudioProfile(format, channelMasks, profile->getSampleRates()); profileToAdd->setDynamicFormat(true); // need to set to allow cleaning add(profileToAdd); } else { profile->setChannels(channelMasks); } return; } } } sp<AudioProfile> getProfileFor(audio_format_t format) const { for (size_t i = 0; i < size(); i++) { if (itemAt(i)->getFormat() == format) { return itemAt(i); } } return 0; } 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); }; Loading
services/audiopolicy/common/managerdefinitions/src/AudioProfile.cpp +257 −12 Original line number Diff line number Diff line Loading @@ -14,17 +14,19 @@ * limitations under the License. */ #include <string> #define LOG_TAG "APM::AudioProfile" //#define LOG_NDEBUG 0 #include "AudioProfile.h" #include <media/AudioResamplerPublic.h> #include <utils/Errors.h> #include "AudioGain.h" #include "AudioPort.h" #include "AudioProfile.h" #include "HwModule.h" #include "AudioGain.h" #include <utils/SortedVector.h> #include "TypeConverter.h" #include <media/AudioResamplerPublic.h> #include <algorithm> namespace android { Loading @@ -50,6 +52,13 @@ ChannelsVector ChannelsVector::asOutMask() const return outMaskVector; } bool operator == (const AudioProfile &left, const AudioProfile &compareTo) { return (left.getFormat() == compareTo.getFormat()) && (left.getChannels() == compareTo.getChannels()) && (left.getSampleRates() == compareTo.getSampleRates()); } static AudioProfile* createFullDynamicImpl() { AudioProfile* dynamicProfile = new AudioProfile(gDynamicFormat, Loading @@ -67,6 +76,48 @@ sp<AudioProfile> AudioProfile::createFullDynamic() return dynamicProfile; } AudioProfile::AudioProfile(audio_format_t format, audio_channel_mask_t channelMasks, uint32_t samplingRate) : mName(String8("")), mFormat(format) { mChannelMasks.add(channelMasks); mSamplingRates.add(samplingRate); } AudioProfile::AudioProfile(audio_format_t format, const ChannelsVector &channelMasks, const SampleRateVector &samplingRateCollection) : mName(String8("")), mFormat(format), mChannelMasks(channelMasks), mSamplingRates(samplingRateCollection) {} void AudioProfile::setChannels(const ChannelsVector &channelMasks) { if (mIsDynamicChannels) { mChannelMasks = channelMasks; } } void AudioProfile::setSampleRates(const SampleRateVector &sampleRates) { if (mIsDynamicRate) { mSamplingRates = sampleRates; } } void AudioProfile::clear() { if (mIsDynamicChannels) { mChannelMasks.clear(); } if (mIsDynamicRate) { mSamplingRates.clear(); } } status_t AudioProfile::checkExact(uint32_t samplingRate, audio_channel_mask_t channelMask, audio_format_t format) const { Loading @@ -78,13 +129,6 @@ status_t AudioProfile::checkExact(uint32_t samplingRate, audio_channel_mask_t ch return BAD_VALUE; } bool operator == (const AudioProfile &left, const AudioProfile &compareTo) { return (left.getFormat() == compareTo.getFormat()) && (left.getChannels() == compareTo.getChannels()) && (left.getSampleRates() == compareTo.getSampleRates()); } status_t AudioProfile::checkCompatibleSamplingRate(uint32_t samplingRate, uint32_t &updatedSamplingRate) const { Loading Loading @@ -250,6 +294,50 @@ void AudioProfile::dump(int fd, int spaces) const write(fd, result.string(), result.size()); } ssize_t AudioProfileVector::add(const sp<AudioProfile> &profile) { ssize_t index = Vector::add(profile); // we sort from worst to best, so that AUDIO_FORMAT_DEFAULT is always the first entry. // TODO: compareFormats could be a lambda to convert between pointer-to-format to format: // [](const audio_format_t *format1, const audio_format_t *format2) { // return compareFormats(*format1, *format2); // } sort(compareFormats); return index; } ssize_t AudioProfileVector::addProfileFromHal(const sp<AudioProfile> &profileToAdd) { // Check valid profile to add: if (!profileToAdd->hasValidFormat()) { return -1; } if (!profileToAdd->hasValidChannels() && !profileToAdd->hasValidRates()) { FormatVector formats; formats.add(profileToAdd->getFormat()); setFormats(FormatVector(formats)); return 0; } if (!profileToAdd->hasValidChannels() && profileToAdd->hasValidRates()) { setSampleRatesFor(profileToAdd->getSampleRates(), profileToAdd->getFormat()); return 0; } if (profileToAdd->hasValidChannels() && !profileToAdd->hasValidRates()) { setChannelsFor(profileToAdd->getChannels(), profileToAdd->getFormat()); return 0; } // Go through the list of profile to avoid duplicates for (size_t profileIndex = 0; profileIndex < size(); profileIndex++) { const sp<AudioProfile> &profile = itemAt(profileIndex); if (profile->isValid() && profile == profileToAdd) { // Nothing to do return profileIndex; } } profileToAdd->setDynamicFormat(true); // set the format as dynamic to allow removal return add(profileToAdd); } status_t AudioProfileVector::checkExactProfile(uint32_t samplingRate, audio_channel_mask_t channelMask, audio_format_t format) const Loading Loading @@ -306,6 +394,163 @@ status_t AudioProfileVector::checkCompatibleProfile(uint32_t &samplingRate, return BAD_VALUE; } void AudioProfileVector::clearProfiles() { for (size_t i = size(); i != 0; ) { sp<AudioProfile> profile = itemAt(--i); if (profile->isDynamicFormat() && profile->hasValidFormat()) { removeAt(i); continue; } profile->clear(); } } sp<AudioProfile> AudioProfileVector::getFirstValidProfile() const { for (size_t i = 0; i < size(); i++) { if (itemAt(i)->isValid()) { return itemAt(i); } } return 0; } sp<AudioProfile> AudioProfileVector::getFirstValidProfileFor(audio_format_t format) const { for (size_t i = 0; i < size(); i++) { if (itemAt(i)->isValid() && itemAt(i)->getFormat() == format) { return itemAt(i); } } return 0; } FormatVector AudioProfileVector::getSupportedFormats() const { FormatVector supportedFormats; for (size_t i = 0; i < size(); i++) { if (itemAt(i)->hasValidFormat()) { supportedFormats.add(itemAt(i)->getFormat()); } } return supportedFormats; } bool AudioProfileVector::hasDynamicChannelsFor(audio_format_t format) const { for (size_t i = 0; i < size(); i++) { sp<AudioProfile> profile = itemAt(i); if (profile->getFormat() == format && profile->isDynamicChannels()) { return true; } } return false; } bool AudioProfileVector::hasDynamicProfile() const { for (size_t i = 0; i < size(); i++) { if (itemAt(i)->isDynamic()) { return true; } } return false; } bool AudioProfileVector::hasDynamicRateFor(audio_format_t format) const { for (size_t i = 0; i < size(); i++) { sp<AudioProfile> profile = itemAt(i); if (profile->getFormat() == format && profile->isDynamicRate()) { return true; } } return false; } void AudioProfileVector::setFormats(const FormatVector &formats) { // Only allow to change the format of dynamic profile sp<AudioProfile> dynamicFormatProfile = getProfileFor(gDynamicFormat); if (dynamicFormatProfile == 0) { return; } for (size_t i = 0; i < formats.size(); i++) { sp<AudioProfile> profile = new AudioProfile(formats[i], dynamicFormatProfile->getChannels(), dynamicFormatProfile->getSampleRates()); profile->setDynamicFormat(true); profile->setDynamicChannels(dynamicFormatProfile->isDynamicChannels()); profile->setDynamicRate(dynamicFormatProfile->isDynamicRate()); add(profile); } } void AudioProfileVector::dump(int fd, int spaces) const { const size_t SIZE = 256; char buffer[SIZE]; snprintf(buffer, SIZE, "%*s- Profiles:\n", spaces, ""); write(fd, buffer, strlen(buffer)); for (size_t i = 0; i < size(); i++) { snprintf(buffer, SIZE, "%*sProfile %zu:", spaces + 4, "", i); write(fd, buffer, strlen(buffer)); itemAt(i)->dump(fd, spaces + 8); } } sp<AudioProfile> AudioProfileVector::getProfileFor(audio_format_t format) const { for (size_t i = 0; i < size(); i++) { if (itemAt(i)->getFormat() == format) { return itemAt(i); } } return 0; } void AudioProfileVector::setSampleRatesFor( const SampleRateVector &sampleRates, audio_format_t format) { for (size_t i = 0; i < size(); i++) { sp<AudioProfile> profile = itemAt(i); if (profile->getFormat() == format && profile->isDynamicRate()) { if (profile->hasValidRates()) { // Need to create a new profile with same format sp<AudioProfile> profileToAdd = new AudioProfile(format, profile->getChannels(), sampleRates); profileToAdd->setDynamicFormat(true); // need to set to allow cleaning add(profileToAdd); } else { profile->setSampleRates(sampleRates); } return; } } } void AudioProfileVector::setChannelsFor(const ChannelsVector &channelMasks, audio_format_t format) { for (size_t i = 0; i < size(); i++) { sp<AudioProfile> profile = itemAt(i); if (profile->getFormat() == format && profile->isDynamicChannels()) { if (profile->hasValidChannels()) { // Need to create a new profile with same format sp<AudioProfile> profileToAdd = new AudioProfile(format, channelMasks, profile->getSampleRates()); profileToAdd->setDynamicFormat(true); // need to set to allow cleaning add(profileToAdd); } else { profile->setChannels(channelMasks); } return; } } } // static int AudioProfileVector::compareFormats(const sp<AudioProfile> *profile1, const sp<AudioProfile> *profile2) { Loading