• 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     return checkAudioProfile(config, checkExactProfile);
67 }
68 
checkIdenticalAudioProfile(const struct audio_port_config * config) const69 status_t PolicyAudioPort::checkIdenticalAudioProfile(const struct audio_port_config *config) const {
70     return checkAudioProfile(config, checkIdenticalProfile);
71 }
72 
pickSamplingRate(uint32_t & pickedRate,const SampleRateSet & samplingRates) const73 void PolicyAudioPort::pickSamplingRate(uint32_t &pickedRate,
74                                        const SampleRateSet &samplingRates) const
75 {
76     pickedRate = 0;
77     // For direct outputs, pick minimum sampling rate: this helps ensuring that the
78     // channel count / sampling rate combination chosen will be supported by the connected
79     // sink
80     if (asAudioPort()->isDirectOutput()) {
81         uint32_t samplingRate = UINT_MAX;
82         for (const auto rate : samplingRates) {
83             if ((rate < samplingRate) && (rate > 0)) {
84                 samplingRate = rate;
85             }
86         }
87         pickedRate = (samplingRate == UINT_MAX) ? 0 : samplingRate;
88     } else {
89         uint32_t maxRate = SAMPLE_RATE_HZ_MAX;
90 
91         // For mixed output and inputs, use max mixer sampling rates. Do not
92         // limit sampling rate otherwise
93         // For inputs, also see checkCompatibleSamplingRate().
94         if (asAudioPort()->getType() == AUDIO_PORT_TYPE_MIX) {
95             maxRate = UINT_MAX;
96         }
97         // TODO: should mSamplingRates[] be ordered in terms of our preference
98         // and we return the first (and hence most preferred) match?  This is of concern if
99         // we want to choose 96kHz over 192kHz for USB driver stability or resource constraints.
100         for (const auto rate : samplingRates) {
101             if ((rate > pickedRate) && (rate <= maxRate)) {
102                 pickedRate = rate;
103             }
104         }
105     }
106 }
107 
pickChannelMask(audio_channel_mask_t & pickedChannelMask,const ChannelMaskSet & channelMasks) const108 void PolicyAudioPort::pickChannelMask(audio_channel_mask_t &pickedChannelMask,
109                                       const ChannelMaskSet &channelMasks) const
110 {
111     pickedChannelMask = AUDIO_CHANNEL_NONE;
112     // For direct outputs, pick minimum channel count: this helps ensuring that the
113     // channel count / sampling rate combination chosen will be supported by the connected
114     // sink
115     if (asAudioPort()->isDirectOutput()) {
116         uint32_t channelCount = UINT_MAX;
117         for (const auto channelMask : channelMasks) {
118             uint32_t cnlCount;
119             if (asAudioPort()->useInputChannelMask()) {
120                 cnlCount = audio_channel_count_from_in_mask(channelMask);
121             } else {
122                 cnlCount = audio_channel_count_from_out_mask(channelMask);
123             }
124             if ((cnlCount < channelCount) && (cnlCount > 0)) {
125                 pickedChannelMask = channelMask;
126                 channelCount = cnlCount;
127             }
128         }
129     } else {
130         uint32_t channelCount = 0;
131         uint32_t maxCount = MAX_MIXER_CHANNEL_COUNT;
132 
133         // For mixed output and inputs, use max mixer channel count. Do not
134         // limit channel count otherwise
135         if (asAudioPort()->getType() != AUDIO_PORT_TYPE_MIX) {
136             maxCount = UINT_MAX;
137         }
138         for (const auto channelMask : channelMasks) {
139             uint32_t cnlCount;
140             if (asAudioPort()->useInputChannelMask()) {
141                 cnlCount = audio_channel_count_from_in_mask(channelMask);
142             } else {
143                 cnlCount = audio_channel_count_from_out_mask(channelMask);
144             }
145             if ((cnlCount > channelCount) && (cnlCount <= maxCount)) {
146                 pickedChannelMask = channelMask;
147                 channelCount = cnlCount;
148             }
149         }
150     }
151 }
152 
153 /* format in order of increasing preference */
154 const audio_format_t PolicyAudioPort::sPcmFormatCompareTable[] = {
155         AUDIO_FORMAT_DEFAULT,
156         AUDIO_FORMAT_PCM_16_BIT,
157         AUDIO_FORMAT_PCM_8_24_BIT,
158         AUDIO_FORMAT_PCM_24_BIT_PACKED,
159         AUDIO_FORMAT_PCM_32_BIT,
160         AUDIO_FORMAT_PCM_FLOAT,
161 };
162 
compareFormats(audio_format_t format1,audio_format_t format2)163 int PolicyAudioPort::compareFormats(audio_format_t format1, audio_format_t format2)
164 {
165     // NOTE: AUDIO_FORMAT_INVALID is also considered not PCM and will be compared equal to any
166     // compressed format and better than any PCM format. This is by design of pickFormat()
167     if (!audio_is_linear_pcm(format1)) {
168         if (!audio_is_linear_pcm(format2)) {
169             return 0;
170         }
171         return 1;
172     }
173     if (!audio_is_linear_pcm(format2)) {
174         return -1;
175     }
176 
177     int index1 = -1, index2 = -1;
178     for (size_t i = 0;
179             (i < ARRAY_SIZE(sPcmFormatCompareTable)) && ((index1 == -1) || (index2 == -1));
180             i ++) {
181         if (sPcmFormatCompareTable[i] == format1) {
182             index1 = i;
183         }
184         if (sPcmFormatCompareTable[i] == format2) {
185             index2 = i;
186         }
187     }
188     // format1 not found => index1 < 0 => format2 > format1
189     // format2 not found => index2 < 0 => format2 < format1
190     return index1 - index2;
191 }
192 
formatDistance(audio_format_t format1,audio_format_t format2)193 uint32_t PolicyAudioPort::formatDistance(audio_format_t format1, audio_format_t format2)
194 {
195     if (format1 == format2) {
196         return 0;
197     }
198     if (format1 == AUDIO_FORMAT_INVALID || format2 == AUDIO_FORMAT_INVALID) {
199         return kFormatDistanceMax;
200     }
201     int diffBytes = (int)audio_bytes_per_sample(format1) -
202             audio_bytes_per_sample(format2);
203 
204     return abs(diffBytes);
205 }
206 
isBetterFormatMatch(audio_format_t newFormat,audio_format_t currentFormat,audio_format_t targetFormat)207 bool PolicyAudioPort::isBetterFormatMatch(audio_format_t newFormat,
208                                           audio_format_t currentFormat,
209                                           audio_format_t targetFormat)
210 {
211     return formatDistance(newFormat, targetFormat) < formatDistance(currentFormat, targetFormat);
212 }
213 
pickAudioProfile(uint32_t & samplingRate,audio_channel_mask_t & channelMask,audio_format_t & format) const214 void PolicyAudioPort::pickAudioProfile(uint32_t &samplingRate,
215                                        audio_channel_mask_t &channelMask,
216                                        audio_format_t &format) const
217 {
218     format = AUDIO_FORMAT_DEFAULT;
219     samplingRate = 0;
220     channelMask = AUDIO_CHANNEL_NONE;
221 
222     // special case for uninitialized dynamic profile
223     if (!asAudioPort()->hasValidAudioProfile()) {
224         return;
225     }
226     audio_format_t bestFormat = sPcmFormatCompareTable[ARRAY_SIZE(sPcmFormatCompareTable) - 1];
227     // For mixed output and inputs, use best mixer output format.
228     // Do not limit format otherwise
229     if ((asAudioPort()->getType() != AUDIO_PORT_TYPE_MIX) || asAudioPort()->isDirectOutput()) {
230         bestFormat = AUDIO_FORMAT_INVALID;
231     }
232 
233     const AudioProfileVector& audioProfiles = asAudioPort()->getAudioProfiles();
234     for (size_t i = 0; i < audioProfiles.size(); i ++) {
235         if (!audioProfiles[i]->isValid()) {
236             continue;
237         }
238         audio_format_t formatToCompare = audioProfiles[i]->getFormat();
239         if ((compareFormats(formatToCompare, format) > 0) &&
240                 (compareFormats(formatToCompare, bestFormat) <= 0)) {
241             uint32_t pickedSamplingRate = 0;
242             audio_channel_mask_t pickedChannelMask = AUDIO_CHANNEL_NONE;
243             pickChannelMask(pickedChannelMask, audioProfiles[i]->getChannels());
244             pickSamplingRate(pickedSamplingRate, audioProfiles[i]->getSampleRates());
245 
246             if (formatToCompare != AUDIO_FORMAT_DEFAULT && pickedChannelMask != AUDIO_CHANNEL_NONE
247                     && pickedSamplingRate != 0) {
248                 format = formatToCompare;
249                 channelMask = pickedChannelMask;
250                 samplingRate = pickedSamplingRate;
251                 // TODO: shall we return on the first one or still trying to pick a better Profile?
252             }
253         }
254     }
255     ALOGV("%s Port[nm:%s] profile rate=%d, format=%d, channels=%d", __FUNCTION__,
256             asAudioPort()->getName().c_str(), samplingRate, channelMask, format);
257 }
258 
checkAudioProfile(const struct audio_port_config * config,std::function<status_t (const AudioProfileVector &,const uint32_t,audio_channel_mask_t,audio_format_t)> checkProfile) const259 status_t PolicyAudioPort::checkAudioProfile(
260         const struct audio_port_config *config,
261         std::function<status_t(const AudioProfileVector &,
262                                const uint32_t,
263                                audio_channel_mask_t,
264                                audio_format_t)> checkProfile) const {
265     status_t status = NO_ERROR;
266     auto config_mask = config->config_mask;
267     if (config_mask & AUDIO_PORT_CONFIG_GAIN) {
268         config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
269         status = asAudioPort()->checkGain(&config->gain, config->gain.index);
270         if (status != NO_ERROR) {
271             return status;
272         }
273     }
274     if (config_mask != 0) {
275         // TODO should we check sample_rate / channel_mask / format separately?
276         status = checkProfile(asAudioPort()->getAudioProfiles(), config->sample_rate,
277                    config->channel_mask, config->format);
278     }
279     return status;
280 
281 }
282 
283 } // namespace android
284