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