• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define LOG_TAG "APM::PolicyAudioPort"
18 //#define LOG_NDEBUG 0
19 #include "TypeConverter.h"
20 #include "PolicyAudioPort.h"
21 #include "HwModule.h"
22 #include <policy.h>
23 
24 #ifndef ARRAY_SIZE
25 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
26 #endif
27 
28 namespace android {
29 
30 // --- PolicyAudioPort class implementation
attach(const sp<HwModule> & module)31 void PolicyAudioPort::attach(const sp<HwModule>& module)
32 {
33     mModule = module;
34     ALOGV("%s: attaching module %s to port %s",
35             __FUNCTION__, getModuleName(), asAudioPort()->getName().c_str());
36 }
37 
detach()38 void PolicyAudioPort::detach()
39 {
40     mModule = nullptr;
41 }
42 
43 // Note that is a different namespace than AudioFlinger unique IDs
getNextUniqueId()44 audio_port_handle_t PolicyAudioPort::getNextUniqueId()
45 {
46     return getNextHandle();
47 }
48 
getModuleHandle() const49 audio_module_handle_t PolicyAudioPort::getModuleHandle() const
50 {
51     return mModule != 0 ? mModule->getHandle() : AUDIO_MODULE_HANDLE_NONE;
52 }
53 
getModuleVersionMajor() const54 uint32_t PolicyAudioPort::getModuleVersionMajor() const
55 {
56     return mModule != 0 ? mModule->getHalVersionMajor() : 0;
57 }
58 
getModuleName() const59 const char *PolicyAudioPort::getModuleName() const
60 {
61     return mModule != 0 ? mModule->getName() : "invalid module";
62 }
63 
checkExactAudioProfile(const struct audio_port_config * config) const64 status_t PolicyAudioPort::checkExactAudioProfile(const struct audio_port_config *config) const
65 {
66     status_t status = NO_ERROR;
67     auto config_mask = config->config_mask;
68     if (config_mask & AUDIO_PORT_CONFIG_GAIN) {
69         config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
70         status = asAudioPort()->checkGain(&config->gain, config->gain.index);
71         if (status != NO_ERROR) {
72             return status;
73         }
74     }
75     if (config_mask != 0) {
76         // TODO should we check sample_rate / channel_mask / format separately?
77         status = checkExactProfile(asAudioPort()->getAudioProfiles(), config->sample_rate,
78                 config->channel_mask, config->format);
79     }
80     return status;
81 }
82 
pickSamplingRate(uint32_t & pickedRate,const SampleRateSet & samplingRates) const83 void PolicyAudioPort::pickSamplingRate(uint32_t &pickedRate,
84                                        const SampleRateSet &samplingRates) const
85 {
86     pickedRate = 0;
87     // For direct outputs, pick minimum sampling rate: this helps ensuring that the
88     // channel count / sampling rate combination chosen will be supported by the connected
89     // sink
90     if (asAudioPort()->isDirectOutput()) {
91         uint32_t samplingRate = UINT_MAX;
92         for (const auto rate : samplingRates) {
93             if ((rate < samplingRate) && (rate > 0)) {
94                 samplingRate = rate;
95             }
96         }
97         pickedRate = (samplingRate == UINT_MAX) ? 0 : samplingRate;
98     } else {
99         uint32_t maxRate = SAMPLE_RATE_HZ_MAX;
100 
101         // For mixed output and inputs, use max mixer sampling rates. Do not
102         // limit sampling rate otherwise
103         // For inputs, also see checkCompatibleSamplingRate().
104         if (asAudioPort()->getType() == AUDIO_PORT_TYPE_MIX) {
105             maxRate = UINT_MAX;
106         }
107         // TODO: should mSamplingRates[] be ordered in terms of our preference
108         // and we return the first (and hence most preferred) match?  This is of concern if
109         // we want to choose 96kHz over 192kHz for USB driver stability or resource constraints.
110         for (const auto rate : samplingRates) {
111             if ((rate > pickedRate) && (rate <= maxRate)) {
112                 pickedRate = rate;
113             }
114         }
115     }
116 }
117 
pickChannelMask(audio_channel_mask_t & pickedChannelMask,const ChannelMaskSet & channelMasks) const118 void PolicyAudioPort::pickChannelMask(audio_channel_mask_t &pickedChannelMask,
119                                       const ChannelMaskSet &channelMasks) const
120 {
121     pickedChannelMask = AUDIO_CHANNEL_NONE;
122     // For direct outputs, pick minimum channel count: this helps ensuring that the
123     // channel count / sampling rate combination chosen will be supported by the connected
124     // sink
125     if (asAudioPort()->isDirectOutput()) {
126         uint32_t channelCount = UINT_MAX;
127         for (const auto channelMask : channelMasks) {
128             uint32_t cnlCount;
129             if (asAudioPort()->useInputChannelMask()) {
130                 cnlCount = audio_channel_count_from_in_mask(channelMask);
131             } else {
132                 cnlCount = audio_channel_count_from_out_mask(channelMask);
133             }
134             if ((cnlCount < channelCount) && (cnlCount > 0)) {
135                 pickedChannelMask = channelMask;
136                 channelCount = cnlCount;
137             }
138         }
139     } else {
140         uint32_t channelCount = 0;
141         uint32_t maxCount = MAX_MIXER_CHANNEL_COUNT;
142 
143         // For mixed output and inputs, use max mixer channel count. Do not
144         // limit channel count otherwise
145         if (asAudioPort()->getType() != AUDIO_PORT_TYPE_MIX) {
146             maxCount = UINT_MAX;
147         }
148         for (const auto channelMask : channelMasks) {
149             uint32_t cnlCount;
150             if (asAudioPort()->useInputChannelMask()) {
151                 cnlCount = audio_channel_count_from_in_mask(channelMask);
152             } else {
153                 cnlCount = audio_channel_count_from_out_mask(channelMask);
154             }
155             if ((cnlCount > channelCount) && (cnlCount <= maxCount)) {
156                 pickedChannelMask = channelMask;
157                 channelCount = cnlCount;
158             }
159         }
160     }
161 }
162 
163 /* format in order of increasing preference */
164 const audio_format_t PolicyAudioPort::sPcmFormatCompareTable[] = {
165         AUDIO_FORMAT_DEFAULT,
166         AUDIO_FORMAT_PCM_16_BIT,
167         AUDIO_FORMAT_PCM_8_24_BIT,
168         AUDIO_FORMAT_PCM_24_BIT_PACKED,
169         AUDIO_FORMAT_PCM_32_BIT,
170         AUDIO_FORMAT_PCM_FLOAT,
171 };
172 
compareFormats(audio_format_t format1,audio_format_t format2)173 int PolicyAudioPort::compareFormats(audio_format_t format1, audio_format_t format2)
174 {
175     // NOTE: AUDIO_FORMAT_INVALID is also considered not PCM and will be compared equal to any
176     // compressed format and better than any PCM format. This is by design of pickFormat()
177     if (!audio_is_linear_pcm(format1)) {
178         if (!audio_is_linear_pcm(format2)) {
179             return 0;
180         }
181         return 1;
182     }
183     if (!audio_is_linear_pcm(format2)) {
184         return -1;
185     }
186 
187     int index1 = -1, index2 = -1;
188     for (size_t i = 0;
189             (i < ARRAY_SIZE(sPcmFormatCompareTable)) && ((index1 == -1) || (index2 == -1));
190             i ++) {
191         if (sPcmFormatCompareTable[i] == format1) {
192             index1 = i;
193         }
194         if (sPcmFormatCompareTable[i] == format2) {
195             index2 = i;
196         }
197     }
198     // format1 not found => index1 < 0 => format2 > format1
199     // format2 not found => index2 < 0 => format2 < format1
200     return index1 - index2;
201 }
202 
formatDistance(audio_format_t format1,audio_format_t format2)203 uint32_t PolicyAudioPort::formatDistance(audio_format_t format1, audio_format_t format2)
204 {
205     if (format1 == format2) {
206         return 0;
207     }
208     if (format1 == AUDIO_FORMAT_INVALID || format2 == AUDIO_FORMAT_INVALID) {
209         return kFormatDistanceMax;
210     }
211     int diffBytes = (int)audio_bytes_per_sample(format1) -
212             audio_bytes_per_sample(format2);
213 
214     return abs(diffBytes);
215 }
216 
isBetterFormatMatch(audio_format_t newFormat,audio_format_t currentFormat,audio_format_t targetFormat)217 bool PolicyAudioPort::isBetterFormatMatch(audio_format_t newFormat,
218                                           audio_format_t currentFormat,
219                                           audio_format_t targetFormat)
220 {
221     return formatDistance(newFormat, targetFormat) < formatDistance(currentFormat, targetFormat);
222 }
223 
pickAudioProfile(uint32_t & samplingRate,audio_channel_mask_t & channelMask,audio_format_t & format) const224 void PolicyAudioPort::pickAudioProfile(uint32_t &samplingRate,
225                                        audio_channel_mask_t &channelMask,
226                                        audio_format_t &format) const
227 {
228     format = AUDIO_FORMAT_DEFAULT;
229     samplingRate = 0;
230     channelMask = AUDIO_CHANNEL_NONE;
231 
232     // special case for uninitialized dynamic profile
233     if (!asAudioPort()->hasValidAudioProfile()) {
234         return;
235     }
236     audio_format_t bestFormat = sPcmFormatCompareTable[ARRAY_SIZE(sPcmFormatCompareTable) - 1];
237     // For mixed output and inputs, use best mixer output format.
238     // Do not limit format otherwise
239     if ((asAudioPort()->getType() != AUDIO_PORT_TYPE_MIX) || asAudioPort()->isDirectOutput()) {
240         bestFormat = AUDIO_FORMAT_INVALID;
241     }
242 
243     const AudioProfileVector& audioProfiles = asAudioPort()->getAudioProfiles();
244     for (size_t i = 0; i < audioProfiles.size(); i ++) {
245         if (!audioProfiles[i]->isValid()) {
246             continue;
247         }
248         audio_format_t formatToCompare = audioProfiles[i]->getFormat();
249         if ((compareFormats(formatToCompare, format) > 0) &&
250                 (compareFormats(formatToCompare, bestFormat) <= 0)) {
251             uint32_t pickedSamplingRate = 0;
252             audio_channel_mask_t pickedChannelMask = AUDIO_CHANNEL_NONE;
253             pickChannelMask(pickedChannelMask, audioProfiles[i]->getChannels());
254             pickSamplingRate(pickedSamplingRate, audioProfiles[i]->getSampleRates());
255 
256             if (formatToCompare != AUDIO_FORMAT_DEFAULT && pickedChannelMask != AUDIO_CHANNEL_NONE
257                     && pickedSamplingRate != 0) {
258                 format = formatToCompare;
259                 channelMask = pickedChannelMask;
260                 samplingRate = pickedSamplingRate;
261                 // TODO: shall we return on the first one or still trying to pick a better Profile?
262             }
263         }
264     }
265     ALOGV("%s Port[nm:%s] profile rate=%d, format=%d, channels=%d", __FUNCTION__,
266             asAudioPort()->getName().c_str(), samplingRate, channelMask, format);
267 }
268 
269 } // namespace android
270