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