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