Merge "audio policy: Refactor AudioProfile"
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioProfile.h b/services/audiopolicy/common/managerdefinitions/include/AudioProfile.h
index d2fc6a3..31c75a4 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioProfile.h
@@ -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 {
@@ -69,71 +68,30 @@
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;
@@ -169,223 +127,38 @@
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;
- }
+ sp<AudioProfile> getFirstValidProfile() const;
+ sp<AudioProfile> getFirstValidProfileFor(audio_format_t format) const;
+ bool hasValidProfile() const { return getFirstValidProfile() != 0; }
- 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;
- }
-
- 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 setFormats(const FormatVector &formats);
- 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 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);
};
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioProfile.cpp
index e8fe5ff..b76b609 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioProfile.cpp
@@ -14,17 +14,19 @@
* limitations under the License.
*/
+#include <string>
+
#define LOG_TAG "APM::AudioProfile"
//#define LOG_NDEBUG 0
-#include "AudioProfile.h"
-#include "AudioPort.h"
-#include "HwModule.h"
-#include "AudioGain.h"
-#include <utils/SortedVector.h>
-#include "TypeConverter.h"
#include <media/AudioResamplerPublic.h>
-#include <algorithm>
+#include <utils/Errors.h>
+
+#include "AudioGain.h"
+#include "AudioPort.h"
+#include "AudioProfile.h"
+#include "HwModule.h"
+#include "TypeConverter.h"
namespace android {
@@ -50,6 +52,13 @@
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,
@@ -67,6 +76,48 @@
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
{
@@ -78,13 +129,6 @@
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
{
@@ -250,6 +294,50 @@
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
@@ -306,6 +394,163 @@
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)
{