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