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