Home | History | Annotate | Download | only in include
      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:
     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 
     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 
     58     audio_format_t getFormat() const { return mFormat; }
     59 
     60     void setChannels(const ChannelsVector &channelMasks)
     61     {
     62         if (mIsDynamicChannels) {
     63             mChannelMasks = channelMasks;
     64         }
     65     }
     66     const ChannelsVector &getChannels() const { return mChannelMasks; }
     67 
     68     void setSampleRates(const SampleRateVector &sampleRates)
     69     {
     70         if (mIsDynamicRate) {
     71             mSamplingRates = sampleRates;
     72         }
     73     }
     74     const SampleRateVector &getSampleRates() const { return mSamplingRates; }
     75 
     76     bool isValid() const { return hasValidFormat() && hasValidRates() && hasValidChannels(); }
     77 
     78     void clear()
     79     {
     80         if (mIsDynamicChannels) {
     81             mChannelMasks.clear();
     82         }
     83         if (mIsDynamicRate) {
     84             mSamplingRates.clear();
     85         }
     86     }
     87 
     88     inline bool supportsChannels(audio_channel_mask_t channels) const
     89     {
     90         return mChannelMasks.indexOf(channels) >= 0;
     91     }
     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 
    107     bool hasValidFormat() const { return mFormat != AUDIO_FORMAT_DEFAULT; }
    108     bool hasValidRates() const { return !mSamplingRates.isEmpty(); }
    109     bool hasValidChannels() const { return !mChannelMasks.isEmpty(); }
    110 
    111     void setDynamicChannels(bool dynamic) { mIsDynamicChannels = dynamic; }
    112     bool isDynamicChannels() const { return mIsDynamicChannels; }
    113 
    114     void setDynamicRate(bool dynamic) { mIsDynamicRate = dynamic; }
    115     bool isDynamicRate() const { return mIsDynamicRate; }
    116 
    117     void setDynamicFormat(bool dynamic) { mIsDynamicFormat = dynamic; }
    118     bool isDynamicFormat() const { return mIsDynamicFormat; }
    119 
    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:
    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
    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 
    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 
    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 
    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 
    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 
    226     bool hasDynamicFormat() const
    227     {
    228         return getProfileFor(gDynamicFormat) != 0;
    229     }
    230 
    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 
    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
    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 
    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 
    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:
    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 
    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 
    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