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