1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include "policy.h" 20 #include <utils/String8.h> 21 #include <utils/SortedVector.h> 22 #include <utils/RefBase.h> 23 #include <utils/Errors.h> 24 #include <system/audio.h> 25 #include <cutils/config_utils.h> 26 27 namespace android { 28 29 typedef SortedVector<uint32_t> SampleRateVector; 30 typedef SortedVector<audio_channel_mask_t> ChannelsVector; 31 typedef Vector<audio_format_t> FormatVector; 32 33 template <typename T> 34 bool operator == (const SortedVector<T> &left, const SortedVector<T> &right); 35 36 class AudioProfile : public virtual RefBase 37 { 38 public: AudioProfile(audio_format_t format,audio_channel_mask_t channelMasks,uint32_t samplingRate)39 AudioProfile(audio_format_t format, 40 audio_channel_mask_t channelMasks, 41 uint32_t samplingRate) : 42 mName(String8("")), 43 mFormat(format) 44 { 45 mChannelMasks.add(channelMasks); 46 mSamplingRates.add(samplingRate); 47 } 48 AudioProfile(audio_format_t format,const ChannelsVector & channelMasks,const SampleRateVector & samplingRateCollection)49 AudioProfile(audio_format_t format, 50 const ChannelsVector &channelMasks, 51 const SampleRateVector &samplingRateCollection) : 52 mName(String8("")), 53 mFormat(format), 54 mChannelMasks(channelMasks), 55 mSamplingRates(samplingRateCollection) 56 {} 57 getFormat()58 audio_format_t getFormat() const { return mFormat; } 59 setChannels(const ChannelsVector & channelMasks)60 void setChannels(const ChannelsVector &channelMasks) 61 { 62 if (mIsDynamicChannels) { 63 mChannelMasks = channelMasks; 64 } 65 } getChannels()66 const ChannelsVector &getChannels() const { return mChannelMasks; } 67 setSampleRates(const SampleRateVector & sampleRates)68 void setSampleRates(const SampleRateVector &sampleRates) 69 { 70 if (mIsDynamicRate) { 71 mSamplingRates = sampleRates; 72 } 73 } getSampleRates()74 const SampleRateVector &getSampleRates() const { return mSamplingRates; } 75 isValid()76 bool isValid() const { return hasValidFormat() && hasValidRates() && hasValidChannels(); } 77 clear()78 void clear() 79 { 80 if (mIsDynamicChannels) { 81 mChannelMasks.clear(); 82 } 83 if (mIsDynamicRate) { 84 mSamplingRates.clear(); 85 } 86 } 87 supportsChannels(audio_channel_mask_t channels)88 inline bool supportsChannels(audio_channel_mask_t channels) const 89 { 90 return mChannelMasks.indexOf(channels) >= 0; 91 } supportsRate(uint32_t rate)92 inline bool supportsRate(uint32_t rate) const 93 { 94 return mSamplingRates.indexOf(rate) >= 0; 95 } 96 97 status_t checkExact(uint32_t rate, audio_channel_mask_t channels, audio_format_t format) const; 98 99 status_t checkCompatibleChannelMask(audio_channel_mask_t channelMask, 100 audio_channel_mask_t &updatedChannelMask, 101 audio_port_type_t portType, 102 audio_port_role_t portRole) const; 103 104 status_t checkCompatibleSamplingRate(uint32_t samplingRate, 105 uint32_t &updatedSamplingRate) const; 106 hasValidFormat()107 bool hasValidFormat() const { return mFormat != AUDIO_FORMAT_DEFAULT; } hasValidRates()108 bool hasValidRates() const { return !mSamplingRates.isEmpty(); } hasValidChannels()109 bool hasValidChannels() const { return !mChannelMasks.isEmpty(); } 110 setDynamicChannels(bool dynamic)111 void setDynamicChannels(bool dynamic) { mIsDynamicChannels = dynamic; } isDynamicChannels()112 bool isDynamicChannels() const { return mIsDynamicChannels; } 113 setDynamicRate(bool dynamic)114 void setDynamicRate(bool dynamic) { mIsDynamicRate = dynamic; } isDynamicRate()115 bool isDynamicRate() const { return mIsDynamicRate; } 116 setDynamicFormat(bool dynamic)117 void setDynamicFormat(bool dynamic) { mIsDynamicFormat = dynamic; } isDynamicFormat()118 bool isDynamicFormat() const { return mIsDynamicFormat; } 119 isDynamic()120 bool isDynamic() { return mIsDynamicFormat || mIsDynamicChannels || mIsDynamicRate; } 121 122 void dump(int fd, int spaces) const; 123 124 private: 125 String8 mName; 126 audio_format_t mFormat; 127 ChannelsVector mChannelMasks; 128 SampleRateVector mSamplingRates; 129 130 bool mIsDynamicFormat = false; 131 bool mIsDynamicChannels = false; 132 bool mIsDynamicRate = false; 133 }; 134 135 136 class AudioProfileVector : public Vector<sp<AudioProfile> > 137 { 138 public: add(const sp<AudioProfile> & profile)139 ssize_t add(const sp<AudioProfile> &profile) 140 { 141 ssize_t index = Vector::add(profile); 142 // we sort from worst to best, so that AUDIO_FORMAT_DEFAULT is always the first entry. 143 // TODO: compareFormats could be a lambda to convert between pointer-to-format to format: 144 // [](const audio_format_t *format1, const audio_format_t *format2) { 145 // return compareFormats(*format1, *format2); 146 // } 147 sort(compareFormats); 148 return index; 149 } 150 151 // This API is intended to be used by the policy manager once retrieving capabilities 152 // for a profile with dynamic format, rate and channels attributes addProfileFromHal(const sp<AudioProfile> & profileToAdd)153 ssize_t addProfileFromHal(const sp<AudioProfile> &profileToAdd) 154 { 155 // Check valid profile to add: 156 if (!profileToAdd->hasValidFormat()) { 157 return -1; 158 } 159 if (!profileToAdd->hasValidChannels() && !profileToAdd->hasValidRates()) { 160 FormatVector formats; 161 formats.add(profileToAdd->getFormat()); 162 setFormats(FormatVector(formats)); 163 return 0; 164 } 165 if (!profileToAdd->hasValidChannels() && profileToAdd->hasValidRates()) { 166 setSampleRatesFor(profileToAdd->getSampleRates(), profileToAdd->getFormat()); 167 return 0; 168 } 169 if (profileToAdd->hasValidChannels() && !profileToAdd->hasValidRates()) { 170 setChannelsFor(profileToAdd->getChannels(), profileToAdd->getFormat()); 171 return 0; 172 } 173 // Go through the list of profile to avoid duplicates 174 for (size_t profileIndex = 0; profileIndex < size(); profileIndex++) { 175 const sp<AudioProfile> &profile = itemAt(profileIndex); 176 if (profile->isValid() && profile == profileToAdd) { 177 // Nothing to do 178 return profileIndex; 179 } 180 } 181 profileToAdd->setDynamicFormat(true); // set the format as dynamic to allow removal 182 return add(profileToAdd); 183 } 184 getFirstValidProfile()185 sp<AudioProfile> getFirstValidProfile() const 186 { 187 for (size_t i = 0; i < size(); i++) { 188 if (itemAt(i)->isValid()) { 189 return itemAt(i); 190 } 191 } 192 return 0; 193 } 194 hasValidProfile()195 bool hasValidProfile() const { return getFirstValidProfile() != 0; } 196 197 status_t checkExactProfile(uint32_t samplingRate, audio_channel_mask_t channelMask, 198 audio_format_t format) const; 199 200 status_t checkCompatibleProfile(uint32_t &samplingRate, audio_channel_mask_t &channelMask, 201 audio_format_t &format, 202 audio_port_type_t portType, 203 audio_port_role_t portRole) const; 204 getSupportedFormats()205 FormatVector getSupportedFormats() const 206 { 207 FormatVector supportedFormats; 208 for (size_t i = 0; i < size(); i++) { 209 if (itemAt(i)->hasValidFormat()) { 210 supportedFormats.add(itemAt(i)->getFormat()); 211 } 212 } 213 return supportedFormats; 214 } 215 hasDynamicProfile()216 bool hasDynamicProfile() const 217 { 218 for (size_t i = 0; i < size(); i++) { 219 if (itemAt(i)->isDynamic()) { 220 return true; 221 } 222 } 223 return false; 224 } 225 hasDynamicFormat()226 bool hasDynamicFormat() const 227 { 228 return getProfileFor(gDynamicFormat) != 0; 229 } 230 hasDynamicChannelsFor(audio_format_t format)231 bool hasDynamicChannelsFor(audio_format_t format) const 232 { 233 for (size_t i = 0; i < size(); i++) { 234 sp<AudioProfile> profile = itemAt(i); 235 if (profile->getFormat() == format && profile->isDynamicChannels()) { 236 return true; 237 } 238 } 239 return false; 240 } 241 hasDynamicRateFor(audio_format_t format)242 bool hasDynamicRateFor(audio_format_t format) const 243 { 244 for (size_t i = 0; i < size(); i++) { 245 sp<AudioProfile> profile = itemAt(i); 246 if (profile->getFormat() == format && profile->isDynamicRate()) { 247 return true; 248 } 249 } 250 return false; 251 } 252 253 // One audio profile will be added for each format supported by Audio HAL setFormats(const FormatVector & formats)254 void setFormats(const FormatVector &formats) 255 { 256 // Only allow to change the format of dynamic profile 257 sp<AudioProfile> dynamicFormatProfile = getProfileFor(gDynamicFormat); 258 if (dynamicFormatProfile == 0) { 259 return; 260 } 261 for (size_t i = 0; i < formats.size(); i++) { 262 sp<AudioProfile> profile = new AudioProfile(formats[i], 263 dynamicFormatProfile->getChannels(), 264 dynamicFormatProfile->getSampleRates()); 265 profile->setDynamicFormat(true); 266 profile->setDynamicChannels(dynamicFormatProfile->isDynamicChannels()); 267 profile->setDynamicRate(dynamicFormatProfile->isDynamicRate()); 268 add(profile); 269 } 270 } 271 clearProfiles()272 void clearProfiles() 273 { 274 for (size_t i = size(); i != 0; ) { 275 sp<AudioProfile> profile = itemAt(--i); 276 if (profile->isDynamicFormat() && profile->hasValidFormat()) { 277 removeAt(i); 278 continue; 279 } 280 profile->clear(); 281 } 282 } 283 dump(int fd,int spaces)284 void dump(int fd, int spaces) const 285 { 286 const size_t SIZE = 256; 287 char buffer[SIZE]; 288 289 snprintf(buffer, SIZE, "%*s- Profiles:\n", spaces, ""); 290 write(fd, buffer, strlen(buffer)); 291 for (size_t i = 0; i < size(); i++) { 292 snprintf(buffer, SIZE, "%*sProfile %zu:", spaces + 4, "", i); 293 write(fd, buffer, strlen(buffer)); 294 itemAt(i)->dump(fd, spaces + 8); 295 } 296 } 297 298 private: setSampleRatesFor(const SampleRateVector & sampleRates,audio_format_t format)299 void setSampleRatesFor(const SampleRateVector &sampleRates, audio_format_t format) 300 { 301 for (size_t i = 0; i < size(); i++) { 302 sp<AudioProfile> profile = itemAt(i); 303 if (profile->getFormat() == format && profile->isDynamicRate()) { 304 if (profile->hasValidRates()) { 305 // Need to create a new profile with same format 306 sp<AudioProfile> profileToAdd = new AudioProfile(format, profile->getChannels(), 307 sampleRates); 308 profileToAdd->setDynamicFormat(true); // need to set to allow cleaning 309 add(profileToAdd); 310 } else { 311 profile->setSampleRates(sampleRates); 312 } 313 return; 314 } 315 } 316 } 317 setChannelsFor(const ChannelsVector & channelMasks,audio_format_t format)318 void setChannelsFor(const ChannelsVector &channelMasks, audio_format_t format) 319 { 320 for (size_t i = 0; i < size(); i++) { 321 sp<AudioProfile> profile = itemAt(i); 322 if (profile->getFormat() == format && profile->isDynamicChannels()) { 323 if (profile->hasValidChannels()) { 324 // Need to create a new profile with same format 325 sp<AudioProfile> profileToAdd = new AudioProfile(format, channelMasks, 326 profile->getSampleRates()); 327 profileToAdd->setDynamicFormat(true); // need to set to allow cleaning 328 add(profileToAdd); 329 } else { 330 profile->setChannels(channelMasks); 331 } 332 return; 333 } 334 } 335 } 336 getProfileFor(audio_format_t format)337 sp<AudioProfile> getProfileFor(audio_format_t format) const 338 { 339 for (size_t i = 0; i < size(); i++) { 340 if (itemAt(i)->getFormat() == format) { 341 return itemAt(i); 342 } 343 } 344 return 0; 345 } 346 347 static int compareFormats(const sp<AudioProfile> *profile1, const sp<AudioProfile> *profile2); 348 }; 349 350 bool operator == (const AudioProfile &left, const AudioProfile &right); 351 352 }; // namespace android 353