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