AudioPort.cpp revision cc750d3604b33a92374253b12dd739dc06440aad
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 <media/AudioResamplerPublic.h>
20#include "AudioPort.h"
21#include "HwModule.h"
22#include "AudioGain.h"
23#include "ConfigParsingUtils.h"
24#include "audio_policy_conf.h"
25#include <policy.h>
26
27namespace android {
28
29int32_t volatile AudioPort::mNextUniqueId = 1;
30
31// --- AudioPort class implementation
32
33AudioPort::AudioPort(const String8& name, audio_port_type_t type,
34                     audio_port_role_t role) :
35    mName(name), mType(type), mRole(role), mFlags(0)
36{
37    mUseInChannelMask = ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) ||
38                    ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK));
39}
40
41void AudioPort::attach(const sp<HwModule>& module)
42{
43    mModule = module;
44}
45
46audio_port_handle_t AudioPort::getNextUniqueId()
47{
48    return static_cast<audio_port_handle_t>(android_atomic_inc(&mNextUniqueId));
49}
50
51audio_module_handle_t AudioPort::getModuleHandle() const
52{
53    if (mModule == 0) {
54        return 0;
55    }
56    return mModule->mHandle;
57}
58
59uint32_t AudioPort::getModuleVersion() const
60{
61    if (mModule == 0) {
62        return 0;
63    }
64    return mModule->mHalVersion;
65}
66
67const char *AudioPort::getModuleName() const
68{
69    if (mModule == 0) {
70        return "";
71    }
72    return mModule->mName;
73}
74
75void AudioPort::toAudioPort(struct audio_port *port) const
76{
77    port->role = mRole;
78    port->type = mType;
79    strlcpy(port->name, mName, AUDIO_PORT_MAX_NAME_LEN);
80    unsigned int i;
81    for (i = 0; i < mSamplingRates.size() && i < AUDIO_PORT_MAX_SAMPLING_RATES; i++) {
82        if (mSamplingRates[i] != 0) {
83            port->sample_rates[i] = mSamplingRates[i];
84        }
85    }
86    port->num_sample_rates = i;
87    for (i = 0; i < mChannelMasks.size() && i < AUDIO_PORT_MAX_CHANNEL_MASKS; i++) {
88        if (mChannelMasks[i] != 0) {
89            port->channel_masks[i] = mChannelMasks[i];
90        }
91    }
92    port->num_channel_masks = i;
93    for (i = 0; i < mFormats.size() && i < AUDIO_PORT_MAX_FORMATS; i++) {
94        if (mFormats[i] != 0) {
95            port->formats[i] = mFormats[i];
96        }
97    }
98    port->num_formats = i;
99
100    ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size());
101
102    for (i = 0; i < mGains.size() && i < AUDIO_PORT_MAX_GAINS; i++) {
103        port->gains[i] = mGains[i]->mGain;
104    }
105    port->num_gains = i;
106}
107
108void AudioPort::importAudioPort(const sp<AudioPort> port) {
109    for (size_t k = 0 ; k < port->mSamplingRates.size() ; k++) {
110        const uint32_t rate = port->mSamplingRates.itemAt(k);
111        if (rate != 0) { // skip "dynamic" rates
112            bool hasRate = false;
113            for (size_t l = 0 ; l < mSamplingRates.size() ; l++) {
114                if (rate == mSamplingRates.itemAt(l)) {
115                    hasRate = true;
116                    break;
117                }
118            }
119            if (!hasRate) { // never import a sampling rate twice
120                mSamplingRates.add(rate);
121            }
122        }
123    }
124    for (size_t k = 0 ; k < port->mChannelMasks.size() ; k++) {
125        const audio_channel_mask_t mask = port->mChannelMasks.itemAt(k);
126        if (mask != 0) { // skip "dynamic" masks
127            bool hasMask = false;
128            for (size_t l = 0 ; l < mChannelMasks.size() ; l++) {
129                if (mask == mChannelMasks.itemAt(l)) {
130                    hasMask = true;
131                    break;
132                }
133            }
134            if (!hasMask) { // never import a channel mask twice
135                mChannelMasks.add(mask);
136            }
137        }
138    }
139    for (size_t k = 0 ; k < port->mFormats.size() ; k++) {
140        const audio_format_t format = port->mFormats.itemAt(k);
141        if (format != 0) { // skip "dynamic" formats
142            bool hasFormat = false;
143            for (size_t l = 0 ; l < mFormats.size() ; l++) {
144                if (format == mFormats.itemAt(l)) {
145                    hasFormat = true;
146                    break;
147                }
148            }
149            if (!hasFormat) { // never import a format twice
150                mFormats.add(format);
151            }
152        }
153    }
154}
155
156void AudioPort::clearCapabilities() {
157    mChannelMasks.clear();
158    mFormats.clear();
159    mSamplingRates.clear();
160}
161
162void AudioPort::loadSamplingRates(char *name)
163{
164    char *str = strtok(name, "|");
165
166    // by convention, "0' in the first entry in mSamplingRates indicates the supported sampling
167    // rates should be read from the output stream after it is opened for the first time
168    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) {
169        mSamplingRates.add(0);
170        return;
171    }
172
173    while (str != NULL) {
174        uint32_t rate = atoi(str);
175        if (rate != 0) {
176            ALOGV("loadSamplingRates() adding rate %d", rate);
177            mSamplingRates.add(rate);
178        }
179        str = strtok(NULL, "|");
180    }
181}
182
183void AudioPort::loadFormats(char *name)
184{
185    char *str = strtok(name, "|");
186
187    // by convention, "0' in the first entry in mFormats indicates the supported formats
188    // should be read from the output stream after it is opened for the first time
189    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) {
190        mFormats.add(AUDIO_FORMAT_DEFAULT);
191        return;
192    }
193
194    while (str != NULL) {
195        audio_format_t format = (audio_format_t)ConfigParsingUtils::stringToEnum(sFormatNameToEnumTable,
196                                                             ARRAY_SIZE(sFormatNameToEnumTable),
197                                                             str);
198        if (format != AUDIO_FORMAT_DEFAULT) {
199            mFormats.add(format);
200        }
201        str = strtok(NULL, "|");
202    }
203    // we sort from worst to best, so that AUDIO_FORMAT_DEFAULT is always the first entry.
204    // TODO: compareFormats could be a lambda to convert between pointer-to-format to format:
205    // [](const audio_format_t *format1, const audio_format_t *format2) {
206    //     return compareFormats(*format1, *format2);
207    // }
208    mFormats.sort(compareFormats);
209}
210
211void AudioPort::loadInChannels(char *name)
212{
213    const char *str = strtok(name, "|");
214
215    ALOGV("loadInChannels() %s", name);
216
217    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) {
218        mChannelMasks.add(0);
219        return;
220    }
221
222    while (str != NULL) {
223        audio_channel_mask_t channelMask =
224                (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sInChannelsNameToEnumTable,
225                                                   ARRAY_SIZE(sInChannelsNameToEnumTable),
226                                                   str);
227        if (channelMask == 0) { // if not found, check the channel index table
228            channelMask = (audio_channel_mask_t)
229                      ConfigParsingUtils::stringToEnum(sIndexChannelsNameToEnumTable,
230                              ARRAY_SIZE(sIndexChannelsNameToEnumTable),
231                              str);
232        }
233        if (channelMask != 0) {
234            ALOGV("loadInChannels() adding channelMask %#x", channelMask);
235            mChannelMasks.add(channelMask);
236        }
237        str = strtok(NULL, "|");
238    }
239}
240
241void AudioPort::loadOutChannels(char *name)
242{
243    const char *str = strtok(name, "|");
244
245    ALOGV("loadOutChannels() %s", name);
246
247    // by convention, "0' in the first entry in mChannelMasks indicates the supported channel
248    // masks should be read from the output stream after it is opened for the first time
249    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) {
250        mChannelMasks.add(0);
251        return;
252    }
253
254    while (str != NULL) {
255        audio_channel_mask_t channelMask =
256                (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sOutChannelsNameToEnumTable,
257                                                   ARRAY_SIZE(sOutChannelsNameToEnumTable),
258                                                   str);
259        if (channelMask == 0) { // if not found, check the channel index table
260            channelMask = (audio_channel_mask_t)
261                      ConfigParsingUtils::stringToEnum(sIndexChannelsNameToEnumTable,
262                              ARRAY_SIZE(sIndexChannelsNameToEnumTable),
263                              str);
264        }
265        if (channelMask != 0) {
266            mChannelMasks.add(channelMask);
267        }
268        str = strtok(NULL, "|");
269    }
270    return;
271}
272
273audio_gain_mode_t AudioPort::loadGainMode(char *name)
274{
275    const char *str = strtok(name, "|");
276
277    ALOGV("loadGainMode() %s", name);
278    audio_gain_mode_t mode = 0;
279    while (str != NULL) {
280        mode |= (audio_gain_mode_t)ConfigParsingUtils::stringToEnum(sGainModeNameToEnumTable,
281                                                ARRAY_SIZE(sGainModeNameToEnumTable),
282                                                str);
283        str = strtok(NULL, "|");
284    }
285    return mode;
286}
287
288void AudioPort::loadGain(cnode *root, int index)
289{
290    cnode *node = root->first_child;
291
292    sp<AudioGain> gain = new AudioGain(index, mUseInChannelMask);
293
294    while (node) {
295        if (strcmp(node->name, GAIN_MODE) == 0) {
296            gain->mGain.mode = loadGainMode((char *)node->value);
297        } else if (strcmp(node->name, GAIN_CHANNELS) == 0) {
298            if (mUseInChannelMask) {
299                gain->mGain.channel_mask =
300                        (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sInChannelsNameToEnumTable,
301                                                           ARRAY_SIZE(sInChannelsNameToEnumTable),
302                                                           (char *)node->value);
303            } else {
304                gain->mGain.channel_mask =
305                        (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sOutChannelsNameToEnumTable,
306                                                           ARRAY_SIZE(sOutChannelsNameToEnumTable),
307                                                           (char *)node->value);
308            }
309        } else if (strcmp(node->name, GAIN_MIN_VALUE) == 0) {
310            gain->mGain.min_value = atoi((char *)node->value);
311        } else if (strcmp(node->name, GAIN_MAX_VALUE) == 0) {
312            gain->mGain.max_value = atoi((char *)node->value);
313        } else if (strcmp(node->name, GAIN_DEFAULT_VALUE) == 0) {
314            gain->mGain.default_value = atoi((char *)node->value);
315        } else if (strcmp(node->name, GAIN_STEP_VALUE) == 0) {
316            gain->mGain.step_value = atoi((char *)node->value);
317        } else if (strcmp(node->name, GAIN_MIN_RAMP_MS) == 0) {
318            gain->mGain.min_ramp_ms = atoi((char *)node->value);
319        } else if (strcmp(node->name, GAIN_MAX_RAMP_MS) == 0) {
320            gain->mGain.max_ramp_ms = atoi((char *)node->value);
321        }
322        node = node->next;
323    }
324
325    ALOGV("loadGain() adding new gain mode %08x channel mask %08x min mB %d max mB %d",
326          gain->mGain.mode, gain->mGain.channel_mask, gain->mGain.min_value, gain->mGain.max_value);
327
328    if (gain->mGain.mode == 0) {
329        return;
330    }
331    mGains.add(gain);
332}
333
334void AudioPort::loadGains(cnode *root)
335{
336    cnode *node = root->first_child;
337    int index = 0;
338    while (node) {
339        ALOGV("loadGains() loading gain %s", node->name);
340        loadGain(node, index++);
341        node = node->next;
342    }
343}
344
345status_t AudioPort::checkExactSamplingRate(uint32_t samplingRate) const
346{
347    if (mSamplingRates.isEmpty()) {
348        return NO_ERROR;
349    }
350
351    for (size_t i = 0; i < mSamplingRates.size(); i ++) {
352        if (mSamplingRates[i] == samplingRate) {
353            return NO_ERROR;
354        }
355    }
356    return BAD_VALUE;
357}
358
359status_t AudioPort::checkCompatibleSamplingRate(uint32_t samplingRate,
360        uint32_t *updatedSamplingRate) const
361{
362    if (mSamplingRates.isEmpty()) {
363        if (updatedSamplingRate != NULL) {
364            *updatedSamplingRate = samplingRate;
365        }
366        return NO_ERROR;
367    }
368
369    // Search for the closest supported sampling rate that is above (preferred)
370    // or below (acceptable) the desired sampling rate, within a permitted ratio.
371    // The sampling rates do not need to be sorted in ascending order.
372    ssize_t maxBelow = -1;
373    ssize_t minAbove = -1;
374    uint32_t candidate;
375    for (size_t i = 0; i < mSamplingRates.size(); i++) {
376        candidate = mSamplingRates[i];
377        if (candidate == samplingRate) {
378            if (updatedSamplingRate != NULL) {
379                *updatedSamplingRate = candidate;
380            }
381            return NO_ERROR;
382        }
383        // candidate < desired
384        if (candidate < samplingRate) {
385            if (maxBelow < 0 || candidate > mSamplingRates[maxBelow]) {
386                maxBelow = i;
387            }
388        // candidate > desired
389        } else {
390            if (minAbove < 0 || candidate < mSamplingRates[minAbove]) {
391                minAbove = i;
392            }
393        }
394    }
395
396    // Prefer to down-sample from a higher sampling rate, as we get the desired frequency spectrum.
397    if (minAbove >= 0) {
398        candidate = mSamplingRates[minAbove];
399        if (candidate / AUDIO_RESAMPLER_DOWN_RATIO_MAX <= samplingRate) {
400            if (updatedSamplingRate != NULL) {
401                *updatedSamplingRate = candidate;
402            }
403            return NO_ERROR;
404        }
405    }
406    // But if we have to up-sample from a lower sampling rate, that's OK.
407    if (maxBelow >= 0) {
408        candidate = mSamplingRates[maxBelow];
409        if (candidate * AUDIO_RESAMPLER_UP_RATIO_MAX >= samplingRate) {
410            if (updatedSamplingRate != NULL) {
411                *updatedSamplingRate = candidate;
412            }
413            return NO_ERROR;
414        }
415    }
416    // leave updatedSamplingRate unmodified
417    return BAD_VALUE;
418}
419
420status_t AudioPort::checkExactChannelMask(audio_channel_mask_t channelMask) const
421{
422    if (mChannelMasks.isEmpty()) {
423        return NO_ERROR;
424    }
425
426    for (size_t i = 0; i < mChannelMasks.size(); i++) {
427        if (mChannelMasks[i] == channelMask) {
428            return NO_ERROR;
429        }
430    }
431    return BAD_VALUE;
432}
433
434status_t AudioPort::checkCompatibleChannelMask(audio_channel_mask_t channelMask,
435        audio_channel_mask_t *updatedChannelMask) const
436{
437    if (mChannelMasks.isEmpty()) {
438        if (updatedChannelMask != NULL) {
439            *updatedChannelMask = channelMask;
440        }
441        return NO_ERROR;
442    }
443
444    const bool isRecordThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK;
445    const bool isIndex = audio_channel_mask_get_representation(channelMask)
446            == AUDIO_CHANNEL_REPRESENTATION_INDEX;
447    int bestMatch = 0;
448    for (size_t i = 0; i < mChannelMasks.size(); i ++) {
449        audio_channel_mask_t supported = mChannelMasks[i];
450        if (supported == channelMask) {
451            // Exact matches always taken.
452            if (updatedChannelMask != NULL) {
453                *updatedChannelMask = channelMask;
454            }
455            return NO_ERROR;
456        }
457
458        // AUDIO_CHANNEL_NONE (value: 0) is used for dynamic channel support
459        if (isRecordThread && supported != AUDIO_CHANNEL_NONE) {
460            // Approximate (best) match:
461            // The match score measures how well the supported channel mask matches the
462            // desired mask, where increasing-is-better.
463            //
464            // TODO: Some tweaks may be needed.
465            // Should be a static function of the data processing library.
466            //
467            // In priority:
468            // match score = 1000 if legacy channel conversion equivalent (always prefer this)
469            // OR
470            // match score += 100 if the channel mask representations match
471            // match score += number of channels matched.
472            //
473            // If there are no matched channels, the mask may still be accepted
474            // but the playback or record will be silent.
475            const bool isSupportedIndex = (audio_channel_mask_get_representation(supported)
476                    == AUDIO_CHANNEL_REPRESENTATION_INDEX);
477            int match;
478            if (isIndex && isSupportedIndex) {
479                // index equivalence
480                match = 100 + __builtin_popcount(
481                        audio_channel_mask_get_bits(channelMask)
482                            & audio_channel_mask_get_bits(supported));
483            } else if (isIndex && !isSupportedIndex) {
484                const uint32_t equivalentBits =
485                        (1 << audio_channel_count_from_in_mask(supported)) - 1 ;
486                match = __builtin_popcount(
487                        audio_channel_mask_get_bits(channelMask) & equivalentBits);
488            } else if (!isIndex && isSupportedIndex) {
489                const uint32_t equivalentBits =
490                        (1 << audio_channel_count_from_in_mask(channelMask)) - 1;
491                match = __builtin_popcount(
492                        equivalentBits & audio_channel_mask_get_bits(supported));
493            } else {
494                // positional equivalence
495                match = 100 + __builtin_popcount(
496                        audio_channel_mask_get_bits(channelMask)
497                            & audio_channel_mask_get_bits(supported));
498                switch (supported) {
499                case AUDIO_CHANNEL_IN_FRONT_BACK:
500                case AUDIO_CHANNEL_IN_STEREO:
501                    if (channelMask == AUDIO_CHANNEL_IN_MONO) {
502                        match = 1000;
503                    }
504                    break;
505                case AUDIO_CHANNEL_IN_MONO:
506                    if (channelMask == AUDIO_CHANNEL_IN_FRONT_BACK
507                            || channelMask == AUDIO_CHANNEL_IN_STEREO) {
508                        match = 1000;
509                    }
510                    break;
511                default:
512                    break;
513                }
514            }
515            if (match > bestMatch) {
516                bestMatch = match;
517                if (updatedChannelMask != NULL) {
518                    *updatedChannelMask = supported;
519                } else {
520                    return NO_ERROR; // any match will do in this case.
521                }
522            }
523        }
524    }
525    return bestMatch > 0 ? NO_ERROR : BAD_VALUE;
526}
527
528status_t AudioPort::checkExactFormat(audio_format_t format) const
529{
530    if (mFormats.isEmpty()) {
531        return NO_ERROR;
532    }
533
534    for (size_t i = 0; i < mFormats.size(); i ++) {
535        if (mFormats[i] == format) {
536            return NO_ERROR;
537        }
538    }
539    return BAD_VALUE;
540}
541
542status_t AudioPort::checkCompatibleFormat(audio_format_t format, audio_format_t *updatedFormat)
543        const
544{
545    if (mFormats.isEmpty()) {
546        if (updatedFormat != NULL) {
547            *updatedFormat = format;
548        }
549        return NO_ERROR;
550    }
551
552    const bool checkInexact = // when port is input and format is linear pcm
553            mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK
554            && audio_is_linear_pcm(format);
555
556    // iterate from best format to worst format (reverse order)
557    for (ssize_t i = mFormats.size() - 1; i >= 0 ; --i) {
558        if (mFormats[i] == format ||
559                (checkInexact
560                        && mFormats[i] != AUDIO_FORMAT_DEFAULT
561                        && audio_is_linear_pcm(mFormats[i]))) {
562            // for inexact checks we take the first linear pcm format due to sorting.
563            if (updatedFormat != NULL) {
564                *updatedFormat = mFormats[i];
565            }
566            return NO_ERROR;
567        }
568    }
569    return BAD_VALUE;
570}
571
572uint32_t AudioPort::pickSamplingRate() const
573{
574    // special case for uninitialized dynamic profile
575    if (mSamplingRates.size() == 1 && mSamplingRates[0] == 0) {
576        return 0;
577    }
578
579    // For direct outputs, pick minimum sampling rate: this helps ensuring that the
580    // channel count / sampling rate combination chosen will be supported by the connected
581    // sink
582    if ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) &&
583            (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))) {
584        uint32_t samplingRate = UINT_MAX;
585        for (size_t i = 0; i < mSamplingRates.size(); i ++) {
586            if ((mSamplingRates[i] < samplingRate) && (mSamplingRates[i] > 0)) {
587                samplingRate = mSamplingRates[i];
588            }
589        }
590        return (samplingRate == UINT_MAX) ? 0 : samplingRate;
591    }
592
593    uint32_t samplingRate = 0;
594    uint32_t maxRate = MAX_MIXER_SAMPLING_RATE;
595
596    // For mixed output and inputs, use max mixer sampling rates. Do not
597    // limit sampling rate otherwise
598    // For inputs, also see checkCompatibleSamplingRate().
599    if (mType != AUDIO_PORT_TYPE_MIX) {
600        maxRate = UINT_MAX;
601    }
602    // TODO: should mSamplingRates[] be ordered in terms of our preference
603    // and we return the first (and hence most preferred) match?  This is of concern if
604    // we want to choose 96kHz over 192kHz for USB driver stability or resource constraints.
605    for (size_t i = 0; i < mSamplingRates.size(); i ++) {
606        if ((mSamplingRates[i] > samplingRate) && (mSamplingRates[i] <= maxRate)) {
607            samplingRate = mSamplingRates[i];
608        }
609    }
610    return samplingRate;
611}
612
613audio_channel_mask_t AudioPort::pickChannelMask() const
614{
615    // special case for uninitialized dynamic profile
616    if (mChannelMasks.size() == 1 && mChannelMasks[0] == 0) {
617        return AUDIO_CHANNEL_NONE;
618    }
619    audio_channel_mask_t channelMask = AUDIO_CHANNEL_NONE;
620
621    // For direct outputs, pick minimum channel count: this helps ensuring that the
622    // channel count / sampling rate combination chosen will be supported by the connected
623    // sink
624    if ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) &&
625            (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))) {
626        uint32_t channelCount = UINT_MAX;
627        for (size_t i = 0; i < mChannelMasks.size(); i ++) {
628            uint32_t cnlCount;
629            if (mUseInChannelMask) {
630                cnlCount = audio_channel_count_from_in_mask(mChannelMasks[i]);
631            } else {
632                cnlCount = audio_channel_count_from_out_mask(mChannelMasks[i]);
633            }
634            if ((cnlCount < channelCount) && (cnlCount > 0)) {
635                channelMask = mChannelMasks[i];
636                channelCount = cnlCount;
637            }
638        }
639        return channelMask;
640    }
641
642    uint32_t channelCount = 0;
643    uint32_t maxCount = MAX_MIXER_CHANNEL_COUNT;
644
645    // For mixed output and inputs, use max mixer channel count. Do not
646    // limit channel count otherwise
647    if (mType != AUDIO_PORT_TYPE_MIX) {
648        maxCount = UINT_MAX;
649    }
650    for (size_t i = 0; i < mChannelMasks.size(); i ++) {
651        uint32_t cnlCount;
652        if (mUseInChannelMask) {
653            cnlCount = audio_channel_count_from_in_mask(mChannelMasks[i]);
654        } else {
655            cnlCount = audio_channel_count_from_out_mask(mChannelMasks[i]);
656        }
657        if ((cnlCount > channelCount) && (cnlCount <= maxCount)) {
658            channelMask = mChannelMasks[i];
659            channelCount = cnlCount;
660        }
661    }
662    return channelMask;
663}
664
665/* format in order of increasing preference */
666const audio_format_t AudioPort::sPcmFormatCompareTable[] = {
667        AUDIO_FORMAT_DEFAULT,
668        AUDIO_FORMAT_PCM_16_BIT,
669        AUDIO_FORMAT_PCM_8_24_BIT,
670        AUDIO_FORMAT_PCM_24_BIT_PACKED,
671        AUDIO_FORMAT_PCM_32_BIT,
672        AUDIO_FORMAT_PCM_FLOAT,
673};
674
675int AudioPort::compareFormats(audio_format_t format1,
676                                                  audio_format_t format2)
677{
678    // NOTE: AUDIO_FORMAT_INVALID is also considered not PCM and will be compared equal to any
679    // compressed format and better than any PCM format. This is by design of pickFormat()
680    if (!audio_is_linear_pcm(format1)) {
681        if (!audio_is_linear_pcm(format2)) {
682            return 0;
683        }
684        return 1;
685    }
686    if (!audio_is_linear_pcm(format2)) {
687        return -1;
688    }
689
690    int index1 = -1, index2 = -1;
691    for (size_t i = 0;
692            (i < ARRAY_SIZE(sPcmFormatCompareTable)) && ((index1 == -1) || (index2 == -1));
693            i ++) {
694        if (sPcmFormatCompareTable[i] == format1) {
695            index1 = i;
696        }
697        if (sPcmFormatCompareTable[i] == format2) {
698            index2 = i;
699        }
700    }
701    // format1 not found => index1 < 0 => format2 > format1
702    // format2 not found => index2 < 0 => format2 < format1
703    return index1 - index2;
704}
705
706audio_format_t AudioPort::pickFormat() const
707{
708    // special case for uninitialized dynamic profile
709    if (mFormats.size() == 1 && mFormats[0] == 0) {
710        return AUDIO_FORMAT_DEFAULT;
711    }
712
713    audio_format_t format = AUDIO_FORMAT_DEFAULT;
714    audio_format_t bestFormat =
715            AudioPort::sPcmFormatCompareTable[
716                ARRAY_SIZE(AudioPort::sPcmFormatCompareTable) - 1];
717    // For mixed output and inputs, use best mixer output format. Do not
718    // limit format otherwise
719    if ((mType != AUDIO_PORT_TYPE_MIX) ||
720            ((mRole == AUDIO_PORT_ROLE_SOURCE) &&
721             (((mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) != 0)))) {
722        bestFormat = AUDIO_FORMAT_INVALID;
723    }
724
725    for (size_t i = 0; i < mFormats.size(); i ++) {
726        if ((compareFormats(mFormats[i], format) > 0) &&
727                (compareFormats(mFormats[i], bestFormat) <= 0)) {
728            format = mFormats[i];
729        }
730    }
731    return format;
732}
733
734status_t AudioPort::checkGain(const struct audio_gain_config *gainConfig,
735                                                  int index) const
736{
737    if (index < 0 || (size_t)index >= mGains.size()) {
738        return BAD_VALUE;
739    }
740    return mGains[index]->checkConfig(gainConfig);
741}
742
743void AudioPort::dump(int fd, int spaces) const
744{
745    const size_t SIZE = 256;
746    char buffer[SIZE];
747    String8 result;
748
749    if (mName.length() != 0) {
750        snprintf(buffer, SIZE, "%*s- name: %s\n", spaces, "", mName.string());
751        result.append(buffer);
752    }
753
754    if (mSamplingRates.size() != 0) {
755        snprintf(buffer, SIZE, "%*s- sampling rates: ", spaces, "");
756        result.append(buffer);
757        for (size_t i = 0; i < mSamplingRates.size(); i++) {
758            if (i == 0 && mSamplingRates[i] == 0) {
759                snprintf(buffer, SIZE, "Dynamic");
760            } else {
761                snprintf(buffer, SIZE, "%d", mSamplingRates[i]);
762            }
763            result.append(buffer);
764            result.append(i == (mSamplingRates.size() - 1) ? "" : ", ");
765        }
766        result.append("\n");
767    }
768
769    if (mChannelMasks.size() != 0) {
770        snprintf(buffer, SIZE, "%*s- channel masks: ", spaces, "");
771        result.append(buffer);
772        for (size_t i = 0; i < mChannelMasks.size(); i++) {
773            ALOGV("AudioPort::dump mChannelMasks %zu %08x", i, mChannelMasks[i]);
774
775            if (i == 0 && mChannelMasks[i] == 0) {
776                snprintf(buffer, SIZE, "Dynamic");
777            } else {
778                snprintf(buffer, SIZE, "0x%04x", mChannelMasks[i]);
779            }
780            result.append(buffer);
781            result.append(i == (mChannelMasks.size() - 1) ? "" : ", ");
782        }
783        result.append("\n");
784    }
785
786    if (mFormats.size() != 0) {
787        snprintf(buffer, SIZE, "%*s- formats: ", spaces, "");
788        result.append(buffer);
789        for (size_t i = 0; i < mFormats.size(); i++) {
790            const char *formatStr = ConfigParsingUtils::enumToString(sFormatNameToEnumTable,
791                                                 ARRAY_SIZE(sFormatNameToEnumTable),
792                                                 mFormats[i]);
793            const bool isEmptyStr = formatStr[0] == 0;
794            if (i == 0 && isEmptyStr) {
795                snprintf(buffer, SIZE, "Dynamic");
796            } else {
797                if (isEmptyStr) {
798                    snprintf(buffer, SIZE, "%#x", mFormats[i]);
799                } else {
800                    snprintf(buffer, SIZE, "%s", formatStr);
801                }
802            }
803            result.append(buffer);
804            result.append(i == (mFormats.size() - 1) ? "" : ", ");
805        }
806        result.append("\n");
807    }
808    write(fd, result.string(), result.size());
809    if (mGains.size() != 0) {
810        snprintf(buffer, SIZE, "%*s- gains:\n", spaces, "");
811        write(fd, buffer, strlen(buffer) + 1);
812        for (size_t i = 0; i < mGains.size(); i++) {
813            mGains[i]->dump(fd, spaces + 2, i);
814        }
815    }
816}
817
818void AudioPort::log(const char* indent) const
819{
820    ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.string(), mType, mRole);
821}
822
823// --- AudioPortConfig class implementation
824
825AudioPortConfig::AudioPortConfig()
826{
827    mSamplingRate = 0;
828    mChannelMask = AUDIO_CHANNEL_NONE;
829    mFormat = AUDIO_FORMAT_INVALID;
830    mGain.index = -1;
831}
832
833status_t AudioPortConfig::applyAudioPortConfig(
834                                                        const struct audio_port_config *config,
835                                                        struct audio_port_config *backupConfig)
836{
837    struct audio_port_config localBackupConfig;
838    status_t status = NO_ERROR;
839
840    localBackupConfig.config_mask = config->config_mask;
841    toAudioPortConfig(&localBackupConfig);
842
843    sp<AudioPort> audioport = getAudioPort();
844    if (audioport == 0) {
845        status = NO_INIT;
846        goto exit;
847    }
848    if (config->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
849        status = audioport->checkExactSamplingRate(config->sample_rate);
850        if (status != NO_ERROR) {
851            goto exit;
852        }
853        mSamplingRate = config->sample_rate;
854    }
855    if (config->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
856        status = audioport->checkExactChannelMask(config->channel_mask);
857        if (status != NO_ERROR) {
858            goto exit;
859        }
860        mChannelMask = config->channel_mask;
861    }
862    if (config->config_mask & AUDIO_PORT_CONFIG_FORMAT) {
863        status = audioport->checkExactFormat(config->format);
864        if (status != NO_ERROR) {
865            goto exit;
866        }
867        mFormat = config->format;
868    }
869    if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) {
870        status = audioport->checkGain(&config->gain, config->gain.index);
871        if (status != NO_ERROR) {
872            goto exit;
873        }
874        mGain = config->gain;
875    }
876
877exit:
878    if (status != NO_ERROR) {
879        applyAudioPortConfig(&localBackupConfig);
880    }
881    if (backupConfig != NULL) {
882        *backupConfig = localBackupConfig;
883    }
884    return status;
885}
886
887void AudioPortConfig::toAudioPortConfig(struct audio_port_config *dstConfig,
888                                        const struct audio_port_config *srcConfig) const
889{
890    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
891        dstConfig->sample_rate = mSamplingRate;
892        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE)) {
893            dstConfig->sample_rate = srcConfig->sample_rate;
894        }
895    } else {
896        dstConfig->sample_rate = 0;
897    }
898    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
899        dstConfig->channel_mask = mChannelMask;
900        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK)) {
901            dstConfig->channel_mask = srcConfig->channel_mask;
902        }
903    } else {
904        dstConfig->channel_mask = AUDIO_CHANNEL_NONE;
905    }
906    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT) {
907        dstConfig->format = mFormat;
908        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT)) {
909            dstConfig->format = srcConfig->format;
910        }
911    } else {
912        dstConfig->format = AUDIO_FORMAT_INVALID;
913    }
914    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) {
915        dstConfig->gain = mGain;
916        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_GAIN)) {
917            dstConfig->gain = srcConfig->gain;
918        }
919    } else {
920        dstConfig->gain.index = -1;
921    }
922    if (dstConfig->gain.index != -1) {
923        dstConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN;
924    } else {
925        dstConfig->config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
926    }
927}
928
929}; // namespace android
930