AudioProfile.h revision 112b0af826aeca45855690b9c105b2cdf9938bbe
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
27namespace android {
28
29typedef SortedVector<uint32_t> SampleRateVector;
30typedef SortedVector<audio_channel_mask_t> ChannelsVector;
31typedef Vector<audio_format_t> FormatVector;
32
33template <typename T>
34bool operator == (const SortedVector<T> &left, const SortedVector<T> &right);
35
36class AudioProfile : public virtual RefBase
37{
38public:
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
124private:
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
136class AudioProfileVector : public Vector<sp<AudioProfile> >
137{
138public:
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        clearProfiles();
262        for (size_t i = 0; i < formats.size(); i++) {
263            sp<AudioProfile> profile = new AudioProfile(formats[i],
264                                                        dynamicFormatProfile->getChannels(),
265                                                        dynamicFormatProfile->getSampleRates());
266            profile->setDynamicFormat(true);
267            profile->setDynamicChannels(dynamicFormatProfile->isDynamicChannels());
268            profile->setDynamicRate(dynamicFormatProfile->isDynamicRate());
269            add(profile);
270        }
271    }
272
273    void setSampleRatesFor(const SampleRateVector &sampleRates, audio_format_t format)
274    {
275        for (size_t i = 0; i < size(); i++) {
276            sp<AudioProfile> profile = itemAt(i);
277            if (profile->getFormat() == format && profile->isDynamicRate()) {
278                if (profile->hasValidRates()) {
279                    // Need to create a new profile with same format
280                    sp<AudioProfile> profileToAdd = new AudioProfile(format, profile->getChannels(),
281                                                                     sampleRates);
282                    profileToAdd->setDynamicFormat(true); // need to set to allow cleaning
283                    add(profileToAdd);
284                } else {
285                    profile->setSampleRates(sampleRates);
286                }
287                return;
288            }
289        }
290    }
291
292    void setChannelsFor(const ChannelsVector &channelMasks, audio_format_t format)
293    {
294        for (size_t i = 0; i < size(); i++) {
295            sp<AudioProfile> profile = itemAt(i);
296            if (profile->getFormat() == format && profile->isDynamicChannels()) {
297                if (profile->hasValidChannels()) {
298                    // Need to create a new profile with same format
299                    sp<AudioProfile> profileToAdd = new AudioProfile(format, channelMasks,
300                                                                     profile->getSampleRates());
301                    profileToAdd->setDynamicFormat(true); // need to set to allow cleaning
302                    add(profileToAdd);
303                } else {
304                    profile->setChannels(channelMasks);
305                }
306                return;
307            }
308        }
309    }
310
311    void clearProfiles()
312    {
313        for (size_t i = size(); i != 0; ) {
314            sp<AudioProfile> profile = itemAt(--i);
315            if (profile->isDynamicFormat() && profile->hasValidFormat()) {
316                removeAt(i);
317                continue;
318            }
319            profile->clear();
320        }
321    }
322
323    void dump(int fd, int spaces) const
324    {
325        const size_t SIZE = 256;
326        char buffer[SIZE];
327
328        snprintf(buffer, SIZE, "%*s- Profiles:\n", spaces, "");
329        write(fd, buffer, strlen(buffer));
330        for (size_t i = 0; i < size(); i++) {
331            snprintf(buffer, SIZE, "%*sProfile %zu:", spaces + 4, "", i);
332            write(fd, buffer, strlen(buffer));
333            itemAt(i)->dump(fd, spaces + 8);
334        }
335    }
336
337private:
338    sp<AudioProfile> getProfileFor(audio_format_t format) const
339    {
340        for (size_t i = 0; i < size(); i++) {
341            if (itemAt(i)->getFormat() == format) {
342                return itemAt(i);
343            }
344        }
345        return 0;
346    }
347
348    static int compareFormats(const sp<AudioProfile> *profile1, const sp<AudioProfile> *profile2);
349};
350
351bool operator == (const AudioProfile &left, const AudioProfile &right);
352
353}; // namespace android
354