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::AudioPort"
18 //#define LOG_NDEBUG 0
19 #include "TypeConverter.h"
20 #include "AudioPort.h"
21 #include "HwModule.h"
22 #include "AudioGain.h"
23 #include <policy.h>
24
25 #ifndef ARRAY_SIZE
26 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
27 #endif
28
29 namespace android {
30
31 // --- AudioPort class implementation
attach(const sp<HwModule> & module)32 void AudioPort::attach(const sp<HwModule>& module)
33 {
34 ALOGV("%s: attaching module %s to port %s", __FUNCTION__, getModuleName(), mName.string());
35 mModule = module;
36 }
37
detach()38 void AudioPort::detach()
39 {
40 mModule = nullptr;
41 }
42
43 // Note that is a different namespace than AudioFlinger unique IDs
getNextUniqueId()44 audio_port_handle_t AudioPort::getNextUniqueId()
45 {
46 return getNextHandle();
47 }
48
getModuleHandle() const49 audio_module_handle_t AudioPort::getModuleHandle() const
50 {
51 return mModule != 0 ? mModule->getHandle() : AUDIO_MODULE_HANDLE_NONE;
52 }
53
getModuleVersionMajor() const54 uint32_t AudioPort::getModuleVersionMajor() const
55 {
56 return mModule != 0 ? mModule->getHalVersionMajor() : 0;
57 }
58
getModuleName() const59 const char *AudioPort::getModuleName() const
60 {
61 return mModule != 0 ? mModule->getName() : "invalid module";
62 }
63
toAudioPort(struct audio_port * port) const64 void AudioPort::toAudioPort(struct audio_port *port) const
65 {
66 // TODO: update this function once audio_port structure reflects the new profile definition.
67 // For compatibility reason: flatening the AudioProfile into audio_port structure.
68 SortedVector<audio_format_t> flatenedFormats;
69 SampleRateVector flatenedRates;
70 ChannelsVector flatenedChannels;
71 for (const auto& profile : mProfiles) {
72 if (profile->isValid()) {
73 audio_format_t formatToExport = profile->getFormat();
74 const SampleRateVector &ratesToExport = profile->getSampleRates();
75 const ChannelsVector &channelsToExport = profile->getChannels();
76
77 if (flatenedFormats.indexOf(formatToExport) < 0) {
78 flatenedFormats.add(formatToExport);
79 }
80 for (size_t rateIndex = 0; rateIndex < ratesToExport.size(); rateIndex++) {
81 uint32_t rate = ratesToExport[rateIndex];
82 if (flatenedRates.indexOf(rate) < 0) {
83 flatenedRates.add(rate);
84 }
85 }
86 for (size_t chanIndex = 0; chanIndex < channelsToExport.size(); chanIndex++) {
87 audio_channel_mask_t channels = channelsToExport[chanIndex];
88 if (flatenedChannels.indexOf(channels) < 0) {
89 flatenedChannels.add(channels);
90 }
91 }
92 if (flatenedRates.size() > AUDIO_PORT_MAX_SAMPLING_RATES ||
93 flatenedChannels.size() > AUDIO_PORT_MAX_CHANNEL_MASKS ||
94 flatenedFormats.size() > AUDIO_PORT_MAX_FORMATS) {
95 ALOGE("%s: bailing out: cannot export profiles to port config", __FUNCTION__);
96 return;
97 }
98 }
99 }
100 port->role = mRole;
101 port->type = mType;
102 strlcpy(port->name, mName, AUDIO_PORT_MAX_NAME_LEN);
103 port->num_sample_rates = flatenedRates.size();
104 port->num_channel_masks = flatenedChannels.size();
105 port->num_formats = flatenedFormats.size();
106 for (size_t i = 0; i < flatenedRates.size(); i++) {
107 port->sample_rates[i] = flatenedRates[i];
108 }
109 for (size_t i = 0; i < flatenedChannels.size(); i++) {
110 port->channel_masks[i] = flatenedChannels[i];
111 }
112 for (size_t i = 0; i < flatenedFormats.size(); i++) {
113 port->formats[i] = flatenedFormats[i];
114 }
115
116 ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size());
117
118 uint32_t i;
119 for (i = 0; i < mGains.size() && i < AUDIO_PORT_MAX_GAINS; i++) {
120 port->gains[i] = mGains[i]->getGain();
121 }
122 port->num_gains = i;
123 }
124
importAudioPort(const sp<AudioPort> & port,bool force __unused)125 void AudioPort::importAudioPort(const sp<AudioPort>& port, bool force __unused)
126 {
127 for (const auto& profileToImport : port->mProfiles) {
128 if (profileToImport->isValid()) {
129 // Import only valid port, i.e. valid format, non empty rates and channels masks
130 bool hasSameProfile = false;
131 for (const auto& profile : mProfiles) {
132 if (*profile == *profileToImport) {
133 // never import a profile twice
134 hasSameProfile = true;
135 break;
136 }
137 }
138 if (hasSameProfile) { // never import a same profile twice
139 continue;
140 }
141 addAudioProfile(profileToImport);
142 }
143 }
144 }
145
checkExactAudioProfile(const struct audio_port_config * config) const146 status_t AudioPort::checkExactAudioProfile(const struct audio_port_config *config) const
147 {
148 status_t status = NO_ERROR;
149 auto config_mask = config->config_mask;
150 if (config_mask & AUDIO_PORT_CONFIG_GAIN) {
151 config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
152 status = checkGain(&config->gain, config->gain.index);
153 if (status != NO_ERROR) {
154 return status;
155 }
156 }
157 if (config_mask != 0) {
158 // TODO should we check sample_rate / channel_mask / format separately?
159 status = mProfiles.checkExactProfile(config->sample_rate,
160 config->channel_mask,
161 config->format);
162 }
163 return status;
164 }
165
pickSamplingRate(uint32_t & pickedRate,const SampleRateVector & samplingRates) const166 void AudioPort::pickSamplingRate(uint32_t &pickedRate,const SampleRateVector &samplingRates) const
167 {
168 pickedRate = 0;
169 // For direct outputs, pick minimum sampling rate: this helps ensuring that the
170 // channel count / sampling rate combination chosen will be supported by the connected
171 // sink
172 if (isDirectOutput()) {
173 uint32_t samplingRate = UINT_MAX;
174 for (size_t i = 0; i < samplingRates.size(); i ++) {
175 if ((samplingRates[i] < samplingRate) && (samplingRates[i] > 0)) {
176 samplingRate = samplingRates[i];
177 }
178 }
179 pickedRate = (samplingRate == UINT_MAX) ? 0 : samplingRate;
180 } else {
181 uint32_t maxRate = SAMPLE_RATE_HZ_MAX;
182
183 // For mixed output and inputs, use max mixer sampling rates. Do not
184 // limit sampling rate otherwise
185 // For inputs, also see checkCompatibleSamplingRate().
186 if (mType != AUDIO_PORT_TYPE_MIX) {
187 maxRate = UINT_MAX;
188 }
189 // TODO: should mSamplingRates[] be ordered in terms of our preference
190 // and we return the first (and hence most preferred) match? This is of concern if
191 // we want to choose 96kHz over 192kHz for USB driver stability or resource constraints.
192 for (size_t i = 0; i < samplingRates.size(); i ++) {
193 if ((samplingRates[i] > pickedRate) && (samplingRates[i] <= maxRate)) {
194 pickedRate = samplingRates[i];
195 }
196 }
197 }
198 }
199
pickChannelMask(audio_channel_mask_t & pickedChannelMask,const ChannelsVector & channelMasks) const200 void AudioPort::pickChannelMask(audio_channel_mask_t &pickedChannelMask,
201 const ChannelsVector &channelMasks) const
202 {
203 pickedChannelMask = AUDIO_CHANNEL_NONE;
204 // For direct outputs, pick minimum channel count: this helps ensuring that the
205 // channel count / sampling rate combination chosen will be supported by the connected
206 // sink
207 if (isDirectOutput()) {
208 uint32_t channelCount = UINT_MAX;
209 for (size_t i = 0; i < channelMasks.size(); i ++) {
210 uint32_t cnlCount;
211 if (useInputChannelMask()) {
212 cnlCount = audio_channel_count_from_in_mask(channelMasks[i]);
213 } else {
214 cnlCount = audio_channel_count_from_out_mask(channelMasks[i]);
215 }
216 if ((cnlCount < channelCount) && (cnlCount > 0)) {
217 pickedChannelMask = channelMasks[i];
218 channelCount = cnlCount;
219 }
220 }
221 } else {
222 uint32_t channelCount = 0;
223 uint32_t maxCount = MAX_MIXER_CHANNEL_COUNT;
224
225 // For mixed output and inputs, use max mixer channel count. Do not
226 // limit channel count otherwise
227 if (mType != AUDIO_PORT_TYPE_MIX) {
228 maxCount = UINT_MAX;
229 }
230 for (size_t i = 0; i < channelMasks.size(); i ++) {
231 uint32_t cnlCount;
232 if (useInputChannelMask()) {
233 cnlCount = audio_channel_count_from_in_mask(channelMasks[i]);
234 } else {
235 cnlCount = audio_channel_count_from_out_mask(channelMasks[i]);
236 }
237 if ((cnlCount > channelCount) && (cnlCount <= maxCount)) {
238 pickedChannelMask = channelMasks[i];
239 channelCount = cnlCount;
240 }
241 }
242 }
243 }
244
245 /* format in order of increasing preference */
246 const audio_format_t AudioPort::sPcmFormatCompareTable[] = {
247 AUDIO_FORMAT_DEFAULT,
248 AUDIO_FORMAT_PCM_16_BIT,
249 AUDIO_FORMAT_PCM_8_24_BIT,
250 AUDIO_FORMAT_PCM_24_BIT_PACKED,
251 AUDIO_FORMAT_PCM_32_BIT,
252 AUDIO_FORMAT_PCM_FLOAT,
253 };
254
compareFormats(audio_format_t format1,audio_format_t format2)255 int AudioPort::compareFormats(audio_format_t format1, audio_format_t format2)
256 {
257 // NOTE: AUDIO_FORMAT_INVALID is also considered not PCM and will be compared equal to any
258 // compressed format and better than any PCM format. This is by design of pickFormat()
259 if (!audio_is_linear_pcm(format1)) {
260 if (!audio_is_linear_pcm(format2)) {
261 return 0;
262 }
263 return 1;
264 }
265 if (!audio_is_linear_pcm(format2)) {
266 return -1;
267 }
268
269 int index1 = -1, index2 = -1;
270 for (size_t i = 0;
271 (i < ARRAY_SIZE(sPcmFormatCompareTable)) && ((index1 == -1) || (index2 == -1));
272 i ++) {
273 if (sPcmFormatCompareTable[i] == format1) {
274 index1 = i;
275 }
276 if (sPcmFormatCompareTable[i] == format2) {
277 index2 = i;
278 }
279 }
280 // format1 not found => index1 < 0 => format2 > format1
281 // format2 not found => index2 < 0 => format2 < format1
282 return index1 - index2;
283 }
284
formatDistance(audio_format_t format1,audio_format_t format2)285 uint32_t AudioPort::formatDistance(audio_format_t format1, audio_format_t format2)
286 {
287 if (format1 == format2) {
288 return 0;
289 }
290 if (format1 == AUDIO_FORMAT_INVALID || format2 == AUDIO_FORMAT_INVALID) {
291 return kFormatDistanceMax;
292 }
293 int diffBytes = (int)audio_bytes_per_sample(format1) -
294 audio_bytes_per_sample(format2);
295
296 return abs(diffBytes);
297 }
298
isBetterFormatMatch(audio_format_t newFormat,audio_format_t currentFormat,audio_format_t targetFormat)299 bool AudioPort::isBetterFormatMatch(audio_format_t newFormat,
300 audio_format_t currentFormat,
301 audio_format_t targetFormat)
302 {
303 return formatDistance(newFormat, targetFormat) < formatDistance(currentFormat, targetFormat);
304 }
305
pickAudioProfile(uint32_t & samplingRate,audio_channel_mask_t & channelMask,audio_format_t & format) const306 void AudioPort::pickAudioProfile(uint32_t &samplingRate,
307 audio_channel_mask_t &channelMask,
308 audio_format_t &format) const
309 {
310 format = AUDIO_FORMAT_DEFAULT;
311 samplingRate = 0;
312 channelMask = AUDIO_CHANNEL_NONE;
313
314 // special case for uninitialized dynamic profile
315 if (!mProfiles.hasValidProfile()) {
316 return;
317 }
318 audio_format_t bestFormat = sPcmFormatCompareTable[ARRAY_SIZE(sPcmFormatCompareTable) - 1];
319 // For mixed output and inputs, use best mixer output format.
320 // Do not limit format otherwise
321 if ((mType != AUDIO_PORT_TYPE_MIX) || isDirectOutput()) {
322 bestFormat = AUDIO_FORMAT_INVALID;
323 }
324
325 for (size_t i = 0; i < mProfiles.size(); i ++) {
326 if (!mProfiles[i]->isValid()) {
327 continue;
328 }
329 audio_format_t formatToCompare = mProfiles[i]->getFormat();
330 if ((compareFormats(formatToCompare, format) > 0) &&
331 (compareFormats(formatToCompare, bestFormat) <= 0)) {
332 uint32_t pickedSamplingRate = 0;
333 audio_channel_mask_t pickedChannelMask = AUDIO_CHANNEL_NONE;
334 pickChannelMask(pickedChannelMask, mProfiles[i]->getChannels());
335 pickSamplingRate(pickedSamplingRate, mProfiles[i]->getSampleRates());
336
337 if (formatToCompare != AUDIO_FORMAT_DEFAULT && pickedChannelMask != AUDIO_CHANNEL_NONE
338 && pickedSamplingRate != 0) {
339 format = formatToCompare;
340 channelMask = pickedChannelMask;
341 samplingRate = pickedSamplingRate;
342 // TODO: shall we return on the first one or still trying to pick a better Profile?
343 }
344 }
345 }
346 ALOGV("%s Port[nm:%s] profile rate=%d, format=%d, channels=%d", __FUNCTION__, mName.string(),
347 samplingRate, channelMask, format);
348 }
349
checkGain(const struct audio_gain_config * gainConfig,int index) const350 status_t AudioPort::checkGain(const struct audio_gain_config *gainConfig, int index) const
351 {
352 if (index < 0 || (size_t)index >= mGains.size()) {
353 return BAD_VALUE;
354 }
355 return mGains[index]->checkConfig(gainConfig);
356 }
357
dump(String8 * dst,int spaces,bool verbose) const358 void AudioPort::dump(String8 *dst, int spaces, bool verbose) const
359 {
360 if (!mName.isEmpty()) {
361 dst->appendFormat("%*s- name: %s\n", spaces, "", mName.string());
362 }
363 if (verbose) {
364 mProfiles.dump(dst, spaces);
365
366 if (mGains.size() != 0) {
367 dst->appendFormat("%*s- gains:\n", spaces, "");
368 for (size_t i = 0; i < mGains.size(); i++) {
369 mGains[i]->dump(dst, spaces + 2, i);
370 }
371 }
372 }
373 }
374
log(const char * indent) const375 void AudioPort::log(const char* indent) const
376 {
377 ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.string(), mType, mRole);
378 }
379
380 // --- AudioPortConfig class implementation
381
applyAudioPortConfig(const struct audio_port_config * config,struct audio_port_config * backupConfig)382 status_t AudioPortConfig::applyAudioPortConfig(const struct audio_port_config *config,
383 struct audio_port_config *backupConfig)
384 {
385 struct audio_port_config localBackupConfig = { .config_mask = config->config_mask };
386 status_t status = NO_ERROR;
387
388 toAudioPortConfig(&localBackupConfig);
389
390 sp<AudioPort> audioport = getAudioPort();
391 if (audioport == 0) {
392 status = NO_INIT;
393 goto exit;
394 }
395 status = audioport->checkExactAudioProfile(config);
396 if (status != NO_ERROR) {
397 goto exit;
398 }
399 if (config->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
400 mSamplingRate = config->sample_rate;
401 }
402 if (config->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
403 mChannelMask = config->channel_mask;
404 }
405 if (config->config_mask & AUDIO_PORT_CONFIG_FORMAT) {
406 mFormat = config->format;
407 }
408 if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) {
409 mGain = config->gain;
410 }
411 if (config->config_mask & AUDIO_PORT_CONFIG_FLAGS) {
412 mFlags = config->flags;
413 }
414
415 exit:
416 if (status != NO_ERROR) {
417 applyAudioPortConfig(&localBackupConfig);
418 }
419 if (backupConfig != NULL) {
420 *backupConfig = localBackupConfig;
421 }
422 return status;
423 }
424
425 namespace {
426
427 template<typename T>
updateField(const T & portConfigField,T audio_port_config::* port_config_field,struct audio_port_config * dstConfig,const struct audio_port_config * srcConfig,unsigned int configMask,T defaultValue)428 void updateField(
429 const T& portConfigField, T audio_port_config::*port_config_field,
430 struct audio_port_config *dstConfig, const struct audio_port_config *srcConfig,
431 unsigned int configMask, T defaultValue)
432 {
433 if (dstConfig->config_mask & configMask) {
434 if ((srcConfig != nullptr) && (srcConfig->config_mask & configMask)) {
435 dstConfig->*port_config_field = srcConfig->*port_config_field;
436 } else {
437 dstConfig->*port_config_field = portConfigField;
438 }
439 } else {
440 dstConfig->*port_config_field = defaultValue;
441 }
442 }
443
444 } // namespace
445
toAudioPortConfig(struct audio_port_config * dstConfig,const struct audio_port_config * srcConfig) const446 void AudioPortConfig::toAudioPortConfig(struct audio_port_config *dstConfig,
447 const struct audio_port_config *srcConfig) const
448 {
449 updateField(mSamplingRate, &audio_port_config::sample_rate,
450 dstConfig, srcConfig, AUDIO_PORT_CONFIG_SAMPLE_RATE, 0u);
451 updateField(mChannelMask, &audio_port_config::channel_mask,
452 dstConfig, srcConfig, AUDIO_PORT_CONFIG_CHANNEL_MASK,
453 (audio_channel_mask_t)AUDIO_CHANNEL_NONE);
454 updateField(mFormat, &audio_port_config::format,
455 dstConfig, srcConfig, AUDIO_PORT_CONFIG_FORMAT, AUDIO_FORMAT_INVALID);
456
457 sp<AudioPort> audioport = getAudioPort();
458 if ((dstConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) && audioport != NULL) {
459 dstConfig->gain = mGain;
460 if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_GAIN)
461 && audioport->checkGain(&srcConfig->gain, srcConfig->gain.index) == OK) {
462 dstConfig->gain = srcConfig->gain;
463 }
464 } else {
465 dstConfig->gain.index = -1;
466 }
467 if (dstConfig->gain.index != -1) {
468 dstConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN;
469 } else {
470 dstConfig->config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
471 }
472
473 updateField(mFlags, &audio_port_config::flags,
474 dstConfig, srcConfig, AUDIO_PORT_CONFIG_FLAGS, { AUDIO_INPUT_FLAG_NONE });
475 }
476
hasGainController(bool canUseForVolume) const477 bool AudioPortConfig::hasGainController(bool canUseForVolume) const
478 {
479 sp<AudioPort> audioport = getAudioPort();
480 if (audioport == nullptr) {
481 return false;
482 }
483 return canUseForVolume ? audioport->getGains().canUseForVolume()
484 : audioport->getGains().size() > 0;
485 }
486
487 } // namespace android
488