156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi/*
256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * Copyright (C) 2015 The Android Open Source Project
356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi *
456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * you may not use this file except in compliance with the License.
656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * You may obtain a copy of the License at
756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi *
856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi *
1056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
1156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
1256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * See the License for the specific language governing permissions and
1456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * limitations under the License.
1556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi */
1656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
1798cc191247388132b6fd8a4ecd07abd6e4c5a0edFrançois Gaffie#define LOG_TAG "APM::AudioPort"
1856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi//#define LOG_NDEBUG 0
19f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung#include <media/AudioResamplerPublic.h>
2098cc191247388132b6fd8a4ecd07abd6e4c5a0edFrançois Gaffie#include "AudioPort.h"
21ad3183e2d4cecd02f6261270a7ea1c68be0efa0fFrançois Gaffie#include "HwModule.h"
2298cc191247388132b6fd8a4ecd07abd6e4c5a0edFrançois Gaffie#include "AudioGain.h"
23ad3183e2d4cecd02f6261270a7ea1c68be0efa0fFrançois Gaffie#include "ConfigParsingUtils.h"
2456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi#include "audio_policy_conf.h"
2553615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie#include <policy.h>
2656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
2756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivinamespace android {
2856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
29ad3183e2d4cecd02f6261270a7ea1c68be0efa0fFrançois Gaffieint32_t volatile AudioPort::mNextUniqueId = 1;
30ad3183e2d4cecd02f6261270a7ea1c68be0efa0fFrançois Gaffie
3156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi// --- AudioPort class implementation
3256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
3356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel TriviAudioPort::AudioPort(const String8& name, audio_port_type_t type,
34322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent                     audio_port_role_t role) :
35322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent    mName(name), mType(type), mRole(role), mFlags(0)
3656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
3756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    mUseInChannelMask = ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) ||
3856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                    ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK));
3956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
4056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
4198cc191247388132b6fd8a4ecd07abd6e4c5a0edFrançois Gaffievoid AudioPort::attach(const sp<HwModule>& module)
4298cc191247388132b6fd8a4ecd07abd6e4c5a0edFrançois Gaffie{
4356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    mModule = module;
4456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
4556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
4698cc191247388132b6fd8a4ecd07abd6e4c5a0edFrançois Gaffieaudio_port_handle_t AudioPort::getNextUniqueId()
4798cc191247388132b6fd8a4ecd07abd6e4c5a0edFrançois Gaffie{
4898cc191247388132b6fd8a4ecd07abd6e4c5a0edFrançois Gaffie    return static_cast<audio_port_handle_t>(android_atomic_inc(&mNextUniqueId));
4998cc191247388132b6fd8a4ecd07abd6e4c5a0edFrançois Gaffie}
5098cc191247388132b6fd8a4ecd07abd6e4c5a0edFrançois Gaffie
5153615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffieaudio_module_handle_t AudioPort::getModuleHandle() const
5253615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie{
53322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent    if (mModule == 0) {
54322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent        return 0;
55322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent    }
5653615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    return mModule->mHandle;
5753615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie}
5853615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie
59322b4d25387a04c9afebe998326d005bbdf17edeEric Laurentuint32_t AudioPort::getModuleVersion() const
60322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent{
61322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent    if (mModule == 0) {
62322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent        return 0;
63322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent    }
64322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent    return mModule->mHalVersion;
65322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent}
66322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent
67322b4d25387a04c9afebe998326d005bbdf17edeEric Laurentconst char *AudioPort::getModuleName() const
68322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent{
69322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent    if (mModule == 0) {
70322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent        return "";
71322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent    }
72322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent    return mModule->mName;
73322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent}
74322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent
7556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivivoid AudioPort::toAudioPort(struct audio_port *port) const
7656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
7756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    port->role = mRole;
7856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    port->type = mType;
7956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    strlcpy(port->name, mName, AUDIO_PORT_MAX_NAME_LEN);
8056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    unsigned int i;
8156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    for (i = 0; i < mSamplingRates.size() && i < AUDIO_PORT_MAX_SAMPLING_RATES; i++) {
8256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (mSamplingRates[i] != 0) {
8356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            port->sample_rates[i] = mSamplingRates[i];
8456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
8556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
8656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    port->num_sample_rates = i;
8756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    for (i = 0; i < mChannelMasks.size() && i < AUDIO_PORT_MAX_CHANNEL_MASKS; i++) {
8856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (mChannelMasks[i] != 0) {
8956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            port->channel_masks[i] = mChannelMasks[i];
9056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
9156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
9256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    port->num_channel_masks = i;
9356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    for (i = 0; i < mFormats.size() && i < AUDIO_PORT_MAX_FORMATS; i++) {
9456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (mFormats[i] != 0) {
9556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            port->formats[i] = mFormats[i];
9656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
9756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
9856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    port->num_formats = i;
9956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
10056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size());
10156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
10256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    for (i = 0; i < mGains.size() && i < AUDIO_PORT_MAX_GAINS; i++) {
10356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        port->gains[i] = mGains[i]->mGain;
10456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
10556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    port->num_gains = i;
10656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
10756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
10856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivivoid AudioPort::importAudioPort(const sp<AudioPort> port) {
10956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    for (size_t k = 0 ; k < port->mSamplingRates.size() ; k++) {
11056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        const uint32_t rate = port->mSamplingRates.itemAt(k);
11156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (rate != 0) { // skip "dynamic" rates
11256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            bool hasRate = false;
11356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            for (size_t l = 0 ; l < mSamplingRates.size() ; l++) {
11456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                if (rate == mSamplingRates.itemAt(l)) {
11556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                    hasRate = true;
11656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                    break;
11756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                }
11856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
11956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            if (!hasRate) { // never import a sampling rate twice
12056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                mSamplingRates.add(rate);
12156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
12256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
12356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
12456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    for (size_t k = 0 ; k < port->mChannelMasks.size() ; k++) {
12556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        const audio_channel_mask_t mask = port->mChannelMasks.itemAt(k);
12656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (mask != 0) { // skip "dynamic" masks
12756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            bool hasMask = false;
12856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            for (size_t l = 0 ; l < mChannelMasks.size() ; l++) {
12956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                if (mask == mChannelMasks.itemAt(l)) {
13056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                    hasMask = true;
13156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                    break;
13256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                }
13356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
13456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            if (!hasMask) { // never import a channel mask twice
13556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                mChannelMasks.add(mask);
13656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
13756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
13856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
13956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    for (size_t k = 0 ; k < port->mFormats.size() ; k++) {
14056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        const audio_format_t format = port->mFormats.itemAt(k);
14156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (format != 0) { // skip "dynamic" formats
14256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            bool hasFormat = false;
14356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            for (size_t l = 0 ; l < mFormats.size() ; l++) {
14456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                if (format == mFormats.itemAt(l)) {
14556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                    hasFormat = true;
14656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                    break;
14756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                }
14856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
149138f77425a0956d867f078881f91628518ae8258Andy Hung            if (!hasFormat) { // never import a format twice
15056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                mFormats.add(format);
15156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
15256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
15356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
15456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
15556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
15656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivivoid AudioPort::clearCapabilities() {
15756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    mChannelMasks.clear();
15856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    mFormats.clear();
15956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    mSamplingRates.clear();
16056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
16156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
16256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivivoid AudioPort::loadSamplingRates(char *name)
16356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
16456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    char *str = strtok(name, "|");
16556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
16656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // by convention, "0' in the first entry in mSamplingRates indicates the supported sampling
16756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // rates should be read from the output stream after it is opened for the first time
16856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) {
16956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        mSamplingRates.add(0);
17056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return;
17156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
17256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
17356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    while (str != NULL) {
17456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        uint32_t rate = atoi(str);
17556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (rate != 0) {
17656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            ALOGV("loadSamplingRates() adding rate %d", rate);
17756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            mSamplingRates.add(rate);
17856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
17956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        str = strtok(NULL, "|");
18056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
18156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
18256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
18356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivivoid AudioPort::loadFormats(char *name)
18456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
18556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    char *str = strtok(name, "|");
18656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
18756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // by convention, "0' in the first entry in mFormats indicates the supported formats
18856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // should be read from the output stream after it is opened for the first time
18956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) {
19056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        mFormats.add(AUDIO_FORMAT_DEFAULT);
19156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return;
19256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
19356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
19456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    while (str != NULL) {
19556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        audio_format_t format = (audio_format_t)ConfigParsingUtils::stringToEnum(sFormatNameToEnumTable,
19656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                                                             ARRAY_SIZE(sFormatNameToEnumTable),
19756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                                                             str);
19856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (format != AUDIO_FORMAT_DEFAULT) {
19956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            mFormats.add(format);
20056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
20156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        str = strtok(NULL, "|");
20256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
203138f77425a0956d867f078881f91628518ae8258Andy Hung    // we sort from worst to best, so that AUDIO_FORMAT_DEFAULT is always the first entry.
204138f77425a0956d867f078881f91628518ae8258Andy Hung    // TODO: compareFormats could be a lambda to convert between pointer-to-format to format:
205138f77425a0956d867f078881f91628518ae8258Andy Hung    // [](const audio_format_t *format1, const audio_format_t *format2) {
206138f77425a0956d867f078881f91628518ae8258Andy Hung    //     return compareFormats(*format1, *format2);
207138f77425a0956d867f078881f91628518ae8258Andy Hung    // }
208138f77425a0956d867f078881f91628518ae8258Andy Hung    mFormats.sort(compareFormats);
20956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
21056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
21156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivivoid AudioPort::loadInChannels(char *name)
21256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
21356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    const char *str = strtok(name, "|");
21456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
21556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    ALOGV("loadInChannels() %s", name);
21656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
21756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) {
21856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        mChannelMasks.add(0);
21956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return;
22056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
22156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
22256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    while (str != NULL) {
22356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        audio_channel_mask_t channelMask =
22456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sInChannelsNameToEnumTable,
22556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                                                   ARRAY_SIZE(sInChannelsNameToEnumTable),
22656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                                                   str);
227f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung        if (channelMask == 0) { // if not found, check the channel index table
228f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            channelMask = (audio_channel_mask_t)
229f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                      ConfigParsingUtils::stringToEnum(sIndexChannelsNameToEnumTable,
230f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                              ARRAY_SIZE(sIndexChannelsNameToEnumTable),
231f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                              str);
232f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung        }
23356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (channelMask != 0) {
234f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            ALOGV("loadInChannels() adding channelMask %#x", channelMask);
23556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            mChannelMasks.add(channelMask);
23656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
23756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        str = strtok(NULL, "|");
23856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
23956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
24056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
24156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivivoid AudioPort::loadOutChannels(char *name)
24256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
24356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    const char *str = strtok(name, "|");
24456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
24556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    ALOGV("loadOutChannels() %s", name);
24656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
24756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // by convention, "0' in the first entry in mChannelMasks indicates the supported channel
24856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // masks should be read from the output stream after it is opened for the first time
24956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) {
25056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        mChannelMasks.add(0);
25156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return;
25256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
25356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
25456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    while (str != NULL) {
25556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        audio_channel_mask_t channelMask =
25656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sOutChannelsNameToEnumTable,
25756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                                                   ARRAY_SIZE(sOutChannelsNameToEnumTable),
25856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                                                   str);
25918aa27016a94d0fee243637a80fd0741f89e08f2Andy Hung        if (channelMask == 0) { // if not found, check the channel index table
26018aa27016a94d0fee243637a80fd0741f89e08f2Andy Hung            channelMask = (audio_channel_mask_t)
26118aa27016a94d0fee243637a80fd0741f89e08f2Andy Hung                      ConfigParsingUtils::stringToEnum(sIndexChannelsNameToEnumTable,
26218aa27016a94d0fee243637a80fd0741f89e08f2Andy Hung                              ARRAY_SIZE(sIndexChannelsNameToEnumTable),
26318aa27016a94d0fee243637a80fd0741f89e08f2Andy Hung                              str);
26418aa27016a94d0fee243637a80fd0741f89e08f2Andy Hung        }
26556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (channelMask != 0) {
26656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            mChannelMasks.add(channelMask);
26756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
26856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        str = strtok(NULL, "|");
26956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
27056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    return;
27156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
27256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
27356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Triviaudio_gain_mode_t AudioPort::loadGainMode(char *name)
27456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
27556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    const char *str = strtok(name, "|");
27656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
27756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    ALOGV("loadGainMode() %s", name);
27856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    audio_gain_mode_t mode = 0;
27956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    while (str != NULL) {
28056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        mode |= (audio_gain_mode_t)ConfigParsingUtils::stringToEnum(sGainModeNameToEnumTable,
28156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                                                ARRAY_SIZE(sGainModeNameToEnumTable),
28256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                                                str);
28356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        str = strtok(NULL, "|");
28456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
28556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    return mode;
28656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
28756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
28856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivivoid AudioPort::loadGain(cnode *root, int index)
28956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
29056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    cnode *node = root->first_child;
29156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
29256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    sp<AudioGain> gain = new AudioGain(index, mUseInChannelMask);
29356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
29456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    while (node) {
29556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (strcmp(node->name, GAIN_MODE) == 0) {
29656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            gain->mGain.mode = loadGainMode((char *)node->value);
29756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        } else if (strcmp(node->name, GAIN_CHANNELS) == 0) {
29856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            if (mUseInChannelMask) {
29956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                gain->mGain.channel_mask =
30056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                        (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sInChannelsNameToEnumTable,
30156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                                                           ARRAY_SIZE(sInChannelsNameToEnumTable),
30256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                                                           (char *)node->value);
30356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            } else {
30456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                gain->mGain.channel_mask =
30556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                        (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sOutChannelsNameToEnumTable,
30656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                                                           ARRAY_SIZE(sOutChannelsNameToEnumTable),
30756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                                                           (char *)node->value);
30856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
30956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        } else if (strcmp(node->name, GAIN_MIN_VALUE) == 0) {
31056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            gain->mGain.min_value = atoi((char *)node->value);
31156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        } else if (strcmp(node->name, GAIN_MAX_VALUE) == 0) {
31256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            gain->mGain.max_value = atoi((char *)node->value);
31356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        } else if (strcmp(node->name, GAIN_DEFAULT_VALUE) == 0) {
31456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            gain->mGain.default_value = atoi((char *)node->value);
31556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        } else if (strcmp(node->name, GAIN_STEP_VALUE) == 0) {
31656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            gain->mGain.step_value = atoi((char *)node->value);
31756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        } else if (strcmp(node->name, GAIN_MIN_RAMP_MS) == 0) {
31856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            gain->mGain.min_ramp_ms = atoi((char *)node->value);
31956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        } else if (strcmp(node->name, GAIN_MAX_RAMP_MS) == 0) {
32056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            gain->mGain.max_ramp_ms = atoi((char *)node->value);
32156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
32256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        node = node->next;
32356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
32456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
32556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    ALOGV("loadGain() adding new gain mode %08x channel mask %08x min mB %d max mB %d",
32656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi          gain->mGain.mode, gain->mGain.channel_mask, gain->mGain.min_value, gain->mGain.max_value);
32756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
32856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (gain->mGain.mode == 0) {
32956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return;
33056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
33156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    mGains.add(gain);
33256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
33356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
33456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivivoid AudioPort::loadGains(cnode *root)
33556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
33656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    cnode *node = root->first_child;
33756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    int index = 0;
33856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    while (node) {
33956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        ALOGV("loadGains() loading gain %s", node->name);
34056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        loadGain(node, index++);
34156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        node = node->next;
34256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
34356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
34456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
34556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivistatus_t AudioPort::checkExactSamplingRate(uint32_t samplingRate) const
34656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
34756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (mSamplingRates.isEmpty()) {
34856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return NO_ERROR;
34956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
35056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
35156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    for (size_t i = 0; i < mSamplingRates.size(); i ++) {
35256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (mSamplingRates[i] == samplingRate) {
35356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            return NO_ERROR;
35456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
35556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
35656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    return BAD_VALUE;
35756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
35856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
35956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivistatus_t AudioPort::checkCompatibleSamplingRate(uint32_t samplingRate,
36056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        uint32_t *updatedSamplingRate) const
36156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
36256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (mSamplingRates.isEmpty()) {
363f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung        if (updatedSamplingRate != NULL) {
364f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung            *updatedSamplingRate = samplingRate;
365f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung        }
36656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return NO_ERROR;
36756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
36856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
36956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // Search for the closest supported sampling rate that is above (preferred)
37056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // or below (acceptable) the desired sampling rate, within a permitted ratio.
37156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // The sampling rates do not need to be sorted in ascending order.
37256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    ssize_t maxBelow = -1;
37356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    ssize_t minAbove = -1;
37456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    uint32_t candidate;
37556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    for (size_t i = 0; i < mSamplingRates.size(); i++) {
37656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        candidate = mSamplingRates[i];
37756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (candidate == samplingRate) {
37856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            if (updatedSamplingRate != NULL) {
37956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                *updatedSamplingRate = candidate;
38056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
38156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            return NO_ERROR;
38256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
38356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        // candidate < desired
38456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (candidate < samplingRate) {
38556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            if (maxBelow < 0 || candidate > mSamplingRates[maxBelow]) {
38656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                maxBelow = i;
38756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
38856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        // candidate > desired
38956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        } else {
39056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            if (minAbove < 0 || candidate < mSamplingRates[minAbove]) {
39156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                minAbove = i;
39256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
39356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
39456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
395f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung
39656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // Prefer to down-sample from a higher sampling rate, as we get the desired frequency spectrum.
39756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (minAbove >= 0) {
39856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        candidate = mSamplingRates[minAbove];
399f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung        if (candidate / AUDIO_RESAMPLER_DOWN_RATIO_MAX <= samplingRate) {
40056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            if (updatedSamplingRate != NULL) {
40156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                *updatedSamplingRate = candidate;
40256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
40356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            return NO_ERROR;
40456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
40556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
40656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // But if we have to up-sample from a lower sampling rate, that's OK.
40756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (maxBelow >= 0) {
40856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        candidate = mSamplingRates[maxBelow];
409f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung        if (candidate * AUDIO_RESAMPLER_UP_RATIO_MAX >= samplingRate) {
41056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            if (updatedSamplingRate != NULL) {
41156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                *updatedSamplingRate = candidate;
41256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
41356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            return NO_ERROR;
41456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
41556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
41656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // leave updatedSamplingRate unmodified
41756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    return BAD_VALUE;
41856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
41956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
42056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivistatus_t AudioPort::checkExactChannelMask(audio_channel_mask_t channelMask) const
42156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
42256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (mChannelMasks.isEmpty()) {
42356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return NO_ERROR;
42456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
42556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
42656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    for (size_t i = 0; i < mChannelMasks.size(); i++) {
42756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (mChannelMasks[i] == channelMask) {
42856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            return NO_ERROR;
42956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
43056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
43156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    return BAD_VALUE;
43256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
43356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
434f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hungstatus_t AudioPort::checkCompatibleChannelMask(audio_channel_mask_t channelMask,
435f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung        audio_channel_mask_t *updatedChannelMask) const
43656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
43756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (mChannelMasks.isEmpty()) {
438f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung        if (updatedChannelMask != NULL) {
439f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung            *updatedChannelMask = channelMask;
440f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung        }
44156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return NO_ERROR;
44256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
44356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
44456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    const bool isRecordThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK;
445f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung    const bool isIndex = audio_channel_mask_get_representation(channelMask)
446f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            == AUDIO_CHANNEL_REPRESENTATION_INDEX;
447f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung    int bestMatch = 0;
44856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    for (size_t i = 0; i < mChannelMasks.size(); i ++) {
44956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        audio_channel_mask_t supported = mChannelMasks[i];
45056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (supported == channelMask) {
451f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            // Exact matches always taken.
452f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung            if (updatedChannelMask != NULL) {
453f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung                *updatedChannelMask = channelMask;
454f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung            }
45556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            return NO_ERROR;
45656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
457f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung
458f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung        // AUDIO_CHANNEL_NONE (value: 0) is used for dynamic channel support
459f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung        if (isRecordThread && supported != AUDIO_CHANNEL_NONE) {
460f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            // Approximate (best) match:
461f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            // The match score measures how well the supported channel mask matches the
462f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            // desired mask, where increasing-is-better.
463f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            //
464f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            // TODO: Some tweaks may be needed.
465f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            // Should be a static function of the data processing library.
466f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            //
467f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            // In priority:
468f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            // match score = 1000 if legacy channel conversion equivalent (always prefer this)
469f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            // OR
470f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            // match score += 100 if the channel mask representations match
471f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            // match score += number of channels matched.
472f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            //
473f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            // If there are no matched channels, the mask may still be accepted
474f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            // but the playback or record will be silent.
475f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            const bool isSupportedIndex = (audio_channel_mask_get_representation(supported)
476f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                    == AUDIO_CHANNEL_REPRESENTATION_INDEX);
477f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            int match;
478f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            if (isIndex && isSupportedIndex) {
479f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                // index equivalence
480f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                match = 100 + __builtin_popcount(
481f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                        audio_channel_mask_get_bits(channelMask)
482f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                            & audio_channel_mask_get_bits(supported));
483f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            } else if (isIndex && !isSupportedIndex) {
484f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                const uint32_t equivalentBits =
485f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                        (1 << audio_channel_count_from_in_mask(supported)) - 1 ;
486f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                match = __builtin_popcount(
487f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                        audio_channel_mask_get_bits(channelMask) & equivalentBits);
488f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            } else if (!isIndex && isSupportedIndex) {
489f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                const uint32_t equivalentBits =
490f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                        (1 << audio_channel_count_from_in_mask(channelMask)) - 1;
491f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                match = __builtin_popcount(
492f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                        equivalentBits & audio_channel_mask_get_bits(supported));
493f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            } else {
494f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                // positional equivalence
495f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                match = 100 + __builtin_popcount(
496f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                        audio_channel_mask_get_bits(channelMask)
497f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                            & audio_channel_mask_get_bits(supported));
498f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                switch (supported) {
499f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                case AUDIO_CHANNEL_IN_FRONT_BACK:
500f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                case AUDIO_CHANNEL_IN_STEREO:
501f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                    if (channelMask == AUDIO_CHANNEL_IN_MONO) {
502f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                        match = 1000;
503f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                    }
504f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                    break;
505f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                case AUDIO_CHANNEL_IN_MONO:
506f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                    if (channelMask == AUDIO_CHANNEL_IN_FRONT_BACK
507f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                            || channelMask == AUDIO_CHANNEL_IN_STEREO) {
508f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                        match = 1000;
509f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                    }
510f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                    break;
511f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                default:
512f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                    break;
513f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                }
514f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            }
515f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            if (match > bestMatch) {
516f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                bestMatch = match;
517f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung                if (updatedChannelMask != NULL) {
518f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung                    *updatedChannelMask = supported;
519f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                } else {
520f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                    return NO_ERROR; // any match will do in this case.
521f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung                }
52256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
52356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
52456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
525f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung    return bestMatch > 0 ? NO_ERROR : BAD_VALUE;
52656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
52756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
528f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hungstatus_t AudioPort::checkExactFormat(audio_format_t format) const
52956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
53056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (mFormats.isEmpty()) {
53156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return NO_ERROR;
53256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
53356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
53456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    for (size_t i = 0; i < mFormats.size(); i ++) {
53556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (mFormats[i] == format) {
53656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            return NO_ERROR;
53756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
53856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
53956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    return BAD_VALUE;
54056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
54156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
542f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hungstatus_t AudioPort::checkCompatibleFormat(audio_format_t format, audio_format_t *updatedFormat)
543f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung        const
544f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung{
545f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung    if (mFormats.isEmpty()) {
546f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung        if (updatedFormat != NULL) {
547f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung            *updatedFormat = format;
548f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung        }
549f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung        return NO_ERROR;
550f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung    }
551f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung
552f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung    const bool checkInexact = // when port is input and format is linear pcm
553f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung            mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK
554f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung            && audio_is_linear_pcm(format);
555f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung
556138f77425a0956d867f078881f91628518ae8258Andy Hung    // iterate from best format to worst format (reverse order)
557138f77425a0956d867f078881f91628518ae8258Andy Hung    for (ssize_t i = mFormats.size() - 1; i >= 0 ; --i) {
558f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung        if (mFormats[i] == format ||
559138f77425a0956d867f078881f91628518ae8258Andy Hung                (checkInexact
560138f77425a0956d867f078881f91628518ae8258Andy Hung                        && mFormats[i] != AUDIO_FORMAT_DEFAULT
561138f77425a0956d867f078881f91628518ae8258Andy Hung                        && audio_is_linear_pcm(mFormats[i]))) {
562138f77425a0956d867f078881f91628518ae8258Andy Hung            // for inexact checks we take the first linear pcm format due to sorting.
563f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung            if (updatedFormat != NULL) {
564f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung                *updatedFormat = mFormats[i];
565f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung            }
566f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung            return NO_ERROR;
567f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung        }
568f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung    }
569f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung    return BAD_VALUE;
570f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung}
57156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
57256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Triviuint32_t AudioPort::pickSamplingRate() const
57356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
57456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // special case for uninitialized dynamic profile
57556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (mSamplingRates.size() == 1 && mSamplingRates[0] == 0) {
57656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return 0;
57756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
57856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
57956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // For direct outputs, pick minimum sampling rate: this helps ensuring that the
58056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // channel count / sampling rate combination chosen will be supported by the connected
58156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // sink
58256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) &&
58356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))) {
58456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        uint32_t samplingRate = UINT_MAX;
58556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        for (size_t i = 0; i < mSamplingRates.size(); i ++) {
58656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            if ((mSamplingRates[i] < samplingRate) && (mSamplingRates[i] > 0)) {
58756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                samplingRate = mSamplingRates[i];
58856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
58956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
59056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return (samplingRate == UINT_MAX) ? 0 : samplingRate;
59156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
59256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
59356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    uint32_t samplingRate = 0;
59456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    uint32_t maxRate = MAX_MIXER_SAMPLING_RATE;
59556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
59656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // For mixed output and inputs, use max mixer sampling rates. Do not
59756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // limit sampling rate otherwise
598db4c031f518ae5806af73756273ff32cd8d0e4f8Andy Hung    // For inputs, also see checkCompatibleSamplingRate().
59956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (mType != AUDIO_PORT_TYPE_MIX) {
60056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        maxRate = UINT_MAX;
60156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
602db4c031f518ae5806af73756273ff32cd8d0e4f8Andy Hung    // TODO: should mSamplingRates[] be ordered in terms of our preference
603db4c031f518ae5806af73756273ff32cd8d0e4f8Andy Hung    // and we return the first (and hence most preferred) match?  This is of concern if
604db4c031f518ae5806af73756273ff32cd8d0e4f8Andy Hung    // we want to choose 96kHz over 192kHz for USB driver stability or resource constraints.
60556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    for (size_t i = 0; i < mSamplingRates.size(); i ++) {
60656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if ((mSamplingRates[i] > samplingRate) && (mSamplingRates[i] <= maxRate)) {
60756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            samplingRate = mSamplingRates[i];
60856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
60956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
61056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    return samplingRate;
61156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
61256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
61356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Triviaudio_channel_mask_t AudioPort::pickChannelMask() const
61456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
61556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // special case for uninitialized dynamic profile
61656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (mChannelMasks.size() == 1 && mChannelMasks[0] == 0) {
61756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return AUDIO_CHANNEL_NONE;
61856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
61956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    audio_channel_mask_t channelMask = AUDIO_CHANNEL_NONE;
62056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
62156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // For direct outputs, pick minimum channel count: this helps ensuring that the
62256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // channel count / sampling rate combination chosen will be supported by the connected
62356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // sink
62456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) &&
62556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))) {
62656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        uint32_t channelCount = UINT_MAX;
62756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        for (size_t i = 0; i < mChannelMasks.size(); i ++) {
62856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            uint32_t cnlCount;
62956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            if (mUseInChannelMask) {
63056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                cnlCount = audio_channel_count_from_in_mask(mChannelMasks[i]);
63156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            } else {
63256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                cnlCount = audio_channel_count_from_out_mask(mChannelMasks[i]);
63356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
63456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            if ((cnlCount < channelCount) && (cnlCount > 0)) {
63556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                channelMask = mChannelMasks[i];
63656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                channelCount = cnlCount;
63756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
63856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
63956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return channelMask;
64056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
64156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
64256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    uint32_t channelCount = 0;
64356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    uint32_t maxCount = MAX_MIXER_CHANNEL_COUNT;
64456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
64556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // For mixed output and inputs, use max mixer channel count. Do not
64656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // limit channel count otherwise
64756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (mType != AUDIO_PORT_TYPE_MIX) {
64856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        maxCount = UINT_MAX;
64956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
65056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    for (size_t i = 0; i < mChannelMasks.size(); i ++) {
65156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        uint32_t cnlCount;
65256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (mUseInChannelMask) {
65356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            cnlCount = audio_channel_count_from_in_mask(mChannelMasks[i]);
65456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        } else {
65556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            cnlCount = audio_channel_count_from_out_mask(mChannelMasks[i]);
65656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
65756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if ((cnlCount > channelCount) && (cnlCount <= maxCount)) {
65856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            channelMask = mChannelMasks[i];
65956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            channelCount = cnlCount;
66056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
66156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
66256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    return channelMask;
66356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
66456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
66556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi/* format in order of increasing preference */
66656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Triviconst audio_format_t AudioPort::sPcmFormatCompareTable[] = {
66756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        AUDIO_FORMAT_DEFAULT,
66856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        AUDIO_FORMAT_PCM_16_BIT,
66956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        AUDIO_FORMAT_PCM_8_24_BIT,
67056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        AUDIO_FORMAT_PCM_24_BIT_PACKED,
67156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        AUDIO_FORMAT_PCM_32_BIT,
67256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        AUDIO_FORMAT_PCM_FLOAT,
67356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi};
67456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
67556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Triviint AudioPort::compareFormats(audio_format_t format1,
67656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                                                  audio_format_t format2)
67756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
67856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // NOTE: AUDIO_FORMAT_INVALID is also considered not PCM and will be compared equal to any
67956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // compressed format and better than any PCM format. This is by design of pickFormat()
68056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (!audio_is_linear_pcm(format1)) {
68156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (!audio_is_linear_pcm(format2)) {
68256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            return 0;
68356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
68456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return 1;
68556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
68656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (!audio_is_linear_pcm(format2)) {
68756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return -1;
68856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
68956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
69056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    int index1 = -1, index2 = -1;
69156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    for (size_t i = 0;
69256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            (i < ARRAY_SIZE(sPcmFormatCompareTable)) && ((index1 == -1) || (index2 == -1));
69356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            i ++) {
69456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (sPcmFormatCompareTable[i] == format1) {
69556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            index1 = i;
69656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
69756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (sPcmFormatCompareTable[i] == format2) {
69856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            index2 = i;
69956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
70056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
70156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // format1 not found => index1 < 0 => format2 > format1
70256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // format2 not found => index2 < 0 => format2 < format1
70356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    return index1 - index2;
70456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
70556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
70656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Triviaudio_format_t AudioPort::pickFormat() const
70756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
70856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // special case for uninitialized dynamic profile
70956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (mFormats.size() == 1 && mFormats[0] == 0) {
71056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return AUDIO_FORMAT_DEFAULT;
71156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
71256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
71356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    audio_format_t format = AUDIO_FORMAT_DEFAULT;
71456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    audio_format_t bestFormat =
71556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            AudioPort::sPcmFormatCompareTable[
71656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                ARRAY_SIZE(AudioPort::sPcmFormatCompareTable) - 1];
71756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // For mixed output and inputs, use best mixer output format. Do not
71856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // limit format otherwise
71956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if ((mType != AUDIO_PORT_TYPE_MIX) ||
72056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            ((mRole == AUDIO_PORT_ROLE_SOURCE) &&
72156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi             (((mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) != 0)))) {
72256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        bestFormat = AUDIO_FORMAT_INVALID;
72356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
72456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
72556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    for (size_t i = 0; i < mFormats.size(); i ++) {
72656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if ((compareFormats(mFormats[i], format) > 0) &&
72756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                (compareFormats(mFormats[i], bestFormat) <= 0)) {
72856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            format = mFormats[i];
72956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
73056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
73156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    return format;
73256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
73356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
73456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivistatus_t AudioPort::checkGain(const struct audio_gain_config *gainConfig,
73556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                                                  int index) const
73656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
73756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (index < 0 || (size_t)index >= mGains.size()) {
73856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return BAD_VALUE;
73956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
74056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    return mGains[index]->checkConfig(gainConfig);
74156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
74256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
74356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivivoid AudioPort::dump(int fd, int spaces) const
74456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
74556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    const size_t SIZE = 256;
74656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    char buffer[SIZE];
74756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    String8 result;
74856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
749322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent    if (mName.length() != 0) {
75056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        snprintf(buffer, SIZE, "%*s- name: %s\n", spaces, "", mName.string());
75156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        result.append(buffer);
75256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
75356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
75456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (mSamplingRates.size() != 0) {
75556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        snprintf(buffer, SIZE, "%*s- sampling rates: ", spaces, "");
75656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        result.append(buffer);
75756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        for (size_t i = 0; i < mSamplingRates.size(); i++) {
75856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            if (i == 0 && mSamplingRates[i] == 0) {
75956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                snprintf(buffer, SIZE, "Dynamic");
76056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            } else {
76156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                snprintf(buffer, SIZE, "%d", mSamplingRates[i]);
76256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
76356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            result.append(buffer);
76456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            result.append(i == (mSamplingRates.size() - 1) ? "" : ", ");
76556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
76656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        result.append("\n");
76756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
76856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
76956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (mChannelMasks.size() != 0) {
77056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        snprintf(buffer, SIZE, "%*s- channel masks: ", spaces, "");
77156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        result.append(buffer);
77256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        for (size_t i = 0; i < mChannelMasks.size(); i++) {
77356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            ALOGV("AudioPort::dump mChannelMasks %zu %08x", i, mChannelMasks[i]);
77456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
77556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            if (i == 0 && mChannelMasks[i] == 0) {
77656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                snprintf(buffer, SIZE, "Dynamic");
77756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            } else {
77856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                snprintf(buffer, SIZE, "0x%04x", mChannelMasks[i]);
77956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
78056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            result.append(buffer);
78156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            result.append(i == (mChannelMasks.size() - 1) ? "" : ", ");
78256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
78356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        result.append("\n");
78456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
78556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
78656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (mFormats.size() != 0) {
78756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        snprintf(buffer, SIZE, "%*s- formats: ", spaces, "");
78856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        result.append(buffer);
78956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        for (size_t i = 0; i < mFormats.size(); i++) {
79056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            const char *formatStr = ConfigParsingUtils::enumToString(sFormatNameToEnumTable,
79156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                                                 ARRAY_SIZE(sFormatNameToEnumTable),
79256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                                                 mFormats[i]);
793138f77425a0956d867f078881f91628518ae8258Andy Hung            const bool isEmptyStr = formatStr[0] == 0;
794138f77425a0956d867f078881f91628518ae8258Andy Hung            if (i == 0 && isEmptyStr) {
79556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                snprintf(buffer, SIZE, "Dynamic");
79656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            } else {
797138f77425a0956d867f078881f91628518ae8258Andy Hung                if (isEmptyStr) {
798138f77425a0956d867f078881f91628518ae8258Andy Hung                    snprintf(buffer, SIZE, "%#x", mFormats[i]);
799138f77425a0956d867f078881f91628518ae8258Andy Hung                } else {
800138f77425a0956d867f078881f91628518ae8258Andy Hung                    snprintf(buffer, SIZE, "%s", formatStr);
801138f77425a0956d867f078881f91628518ae8258Andy Hung                }
80256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
80356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            result.append(buffer);
80456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            result.append(i == (mFormats.size() - 1) ? "" : ", ");
80556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
80656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        result.append("\n");
80756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
80856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    write(fd, result.string(), result.size());
80956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (mGains.size() != 0) {
81056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        snprintf(buffer, SIZE, "%*s- gains:\n", spaces, "");
81156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        write(fd, buffer, strlen(buffer) + 1);
81256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        for (size_t i = 0; i < mGains.size(); i++) {
81356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            mGains[i]->dump(fd, spaces + 2, i);
81456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
81556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
81656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
81756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
818aa9811945f575614b3482d09e4d969792701cebbPaul McLeanvoid AudioPort::log(const char* indent) const
819aa9811945f575614b3482d09e4d969792701cebbPaul McLean{
820aa9811945f575614b3482d09e4d969792701cebbPaul McLean    ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.string(), mType, mRole);
821aa9811945f575614b3482d09e4d969792701cebbPaul McLean}
82256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
82356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi// --- AudioPortConfig class implementation
82456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
82556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel TriviAudioPortConfig::AudioPortConfig()
82656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
82756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    mSamplingRate = 0;
82856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    mChannelMask = AUDIO_CHANNEL_NONE;
82956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    mFormat = AUDIO_FORMAT_INVALID;
83056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    mGain.index = -1;
83156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
83256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
83356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivistatus_t AudioPortConfig::applyAudioPortConfig(
83456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                                                        const struct audio_port_config *config,
83556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                                                        struct audio_port_config *backupConfig)
83656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
83756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    struct audio_port_config localBackupConfig;
83856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    status_t status = NO_ERROR;
83956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
84056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    localBackupConfig.config_mask = config->config_mask;
84156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    toAudioPortConfig(&localBackupConfig);
84256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
84356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    sp<AudioPort> audioport = getAudioPort();
84456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (audioport == 0) {
84556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        status = NO_INIT;
84656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        goto exit;
84756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
84856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (config->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
84956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        status = audioport->checkExactSamplingRate(config->sample_rate);
85056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (status != NO_ERROR) {
85156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            goto exit;
85256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
85356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        mSamplingRate = config->sample_rate;
85456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
85556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (config->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
85656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        status = audioport->checkExactChannelMask(config->channel_mask);
85756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (status != NO_ERROR) {
85856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            goto exit;
85956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
86056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        mChannelMask = config->channel_mask;
86156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
86256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (config->config_mask & AUDIO_PORT_CONFIG_FORMAT) {
863f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung        status = audioport->checkExactFormat(config->format);
86456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (status != NO_ERROR) {
86556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            goto exit;
86656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
86756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        mFormat = config->format;
86856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
86956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) {
87056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        status = audioport->checkGain(&config->gain, config->gain.index);
87156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (status != NO_ERROR) {
87256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            goto exit;
87356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
87456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        mGain = config->gain;
87556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
87656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
87756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Triviexit:
87856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (status != NO_ERROR) {
87956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        applyAudioPortConfig(&localBackupConfig);
88056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
88156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (backupConfig != NULL) {
88256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        *backupConfig = localBackupConfig;
88356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
88456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    return status;
88556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
88656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
88756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivivoid AudioPortConfig::toAudioPortConfig(struct audio_port_config *dstConfig,
88856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                                        const struct audio_port_config *srcConfig) const
88956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
89056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
89156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        dstConfig->sample_rate = mSamplingRate;
89256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE)) {
89356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            dstConfig->sample_rate = srcConfig->sample_rate;
89456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
89556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    } else {
89656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        dstConfig->sample_rate = 0;
89756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
89856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
89956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        dstConfig->channel_mask = mChannelMask;
90056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK)) {
90156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            dstConfig->channel_mask = srcConfig->channel_mask;
90256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
90356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    } else {
90456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        dstConfig->channel_mask = AUDIO_CHANNEL_NONE;
90556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
90656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT) {
90756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        dstConfig->format = mFormat;
90856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT)) {
90956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            dstConfig->format = srcConfig->format;
91056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
91156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    } else {
91256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        dstConfig->format = AUDIO_FORMAT_INVALID;
91356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
91456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) {
91556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        dstConfig->gain = mGain;
91656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_GAIN)) {
91756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            dstConfig->gain = srcConfig->gain;
91856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
91956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    } else {
92056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        dstConfig->gain.index = -1;
92156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
92256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (dstConfig->gain.index != -1) {
92356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        dstConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN;
92456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    } else {
92556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        dstConfig->config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
92656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
92756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
92856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
92956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}; // namespace android
930