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
19a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie#include "TypeConverter.h"
2098cc191247388132b6fd8a4ecd07abd6e4c5a0edFrançois Gaffie#include "AudioPort.h"
21ad3183e2d4cecd02f6261270a7ea1c68be0efa0fFrançois Gaffie#include "HwModule.h"
2298cc191247388132b6fd8a4ecd07abd6e4c5a0edFrançois Gaffie#include "AudioGain.h"
2353615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie#include <policy.h>
2456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
25a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie#ifndef ARRAY_SIZE
26a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
27a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie#endif
28a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie
2956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivinamespace android {
3056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
3156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi// --- AudioPort class implementation
3298cc191247388132b6fd8a4ecd07abd6e4c5a0edFrançois Gaffievoid AudioPort::attach(const sp<HwModule>& module)
3398cc191247388132b6fd8a4ecd07abd6e4c5a0edFrançois Gaffie{
3456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    mModule = module;
3556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
3656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
37eeecb980ff4c202d0a3c4b0bfe040dce2f73336dGlenn Kasten// Note that is a different namespace than AudioFlinger unique IDs
3898cc191247388132b6fd8a4ecd07abd6e4c5a0edFrançois Gaffieaudio_port_handle_t AudioPort::getNextUniqueId()
3998cc191247388132b6fd8a4ecd07abd6e4c5a0edFrançois Gaffie{
402773dd7219e6cdc56471501c90808a1bafc31d39Mikhail Naganov    return getNextHandle();
4198cc191247388132b6fd8a4ecd07abd6e4c5a0edFrançois Gaffie}
4298cc191247388132b6fd8a4ecd07abd6e4c5a0edFrançois Gaffie
4353615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffieaudio_module_handle_t AudioPort::getModuleHandle() const
4453615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie{
45a5e165d3a9074c09b67df5a89aa26b153cf69562Mikhail Naganov    return mModule != 0 ? mModule->getHandle() : AUDIO_MODULE_HANDLE_NONE;
4653615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie}
4753615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie
489ee0540d3a61bff03d561ca431a371c3d9335d2bMikhail Naganovuint32_t AudioPort::getModuleVersionMajor() const
49322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent{
50a5e165d3a9074c09b67df5a89aa26b153cf69562Mikhail Naganov    return mModule != 0 ? mModule->getHalVersionMajor() : 0;
51322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent}
52322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent
53322b4d25387a04c9afebe998326d005bbdf17edeEric Laurentconst char *AudioPort::getModuleName() const
54322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent{
55a5e165d3a9074c09b67df5a89aa26b153cf69562Mikhail Naganov    return mModule != 0 ? mModule->getName() : "invalid module";
56322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent}
57322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent
5856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivivoid AudioPort::toAudioPort(struct audio_port *port) const
5956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
60112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    // TODO: update this function once audio_port structure reflects the new profile definition.
61112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    // For compatibility reason: flatening the AudioProfile into audio_port structure.
62112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    SortedVector<audio_format_t> flatenedFormats;
63112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    SampleRateVector flatenedRates;
64112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    ChannelsVector flatenedChannels;
652478d528186436f693b02c3534f04425086b638cMikhail Naganov    for (const auto& profile : mProfiles) {
662478d528186436f693b02c3534f04425086b638cMikhail Naganov        if (profile->isValid()) {
672478d528186436f693b02c3534f04425086b638cMikhail Naganov            audio_format_t formatToExport = profile->getFormat();
682478d528186436f693b02c3534f04425086b638cMikhail Naganov            const SampleRateVector &ratesToExport = profile->getSampleRates();
692478d528186436f693b02c3534f04425086b638cMikhail Naganov            const ChannelsVector &channelsToExport = profile->getChannels();
70112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
71112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            if (flatenedFormats.indexOf(formatToExport) < 0) {
72112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                flatenedFormats.add(formatToExport);
7356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
74112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            for (size_t rateIndex = 0; rateIndex < ratesToExport.size(); rateIndex++) {
75112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                uint32_t rate = ratesToExport[rateIndex];
76112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                if (flatenedRates.indexOf(rate) < 0) {
77112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                    flatenedRates.add(rate);
7856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                }
7956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
80112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            for (size_t chanIndex = 0; chanIndex < channelsToExport.size(); chanIndex++) {
81112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                audio_channel_mask_t channels = channelsToExport[chanIndex];
82112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                if (flatenedChannels.indexOf(channels) < 0) {
83112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                    flatenedChannels.add(channels);
8456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                }
8556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
86112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            if (flatenedRates.size() > AUDIO_PORT_MAX_SAMPLING_RATES ||
87112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                    flatenedChannels.size() > AUDIO_PORT_MAX_CHANNEL_MASKS ||
88112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                    flatenedFormats.size() > AUDIO_PORT_MAX_FORMATS) {
89112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                ALOGE("%s: bailing out: cannot export profiles to port config", __FUNCTION__);
90112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                return;
9156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
9256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
9356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
94112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    port->role = mRole;
95112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    port->type = mType;
96112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    strlcpy(port->name, mName, AUDIO_PORT_MAX_NAME_LEN);
97112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    port->num_sample_rates = flatenedRates.size();
98112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    port->num_channel_masks = flatenedChannels.size();
99112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    port->num_formats = flatenedFormats.size();
100112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    for (size_t i = 0; i < flatenedRates.size(); i++) {
101112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        port->sample_rates[i] = flatenedRates[i];
10256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
103112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    for (size_t i = 0; i < flatenedChannels.size(); i++) {
104112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        port->channel_masks[i] = flatenedChannels[i];
10556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
106112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    for (size_t i = 0; i < flatenedFormats.size(); i++) {
107112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        port->formats[i] = flatenedFormats[i];
10856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
10956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
110112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size());
11156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
112112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    uint32_t i;
113112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    for (i = 0; i < mGains.size() && i < AUDIO_PORT_MAX_GAINS; i++) {
114112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        port->gains[i] = mGains[i]->getGain();
11556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
116112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    port->num_gains = i;
11756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
11856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
11983efe1c6bd6fa206560377960358ec95aa6a1c41Eric Laurentvoid AudioPort::importAudioPort(const sp<AudioPort>& port, bool force __unused)
12056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
1212478d528186436f693b02c3534f04425086b638cMikhail Naganov    for (const auto& profileToImport : port->mProfiles) {
122112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        if (profileToImport->isValid()) {
123112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            // Import only valid port, i.e. valid format, non empty rates and channels masks
124112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            bool hasSameProfile = false;
1252478d528186436f693b02c3534f04425086b638cMikhail Naganov            for (const auto& profile : mProfiles) {
1262478d528186436f693b02c3534f04425086b638cMikhail Naganov                if (*profile == *profileToImport) {
127112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                    // never import a profile twice
128112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                    hasSameProfile = true;
129f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                    break;
130f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung                }
131f27e2fbfc3284c00a60fa68edc51d436f75b1e32Andy Hung            }
132112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            if (hasSameProfile) { // never import a same profile twice
133112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                continue;
13456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
135112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            addAudioProfile(profileToImport);
13656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
13756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
13856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
13956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
1407a098c5e4366b9e2503b0211a82463e8a1cb0525Hongwei Wangstatus_t AudioPort::checkExactAudioProfile(const struct audio_port_config *config) const
1417a098c5e4366b9e2503b0211a82463e8a1cb0525Hongwei Wang{
1427a098c5e4366b9e2503b0211a82463e8a1cb0525Hongwei Wang    status_t status = NO_ERROR;
1437a098c5e4366b9e2503b0211a82463e8a1cb0525Hongwei Wang    auto config_mask = config->config_mask;
1447a098c5e4366b9e2503b0211a82463e8a1cb0525Hongwei Wang    if (config_mask & AUDIO_PORT_CONFIG_GAIN) {
1457a098c5e4366b9e2503b0211a82463e8a1cb0525Hongwei Wang        config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
1467a098c5e4366b9e2503b0211a82463e8a1cb0525Hongwei Wang        status = checkGain(&config->gain, config->gain.index);
1477a098c5e4366b9e2503b0211a82463e8a1cb0525Hongwei Wang        if (status != NO_ERROR) {
1487a098c5e4366b9e2503b0211a82463e8a1cb0525Hongwei Wang            return status;
1497a098c5e4366b9e2503b0211a82463e8a1cb0525Hongwei Wang        }
1507a098c5e4366b9e2503b0211a82463e8a1cb0525Hongwei Wang    }
1517a098c5e4366b9e2503b0211a82463e8a1cb0525Hongwei Wang    if (config_mask != 0) {
1527a098c5e4366b9e2503b0211a82463e8a1cb0525Hongwei Wang        // TODO should we check sample_rate / channel_mask / format separately?
1537a098c5e4366b9e2503b0211a82463e8a1cb0525Hongwei Wang        status = mProfiles.checkExactProfile(config->sample_rate,
1547a098c5e4366b9e2503b0211a82463e8a1cb0525Hongwei Wang                                             config->channel_mask,
1557a098c5e4366b9e2503b0211a82463e8a1cb0525Hongwei Wang                                             config->format);
1567a098c5e4366b9e2503b0211a82463e8a1cb0525Hongwei Wang    }
1577a098c5e4366b9e2503b0211a82463e8a1cb0525Hongwei Wang    return status;
1587a098c5e4366b9e2503b0211a82463e8a1cb0525Hongwei Wang}
1597a098c5e4366b9e2503b0211a82463e8a1cb0525Hongwei Wang
160112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffievoid AudioPort::pickSamplingRate(uint32_t &pickedRate,const SampleRateVector &samplingRates) const
16156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
162112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    pickedRate = 0;
16356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // For direct outputs, pick minimum sampling rate: this helps ensuring that the
16456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // channel count / sampling rate combination chosen will be supported by the connected
16556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // sink
166112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    if (isDirectOutput()) {
16756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        uint32_t samplingRate = UINT_MAX;
168112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        for (size_t i = 0; i < samplingRates.size(); i ++) {
169112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            if ((samplingRates[i] < samplingRate) && (samplingRates[i] > 0)) {
170112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                samplingRate = samplingRates[i];
17156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
17256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
173112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        pickedRate = (samplingRate == UINT_MAX) ? 0 : samplingRate;
174112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    } else {
17505ddca504ce8e0e61b41e5c1aebea72086eea57bGlenn Kasten        uint32_t maxRate = SAMPLE_RATE_HZ_MAX;
176112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
177112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        // For mixed output and inputs, use max mixer sampling rates. Do not
178112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        // limit sampling rate otherwise
179112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        // For inputs, also see checkCompatibleSamplingRate().
180112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        if (mType != AUDIO_PORT_TYPE_MIX) {
181112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            maxRate = UINT_MAX;
182112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        }
183112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        // TODO: should mSamplingRates[] be ordered in terms of our preference
184112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        // and we return the first (and hence most preferred) match?  This is of concern if
185112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        // we want to choose 96kHz over 192kHz for USB driver stability or resource constraints.
186112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        for (size_t i = 0; i < samplingRates.size(); i ++) {
187112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            if ((samplingRates[i] > pickedRate) && (samplingRates[i] <= maxRate)) {
188112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                pickedRate = samplingRates[i];
189112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            }
19056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
19156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
19256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
19356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
194112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffievoid AudioPort::pickChannelMask(audio_channel_mask_t &pickedChannelMask,
195112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                const ChannelsVector &channelMasks) const
19656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
197112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    pickedChannelMask = AUDIO_CHANNEL_NONE;
19856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // For direct outputs, pick minimum channel count: this helps ensuring that the
19956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // channel count / sampling rate combination chosen will be supported by the connected
20056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // sink
201112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    if (isDirectOutput()) {
20256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        uint32_t channelCount = UINT_MAX;
203112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        for (size_t i = 0; i < channelMasks.size(); i ++) {
20456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            uint32_t cnlCount;
205a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            if (useInputChannelMask()) {
206112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                cnlCount = audio_channel_count_from_in_mask(channelMasks[i]);
20756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            } else {
208112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                cnlCount = audio_channel_count_from_out_mask(channelMasks[i]);
20956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
21056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            if ((cnlCount < channelCount) && (cnlCount > 0)) {
211112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                pickedChannelMask = channelMasks[i];
21256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                channelCount = cnlCount;
21356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
21456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
215112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    } else {
216112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        uint32_t channelCount = 0;
217112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        uint32_t maxCount = MAX_MIXER_CHANNEL_COUNT;
21856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
219112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        // For mixed output and inputs, use max mixer channel count. Do not
220112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        // limit channel count otherwise
221112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        if (mType != AUDIO_PORT_TYPE_MIX) {
222112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            maxCount = UINT_MAX;
22356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
224112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        for (size_t i = 0; i < channelMasks.size(); i ++) {
225112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            uint32_t cnlCount;
226112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            if (useInputChannelMask()) {
227112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                cnlCount = audio_channel_count_from_in_mask(channelMasks[i]);
228112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            } else {
229112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                cnlCount = audio_channel_count_from_out_mask(channelMasks[i]);
230112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            }
231112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            if ((cnlCount > channelCount) && (cnlCount <= maxCount)) {
232112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                pickedChannelMask = channelMasks[i];
233112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                channelCount = cnlCount;
234112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            }
23556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
23656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
23756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
23856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
23956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi/* format in order of increasing preference */
24056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Triviconst audio_format_t AudioPort::sPcmFormatCompareTable[] = {
24156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        AUDIO_FORMAT_DEFAULT,
24256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        AUDIO_FORMAT_PCM_16_BIT,
24356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        AUDIO_FORMAT_PCM_8_24_BIT,
24456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        AUDIO_FORMAT_PCM_24_BIT_PACKED,
24556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        AUDIO_FORMAT_PCM_32_BIT,
24656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        AUDIO_FORMAT_PCM_FLOAT,
24756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi};
24856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
249112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffieint AudioPort::compareFormats(audio_format_t format1, audio_format_t format2)
25056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
25156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // NOTE: AUDIO_FORMAT_INVALID is also considered not PCM and will be compared equal to any
25256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // compressed format and better than any PCM format. This is by design of pickFormat()
25356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (!audio_is_linear_pcm(format1)) {
25456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (!audio_is_linear_pcm(format2)) {
25556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            return 0;
25656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
25756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return 1;
25856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
25956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (!audio_is_linear_pcm(format2)) {
26056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return -1;
26156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
26256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
26356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    int index1 = -1, index2 = -1;
26456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    for (size_t i = 0;
26556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            (i < ARRAY_SIZE(sPcmFormatCompareTable)) && ((index1 == -1) || (index2 == -1));
26656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            i ++) {
26756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (sPcmFormatCompareTable[i] == format1) {
26856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            index1 = i;
26956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
27056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (sPcmFormatCompareTable[i] == format2) {
27156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            index2 = i;
27256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
27356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
27456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // format1 not found => index1 < 0 => format2 > format1
27556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // format2 not found => index2 < 0 => format2 < format1
27656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    return index1 - index2;
27756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
27856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
279e693002b0fb25099540588245892ed98103749baEric Laurentbool AudioPort::isBetterFormatMatch(audio_format_t newFormat,
280e693002b0fb25099540588245892ed98103749baEric Laurent                                    audio_format_t currentFormat,
281e693002b0fb25099540588245892ed98103749baEric Laurent                                    audio_format_t targetFormat)
282e693002b0fb25099540588245892ed98103749baEric Laurent{
283e693002b0fb25099540588245892ed98103749baEric Laurent    if (newFormat == currentFormat) {
284e693002b0fb25099540588245892ed98103749baEric Laurent        return false;
285e693002b0fb25099540588245892ed98103749baEric Laurent    }
286e693002b0fb25099540588245892ed98103749baEric Laurent    if (currentFormat == AUDIO_FORMAT_INVALID) {
287e693002b0fb25099540588245892ed98103749baEric Laurent        return true;
288e693002b0fb25099540588245892ed98103749baEric Laurent    }
289e693002b0fb25099540588245892ed98103749baEric Laurent    if (newFormat == targetFormat) {
290e693002b0fb25099540588245892ed98103749baEric Laurent        return true;
291e693002b0fb25099540588245892ed98103749baEric Laurent    }
292e693002b0fb25099540588245892ed98103749baEric Laurent    int currentDiffBytes = (int)audio_bytes_per_sample(targetFormat) -
293e693002b0fb25099540588245892ed98103749baEric Laurent            audio_bytes_per_sample(currentFormat);
294e693002b0fb25099540588245892ed98103749baEric Laurent    int newDiffBytes = (int)audio_bytes_per_sample(targetFormat) -
295e693002b0fb25099540588245892ed98103749baEric Laurent            audio_bytes_per_sample(newFormat);
296e693002b0fb25099540588245892ed98103749baEric Laurent
297e693002b0fb25099540588245892ed98103749baEric Laurent    if (abs(newDiffBytes) < abs(currentDiffBytes)) {
298e693002b0fb25099540588245892ed98103749baEric Laurent        return true;
299e693002b0fb25099540588245892ed98103749baEric Laurent    } else if (abs(newDiffBytes) == abs(currentDiffBytes)) {
300e693002b0fb25099540588245892ed98103749baEric Laurent        return (newDiffBytes >= 0);
301e693002b0fb25099540588245892ed98103749baEric Laurent    }
302e693002b0fb25099540588245892ed98103749baEric Laurent    return false;
303e693002b0fb25099540588245892ed98103749baEric Laurent}
304e693002b0fb25099540588245892ed98103749baEric Laurent
305112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffievoid AudioPort::pickAudioProfile(uint32_t &samplingRate,
306112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                 audio_channel_mask_t &channelMask,
307112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                 audio_format_t &format) const
30856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
309112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    format = AUDIO_FORMAT_DEFAULT;
310112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    samplingRate = 0;
311112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    channelMask = AUDIO_CHANNEL_NONE;
312112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
31356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // special case for uninitialized dynamic profile
314112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    if (!mProfiles.hasValidProfile()) {
315112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        return;
31656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
317112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    audio_format_t bestFormat = sPcmFormatCompareTable[ARRAY_SIZE(sPcmFormatCompareTable) - 1];
318112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    // For mixed output and inputs, use best mixer output format.
319112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    // Do not limit format otherwise
320112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    if ((mType != AUDIO_PORT_TYPE_MIX) || isDirectOutput()) {
32156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        bestFormat = AUDIO_FORMAT_INVALID;
32256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
32356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
324112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    for (size_t i = 0; i < mProfiles.size(); i ++) {
325112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        if (!mProfiles[i]->isValid()) {
326112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            continue;
327112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        }
328112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        audio_format_t formatToCompare = mProfiles[i]->getFormat();
329112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        if ((compareFormats(formatToCompare, format) > 0) &&
330112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                (compareFormats(formatToCompare, bestFormat) <= 0)) {
331112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            uint32_t pickedSamplingRate = 0;
332112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            audio_channel_mask_t pickedChannelMask = AUDIO_CHANNEL_NONE;
333112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            pickChannelMask(pickedChannelMask, mProfiles[i]->getChannels());
334112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            pickSamplingRate(pickedSamplingRate, mProfiles[i]->getSampleRates());
335112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
336112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            if (formatToCompare != AUDIO_FORMAT_DEFAULT && pickedChannelMask != AUDIO_CHANNEL_NONE
337112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                    && pickedSamplingRate != 0) {
338112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                format = formatToCompare;
339112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                channelMask = pickedChannelMask;
340112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                samplingRate = pickedSamplingRate;
341112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                // TODO: shall we return on the first one or still trying to pick a better Profile?
342112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            }
34356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
34456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
345f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    ALOGV("%s Port[nm:%s] profile rate=%d, format=%d, channels=%d", __FUNCTION__, mName.string(),
346f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie          samplingRate, channelMask, format);
34756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
34856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
349112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffiestatus_t AudioPort::checkGain(const struct audio_gain_config *gainConfig, int index) const
35056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
35156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (index < 0 || (size_t)index >= mGains.size()) {
35256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return BAD_VALUE;
35356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
35456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    return mGains[index]->checkConfig(gainConfig);
35556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
35656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
357112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffievoid AudioPort::dump(int fd, int spaces, bool verbose) const
35856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
35956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    const size_t SIZE = 256;
36056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    char buffer[SIZE];
36156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    String8 result;
36256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
363f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    if (!mName.isEmpty()) {
36456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        snprintf(buffer, SIZE, "%*s- name: %s\n", spaces, "", mName.string());
36556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        result.append(buffer);
366112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        write(fd, result.string(), result.size());
36756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
368112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    if (verbose) {
369112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        mProfiles.dump(fd, spaces);
37056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
371112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        if (mGains.size() != 0) {
372112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            snprintf(buffer, SIZE, "%*s- gains:\n", spaces, "");
373f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            result = buffer;
374f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie            write(fd, result.string(), result.size());
375112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            for (size_t i = 0; i < mGains.size(); i++) {
376112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                mGains[i]->dump(fd, spaces + 2, i);
37756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
37856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
37956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
38056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
38156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
382aa9811945f575614b3482d09e4d969792701cebbPaul McLeanvoid AudioPort::log(const char* indent) const
383aa9811945f575614b3482d09e4d969792701cebbPaul McLean{
384aa9811945f575614b3482d09e4d969792701cebbPaul McLean    ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.string(), mType, mRole);
385aa9811945f575614b3482d09e4d969792701cebbPaul McLean}
38656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
38756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi// --- AudioPortConfig class implementation
38856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
38956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel TriviAudioPortConfig::AudioPortConfig()
39056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
39156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    mSamplingRate = 0;
39256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    mChannelMask = AUDIO_CHANNEL_NONE;
39356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    mFormat = AUDIO_FORMAT_INVALID;
394f2f6999b329654641e6af29678f5aa047325d3a0jiabin    memset(&mGain, 0, sizeof(struct audio_gain_config));
39556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    mGain.index = -1;
39656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
39756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
398112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffiestatus_t AudioPortConfig::applyAudioPortConfig(const struct audio_port_config *config,
399112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                               struct audio_port_config *backupConfig)
40056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
40156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    struct audio_port_config localBackupConfig;
40256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    status_t status = NO_ERROR;
40356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
40456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    localBackupConfig.config_mask = config->config_mask;
40556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    toAudioPortConfig(&localBackupConfig);
40656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
40756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    sp<AudioPort> audioport = getAudioPort();
40856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (audioport == 0) {
40956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        status = NO_INIT;
41056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        goto exit;
41156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
4127a098c5e4366b9e2503b0211a82463e8a1cb0525Hongwei Wang    status = audioport->checkExactAudioProfile(config);
413112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    if (status != NO_ERROR) {
414112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        goto exit;
415112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    }
41656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (config->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
41756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        mSamplingRate = config->sample_rate;
41856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
41956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (config->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
42056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        mChannelMask = config->channel_mask;
42156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
42256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (config->config_mask & AUDIO_PORT_CONFIG_FORMAT) {
42356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        mFormat = config->format;
42456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
42556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) {
42656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        mGain = config->gain;
42756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
42856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
42956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Triviexit:
43056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (status != NO_ERROR) {
43156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        applyAudioPortConfig(&localBackupConfig);
43256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
43356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (backupConfig != NULL) {
43456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        *backupConfig = localBackupConfig;
43556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
43656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    return status;
43756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
43856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
43956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivivoid AudioPortConfig::toAudioPortConfig(struct audio_port_config *dstConfig,
44056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                                        const struct audio_port_config *srcConfig) const
44156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
44256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
44356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        dstConfig->sample_rate = mSamplingRate;
44456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE)) {
44556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            dstConfig->sample_rate = srcConfig->sample_rate;
44656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
44756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    } else {
44856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        dstConfig->sample_rate = 0;
44956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
45056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
45156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        dstConfig->channel_mask = mChannelMask;
45256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK)) {
45356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            dstConfig->channel_mask = srcConfig->channel_mask;
45456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
45556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    } else {
45656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        dstConfig->channel_mask = AUDIO_CHANNEL_NONE;
45756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
45856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT) {
45956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        dstConfig->format = mFormat;
46056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT)) {
46156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            dstConfig->format = srcConfig->format;
46256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
46356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    } else {
46456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        dstConfig->format = AUDIO_FORMAT_INVALID;
46556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
46660d156247a7189d59af0a3643e2a786dacef734dWonsik Kim    sp<AudioPort> audioport = getAudioPort();
46760d156247a7189d59af0a3643e2a786dacef734dWonsik Kim    if ((dstConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) && audioport != NULL) {
46856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        dstConfig->gain = mGain;
46960d156247a7189d59af0a3643e2a786dacef734dWonsik Kim        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_GAIN)
47060d156247a7189d59af0a3643e2a786dacef734dWonsik Kim                && audioport->checkGain(&srcConfig->gain, srcConfig->gain.index) == OK) {
47156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            dstConfig->gain = srcConfig->gain;
47256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
47356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    } else {
47456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        dstConfig->gain.index = -1;
47556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
47656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (dstConfig->gain.index != -1) {
47756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        dstConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN;
47856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    } else {
47956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        dstConfig->config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
48056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
48156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
48256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
4831b2a794a27caab3a1320d22b872b04ef73e96555Mikhail Naganov} // namespace android
484