AudioPort.cpp revision f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4
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 channel mask 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    mFormats.sort(compareFormatsGoodToBad);
220}
221
222void AudioPort::loadInChannels(char *name)
223{
224    const char *str = strtok(name, "|");
225
226    ALOGV("loadInChannels() %s", name);
227
228    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) {
229        mChannelMasks.add(0);
230        return;
231    }
232
233    while (str != NULL) {
234        audio_channel_mask_t channelMask =
235                (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sInChannelsNameToEnumTable,
236                                                   ARRAY_SIZE(sInChannelsNameToEnumTable),
237                                                   str);
238        if (channelMask != 0) {
239            ALOGV("loadInChannels() adding channelMask %04x", channelMask);
240            mChannelMasks.add(channelMask);
241        }
242        str = strtok(NULL, "|");
243    }
244}
245
246void AudioPort::loadOutChannels(char *name)
247{
248    const char *str = strtok(name, "|");
249
250    ALOGV("loadOutChannels() %s", name);
251
252    // by convention, "0' in the first entry in mChannelMasks indicates the supported channel
253    // masks should be read from the output stream after it is opened for the first time
254    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) {
255        mChannelMasks.add(0);
256        return;
257    }
258
259    while (str != NULL) {
260        audio_channel_mask_t channelMask =
261                (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sOutChannelsNameToEnumTable,
262                                                   ARRAY_SIZE(sOutChannelsNameToEnumTable),
263                                                   str);
264        if (channelMask != 0) {
265            mChannelMasks.add(channelMask);
266        }
267        str = strtok(NULL, "|");
268    }
269    return;
270}
271
272audio_gain_mode_t AudioPort::loadGainMode(char *name)
273{
274    const char *str = strtok(name, "|");
275
276    ALOGV("loadGainMode() %s", name);
277    audio_gain_mode_t mode = 0;
278    while (str != NULL) {
279        mode |= (audio_gain_mode_t)ConfigParsingUtils::stringToEnum(sGainModeNameToEnumTable,
280                                                ARRAY_SIZE(sGainModeNameToEnumTable),
281                                                str);
282        str = strtok(NULL, "|");
283    }
284    return mode;
285}
286
287void AudioPort::loadGain(cnode *root, int index)
288{
289    cnode *node = root->first_child;
290
291    sp<AudioGain> gain = new AudioGain(index, mUseInChannelMask);
292
293    while (node) {
294        if (strcmp(node->name, GAIN_MODE) == 0) {
295            gain->mGain.mode = loadGainMode((char *)node->value);
296        } else if (strcmp(node->name, GAIN_CHANNELS) == 0) {
297            if (mUseInChannelMask) {
298                gain->mGain.channel_mask =
299                        (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sInChannelsNameToEnumTable,
300                                                           ARRAY_SIZE(sInChannelsNameToEnumTable),
301                                                           (char *)node->value);
302            } else {
303                gain->mGain.channel_mask =
304                        (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sOutChannelsNameToEnumTable,
305                                                           ARRAY_SIZE(sOutChannelsNameToEnumTable),
306                                                           (char *)node->value);
307            }
308        } else if (strcmp(node->name, GAIN_MIN_VALUE) == 0) {
309            gain->mGain.min_value = atoi((char *)node->value);
310        } else if (strcmp(node->name, GAIN_MAX_VALUE) == 0) {
311            gain->mGain.max_value = atoi((char *)node->value);
312        } else if (strcmp(node->name, GAIN_DEFAULT_VALUE) == 0) {
313            gain->mGain.default_value = atoi((char *)node->value);
314        } else if (strcmp(node->name, GAIN_STEP_VALUE) == 0) {
315            gain->mGain.step_value = atoi((char *)node->value);
316        } else if (strcmp(node->name, GAIN_MIN_RAMP_MS) == 0) {
317            gain->mGain.min_ramp_ms = atoi((char *)node->value);
318        } else if (strcmp(node->name, GAIN_MAX_RAMP_MS) == 0) {
319            gain->mGain.max_ramp_ms = atoi((char *)node->value);
320        }
321        node = node->next;
322    }
323
324    ALOGV("loadGain() adding new gain mode %08x channel mask %08x min mB %d max mB %d",
325          gain->mGain.mode, gain->mGain.channel_mask, gain->mGain.min_value, gain->mGain.max_value);
326
327    if (gain->mGain.mode == 0) {
328        return;
329    }
330    mGains.add(gain);
331}
332
333void AudioPort::loadGains(cnode *root)
334{
335    cnode *node = root->first_child;
336    int index = 0;
337    while (node) {
338        ALOGV("loadGains() loading gain %s", node->name);
339        loadGain(node, index++);
340        node = node->next;
341    }
342}
343
344status_t AudioPort::checkExactSamplingRate(uint32_t samplingRate) const
345{
346    if (mSamplingRates.isEmpty()) {
347        return NO_ERROR;
348    }
349
350    for (size_t i = 0; i < mSamplingRates.size(); i ++) {
351        if (mSamplingRates[i] == samplingRate) {
352            return NO_ERROR;
353        }
354    }
355    return BAD_VALUE;
356}
357
358status_t AudioPort::checkCompatibleSamplingRate(uint32_t samplingRate,
359        uint32_t *updatedSamplingRate) const
360{
361    if (mSamplingRates.isEmpty()) {
362        if (updatedSamplingRate != NULL) {
363            *updatedSamplingRate = samplingRate;
364        }
365        return NO_ERROR;
366    }
367
368    // Search for the closest supported sampling rate that is above (preferred)
369    // or below (acceptable) the desired sampling rate, within a permitted ratio.
370    // The sampling rates do not need to be sorted in ascending order.
371    ssize_t maxBelow = -1;
372    ssize_t minAbove = -1;
373    uint32_t candidate;
374    for (size_t i = 0; i < mSamplingRates.size(); i++) {
375        candidate = mSamplingRates[i];
376        if (candidate == samplingRate) {
377            if (updatedSamplingRate != NULL) {
378                *updatedSamplingRate = candidate;
379            }
380            return NO_ERROR;
381        }
382        // candidate < desired
383        if (candidate < samplingRate) {
384            if (maxBelow < 0 || candidate > mSamplingRates[maxBelow]) {
385                maxBelow = i;
386            }
387        // candidate > desired
388        } else {
389            if (minAbove < 0 || candidate < mSamplingRates[minAbove]) {
390                minAbove = i;
391            }
392        }
393    }
394
395    // Prefer to down-sample from a higher sampling rate, as we get the desired frequency spectrum.
396    if (minAbove >= 0) {
397        candidate = mSamplingRates[minAbove];
398        if (candidate / AUDIO_RESAMPLER_DOWN_RATIO_MAX <= samplingRate) {
399            if (updatedSamplingRate != NULL) {
400                *updatedSamplingRate = candidate;
401            }
402            return NO_ERROR;
403        }
404    }
405    // But if we have to up-sample from a lower sampling rate, that's OK.
406    if (maxBelow >= 0) {
407        candidate = mSamplingRates[maxBelow];
408        if (candidate * AUDIO_RESAMPLER_UP_RATIO_MAX >= samplingRate) {
409            if (updatedSamplingRate != NULL) {
410                *updatedSamplingRate = candidate;
411            }
412            return NO_ERROR;
413        }
414    }
415    // leave updatedSamplingRate unmodified
416    return BAD_VALUE;
417}
418
419status_t AudioPort::checkExactChannelMask(audio_channel_mask_t channelMask) const
420{
421    if (mChannelMasks.isEmpty()) {
422        return NO_ERROR;
423    }
424
425    for (size_t i = 0; i < mChannelMasks.size(); i++) {
426        if (mChannelMasks[i] == channelMask) {
427            return NO_ERROR;
428        }
429    }
430    return BAD_VALUE;
431}
432
433status_t AudioPort::checkCompatibleChannelMask(audio_channel_mask_t channelMask,
434        audio_channel_mask_t *updatedChannelMask) const
435{
436    if (mChannelMasks.isEmpty()) {
437        if (updatedChannelMask != NULL) {
438            *updatedChannelMask = channelMask;
439        }
440        return NO_ERROR;
441    }
442
443    const bool isRecordThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK;
444    for (size_t i = 0; i < mChannelMasks.size(); i ++) {
445        // FIXME Does not handle multi-channel automatic conversions yet
446        audio_channel_mask_t supported = mChannelMasks[i];
447        if (supported == channelMask) {
448            if (updatedChannelMask != NULL) {
449                *updatedChannelMask = channelMask;
450            }
451            return NO_ERROR;
452        }
453        if (isRecordThread) {
454            // This uses hard-coded knowledge that AudioFlinger can silently down-mix and up-mix.
455            // FIXME Abstract this out to a table.
456            if (((supported == AUDIO_CHANNEL_IN_FRONT_BACK || supported == AUDIO_CHANNEL_IN_STEREO)
457                    && channelMask == AUDIO_CHANNEL_IN_MONO) ||
458                (supported == AUDIO_CHANNEL_IN_MONO && (channelMask == AUDIO_CHANNEL_IN_FRONT_BACK
459                    || channelMask == AUDIO_CHANNEL_IN_STEREO))) {
460                if (updatedChannelMask != NULL) {
461                    *updatedChannelMask = supported;
462                }
463                return NO_ERROR;
464            }
465        }
466    }
467    return BAD_VALUE;
468}
469
470status_t AudioPort::checkExactFormat(audio_format_t format) const
471{
472    if (mFormats.isEmpty()) {
473        return NO_ERROR;
474    }
475
476    for (size_t i = 0; i < mFormats.size(); i ++) {
477        if (mFormats[i] == format) {
478            return NO_ERROR;
479        }
480    }
481    return BAD_VALUE;
482}
483
484status_t AudioPort::checkCompatibleFormat(audio_format_t format, audio_format_t *updatedFormat)
485        const
486{
487    if (mFormats.isEmpty()) {
488        if (updatedFormat != NULL) {
489            *updatedFormat = format;
490        }
491        return NO_ERROR;
492    }
493
494    const bool checkInexact = // when port is input and format is linear pcm
495            mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK
496            && audio_is_linear_pcm(format);
497
498    for (size_t i = 0; i < mFormats.size(); ++i) {
499        if (mFormats[i] == format ||
500                (checkInexact && audio_is_linear_pcm(mFormats[i]))) {
501            // for inexact checks we take the first linear pcm format since
502            // mFormats is sorted from best PCM format to worst PCM format.
503            if (updatedFormat != NULL) {
504                *updatedFormat = mFormats[i];
505            }
506            return NO_ERROR;
507        }
508    }
509    return BAD_VALUE;
510}
511
512uint32_t AudioPort::pickSamplingRate() const
513{
514    // special case for uninitialized dynamic profile
515    if (mSamplingRates.size() == 1 && mSamplingRates[0] == 0) {
516        return 0;
517    }
518
519    // For direct outputs, pick minimum sampling rate: this helps ensuring that the
520    // channel count / sampling rate combination chosen will be supported by the connected
521    // sink
522    if ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) &&
523            (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))) {
524        uint32_t samplingRate = UINT_MAX;
525        for (size_t i = 0; i < mSamplingRates.size(); i ++) {
526            if ((mSamplingRates[i] < samplingRate) && (mSamplingRates[i] > 0)) {
527                samplingRate = mSamplingRates[i];
528            }
529        }
530        return (samplingRate == UINT_MAX) ? 0 : samplingRate;
531    }
532
533    uint32_t samplingRate = 0;
534    uint32_t maxRate = MAX_MIXER_SAMPLING_RATE;
535
536    // For mixed output and inputs, use max mixer sampling rates. Do not
537    // limit sampling rate otherwise
538    if (mType != AUDIO_PORT_TYPE_MIX) {
539        maxRate = UINT_MAX;
540    }
541    for (size_t i = 0; i < mSamplingRates.size(); i ++) {
542        if ((mSamplingRates[i] > samplingRate) && (mSamplingRates[i] <= maxRate)) {
543            samplingRate = mSamplingRates[i];
544        }
545    }
546    return samplingRate;
547}
548
549audio_channel_mask_t AudioPort::pickChannelMask() const
550{
551    // special case for uninitialized dynamic profile
552    if (mChannelMasks.size() == 1 && mChannelMasks[0] == 0) {
553        return AUDIO_CHANNEL_NONE;
554    }
555    audio_channel_mask_t channelMask = AUDIO_CHANNEL_NONE;
556
557    // For direct outputs, pick minimum channel count: this helps ensuring that the
558    // channel count / sampling rate combination chosen will be supported by the connected
559    // sink
560    if ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) &&
561            (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))) {
562        uint32_t channelCount = UINT_MAX;
563        for (size_t i = 0; i < mChannelMasks.size(); i ++) {
564            uint32_t cnlCount;
565            if (mUseInChannelMask) {
566                cnlCount = audio_channel_count_from_in_mask(mChannelMasks[i]);
567            } else {
568                cnlCount = audio_channel_count_from_out_mask(mChannelMasks[i]);
569            }
570            if ((cnlCount < channelCount) && (cnlCount > 0)) {
571                channelMask = mChannelMasks[i];
572                channelCount = cnlCount;
573            }
574        }
575        return channelMask;
576    }
577
578    uint32_t channelCount = 0;
579    uint32_t maxCount = MAX_MIXER_CHANNEL_COUNT;
580
581    // For mixed output and inputs, use max mixer channel count. Do not
582    // limit channel count otherwise
583    if (mType != AUDIO_PORT_TYPE_MIX) {
584        maxCount = UINT_MAX;
585    }
586    for (size_t i = 0; i < mChannelMasks.size(); i ++) {
587        uint32_t cnlCount;
588        if (mUseInChannelMask) {
589            cnlCount = audio_channel_count_from_in_mask(mChannelMasks[i]);
590        } else {
591            cnlCount = audio_channel_count_from_out_mask(mChannelMasks[i]);
592        }
593        if ((cnlCount > channelCount) && (cnlCount <= maxCount)) {
594            channelMask = mChannelMasks[i];
595            channelCount = cnlCount;
596        }
597    }
598    return channelMask;
599}
600
601/* format in order of increasing preference */
602const audio_format_t AudioPort::sPcmFormatCompareTable[] = {
603        AUDIO_FORMAT_DEFAULT,
604        AUDIO_FORMAT_PCM_16_BIT,
605        AUDIO_FORMAT_PCM_8_24_BIT,
606        AUDIO_FORMAT_PCM_24_BIT_PACKED,
607        AUDIO_FORMAT_PCM_32_BIT,
608        AUDIO_FORMAT_PCM_FLOAT,
609};
610
611int AudioPort::compareFormats(audio_format_t format1,
612                                                  audio_format_t format2)
613{
614    // NOTE: AUDIO_FORMAT_INVALID is also considered not PCM and will be compared equal to any
615    // compressed format and better than any PCM format. This is by design of pickFormat()
616    if (!audio_is_linear_pcm(format1)) {
617        if (!audio_is_linear_pcm(format2)) {
618            return 0;
619        }
620        return 1;
621    }
622    if (!audio_is_linear_pcm(format2)) {
623        return -1;
624    }
625
626    int index1 = -1, index2 = -1;
627    for (size_t i = 0;
628            (i < ARRAY_SIZE(sPcmFormatCompareTable)) && ((index1 == -1) || (index2 == -1));
629            i ++) {
630        if (sPcmFormatCompareTable[i] == format1) {
631            index1 = i;
632        }
633        if (sPcmFormatCompareTable[i] == format2) {
634            index2 = i;
635        }
636    }
637    // format1 not found => index1 < 0 => format2 > format1
638    // format2 not found => index2 < 0 => format2 < format1
639    return index1 - index2;
640}
641
642audio_format_t AudioPort::pickFormat() const
643{
644    // special case for uninitialized dynamic profile
645    if (mFormats.size() == 1 && mFormats[0] == 0) {
646        return AUDIO_FORMAT_DEFAULT;
647    }
648
649    audio_format_t format = AUDIO_FORMAT_DEFAULT;
650    audio_format_t bestFormat =
651            AudioPort::sPcmFormatCompareTable[
652                ARRAY_SIZE(AudioPort::sPcmFormatCompareTable) - 1];
653    // For mixed output and inputs, use best mixer output format. Do not
654    // limit format otherwise
655    if ((mType != AUDIO_PORT_TYPE_MIX) ||
656            ((mRole == AUDIO_PORT_ROLE_SOURCE) &&
657             (((mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) != 0)))) {
658        bestFormat = AUDIO_FORMAT_INVALID;
659    }
660
661    for (size_t i = 0; i < mFormats.size(); i ++) {
662        if ((compareFormats(mFormats[i], format) > 0) &&
663                (compareFormats(mFormats[i], bestFormat) <= 0)) {
664            format = mFormats[i];
665        }
666    }
667    return format;
668}
669
670status_t AudioPort::checkGain(const struct audio_gain_config *gainConfig,
671                                                  int index) const
672{
673    if (index < 0 || (size_t)index >= mGains.size()) {
674        return BAD_VALUE;
675    }
676    return mGains[index]->checkConfig(gainConfig);
677}
678
679void AudioPort::dump(int fd, int spaces) const
680{
681    const size_t SIZE = 256;
682    char buffer[SIZE];
683    String8 result;
684
685    if (mName.length() != 0) {
686        snprintf(buffer, SIZE, "%*s- name: %s\n", spaces, "", mName.string());
687        result.append(buffer);
688    }
689
690    if (mSamplingRates.size() != 0) {
691        snprintf(buffer, SIZE, "%*s- sampling rates: ", spaces, "");
692        result.append(buffer);
693        for (size_t i = 0; i < mSamplingRates.size(); i++) {
694            if (i == 0 && mSamplingRates[i] == 0) {
695                snprintf(buffer, SIZE, "Dynamic");
696            } else {
697                snprintf(buffer, SIZE, "%d", mSamplingRates[i]);
698            }
699            result.append(buffer);
700            result.append(i == (mSamplingRates.size() - 1) ? "" : ", ");
701        }
702        result.append("\n");
703    }
704
705    if (mChannelMasks.size() != 0) {
706        snprintf(buffer, SIZE, "%*s- channel masks: ", spaces, "");
707        result.append(buffer);
708        for (size_t i = 0; i < mChannelMasks.size(); i++) {
709            ALOGV("AudioPort::dump mChannelMasks %zu %08x", i, mChannelMasks[i]);
710
711            if (i == 0 && mChannelMasks[i] == 0) {
712                snprintf(buffer, SIZE, "Dynamic");
713            } else {
714                snprintf(buffer, SIZE, "0x%04x", mChannelMasks[i]);
715            }
716            result.append(buffer);
717            result.append(i == (mChannelMasks.size() - 1) ? "" : ", ");
718        }
719        result.append("\n");
720    }
721
722    if (mFormats.size() != 0) {
723        snprintf(buffer, SIZE, "%*s- formats: ", spaces, "");
724        result.append(buffer);
725        for (size_t i = 0; i < mFormats.size(); i++) {
726            const char *formatStr = ConfigParsingUtils::enumToString(sFormatNameToEnumTable,
727                                                 ARRAY_SIZE(sFormatNameToEnumTable),
728                                                 mFormats[i]);
729            if (i == 0 && strcmp(formatStr, "") == 0) {
730                snprintf(buffer, SIZE, "Dynamic");
731            } else {
732                snprintf(buffer, SIZE, "%s", formatStr);
733            }
734            result.append(buffer);
735            result.append(i == (mFormats.size() - 1) ? "" : ", ");
736        }
737        result.append("\n");
738    }
739    write(fd, result.string(), result.size());
740    if (mGains.size() != 0) {
741        snprintf(buffer, SIZE, "%*s- gains:\n", spaces, "");
742        write(fd, buffer, strlen(buffer) + 1);
743        for (size_t i = 0; i < mGains.size(); i++) {
744            mGains[i]->dump(fd, spaces + 2, i);
745        }
746    }
747}
748
749void AudioPort::log(const char* indent) const
750{
751    ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.string(), mType, mRole);
752}
753
754// --- AudioPortConfig class implementation
755
756AudioPortConfig::AudioPortConfig()
757{
758    mSamplingRate = 0;
759    mChannelMask = AUDIO_CHANNEL_NONE;
760    mFormat = AUDIO_FORMAT_INVALID;
761    mGain.index = -1;
762}
763
764status_t AudioPortConfig::applyAudioPortConfig(
765                                                        const struct audio_port_config *config,
766                                                        struct audio_port_config *backupConfig)
767{
768    struct audio_port_config localBackupConfig;
769    status_t status = NO_ERROR;
770
771    localBackupConfig.config_mask = config->config_mask;
772    toAudioPortConfig(&localBackupConfig);
773
774    sp<AudioPort> audioport = getAudioPort();
775    if (audioport == 0) {
776        status = NO_INIT;
777        goto exit;
778    }
779    if (config->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
780        status = audioport->checkExactSamplingRate(config->sample_rate);
781        if (status != NO_ERROR) {
782            goto exit;
783        }
784        mSamplingRate = config->sample_rate;
785    }
786    if (config->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
787        status = audioport->checkExactChannelMask(config->channel_mask);
788        if (status != NO_ERROR) {
789            goto exit;
790        }
791        mChannelMask = config->channel_mask;
792    }
793    if (config->config_mask & AUDIO_PORT_CONFIG_FORMAT) {
794        status = audioport->checkExactFormat(config->format);
795        if (status != NO_ERROR) {
796            goto exit;
797        }
798        mFormat = config->format;
799    }
800    if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) {
801        status = audioport->checkGain(&config->gain, config->gain.index);
802        if (status != NO_ERROR) {
803            goto exit;
804        }
805        mGain = config->gain;
806    }
807
808exit:
809    if (status != NO_ERROR) {
810        applyAudioPortConfig(&localBackupConfig);
811    }
812    if (backupConfig != NULL) {
813        *backupConfig = localBackupConfig;
814    }
815    return status;
816}
817
818void AudioPortConfig::toAudioPortConfig(struct audio_port_config *dstConfig,
819                                        const struct audio_port_config *srcConfig) const
820{
821    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
822        dstConfig->sample_rate = mSamplingRate;
823        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE)) {
824            dstConfig->sample_rate = srcConfig->sample_rate;
825        }
826    } else {
827        dstConfig->sample_rate = 0;
828    }
829    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
830        dstConfig->channel_mask = mChannelMask;
831        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK)) {
832            dstConfig->channel_mask = srcConfig->channel_mask;
833        }
834    } else {
835        dstConfig->channel_mask = AUDIO_CHANNEL_NONE;
836    }
837    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT) {
838        dstConfig->format = mFormat;
839        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT)) {
840            dstConfig->format = srcConfig->format;
841        }
842    } else {
843        dstConfig->format = AUDIO_FORMAT_INVALID;
844    }
845    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) {
846        dstConfig->gain = mGain;
847        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_GAIN)) {
848            dstConfig->gain = srcConfig->gain;
849        }
850    } else {
851        dstConfig->gain.index = -1;
852    }
853    if (dstConfig->gain.index != -1) {
854        dstConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN;
855    } else {
856        dstConfig->config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
857    }
858}
859
860}; // namespace android
861