1112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie/* 2112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * Copyright (C) 2015 The Android Open Source Project 3112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * 4112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * Licensed under the Apache License, Version 2.0 (the "License"); 5112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * you may not use this file except in compliance with the License. 6112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * You may obtain a copy of the License at 7112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * 8112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * http://www.apache.org/licenses/LICENSE-2.0 9112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * 10112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * Unless required by applicable law or agreed to in writing, software 11112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * distributed under the License is distributed on an "AS IS" BASIS, 12112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * See the License for the specific language governing permissions and 14112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * limitations under the License. 15112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie */ 16112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie 17112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie#define LOG_TAG "APM::AudioProfile" 18112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie//#define LOG_NDEBUG 0 19112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie 20112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie#include "AudioProfile.h" 21112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie#include "AudioPort.h" 22112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie#include "HwModule.h" 23112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie#include "AudioGain.h" 24112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie#include <utils/SortedVector.h> 25112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie#include "TypeConverter.h" 26112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie#include <media/AudioResamplerPublic.h> 27112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie#include <algorithm> 28112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie 29112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffienamespace android { 30112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie 31112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffiestatus_t AudioProfile::checkExact(uint32_t samplingRate, audio_channel_mask_t channelMask, 32112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie audio_format_t format) const 33112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie{ 34e693002b0fb25099540588245892ed98103749baEric Laurent if (audio_formats_match(format, mFormat) && 352cc2a03319144bcebac5a9693319776afc471307Phil Burk supportsChannels(channelMask) && 362cc2a03319144bcebac5a9693319776afc471307Phil Burk supportsRate(samplingRate)) { 37112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie return NO_ERROR; 38112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 39112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie return BAD_VALUE; 40112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie} 41112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie 42112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffietemplate <typename T> 43112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffiebool operator == (const SortedVector<T> &left, const SortedVector<T> &right) 44112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie{ 45112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie if (left.size() != right.size()) { 46112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie return false; 47112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 48112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie for(size_t index = 0; index < right.size(); index++) { 49112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie if (left[index] != right[index]) { 50112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie return false; 51112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 52112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 53112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie return true; 54112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie} 55112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie 56112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffiebool operator == (const AudioProfile &left, const AudioProfile &compareTo) 57112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie{ 58112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie return (left.getFormat() == compareTo.getFormat()) && 59112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie (left.getChannels() == compareTo.getChannels()) && 60112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie (left.getSampleRates() == compareTo.getSampleRates()); 61112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie} 62112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie 63112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffiestatus_t AudioProfile::checkCompatibleSamplingRate(uint32_t samplingRate, 64112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie uint32_t &updatedSamplingRate) const 65112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie{ 6605ddca504ce8e0e61b41e5c1aebea72086eea57bGlenn Kasten ALOG_ASSERT(samplingRate > 0); 6705ddca504ce8e0e61b41e5c1aebea72086eea57bGlenn Kasten 68112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie if (mSamplingRates.isEmpty()) { 69112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie updatedSamplingRate = samplingRate; 70112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie return NO_ERROR; 71112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 7205ddca504ce8e0e61b41e5c1aebea72086eea57bGlenn Kasten 73112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // Search for the closest supported sampling rate that is above (preferred) 74112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // or below (acceptable) the desired sampling rate, within a permitted ratio. 75112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // The sampling rates are sorted in ascending order. 76112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie size_t orderOfDesiredRate = mSamplingRates.orderOf(samplingRate); 77112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie 78112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // Prefer to down-sample from a higher sampling rate, as we get the desired frequency spectrum. 79112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie if (orderOfDesiredRate < mSamplingRates.size()) { 80112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie uint32_t candidate = mSamplingRates[orderOfDesiredRate]; 81112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie if (candidate / AUDIO_RESAMPLER_DOWN_RATIO_MAX <= samplingRate) { 82112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie updatedSamplingRate = candidate; 83112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie return NO_ERROR; 84112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 85112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 86112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // But if we have to up-sample from a lower sampling rate, that's OK. 87112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie if (orderOfDesiredRate != 0) { 88112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie uint32_t candidate = mSamplingRates[orderOfDesiredRate - 1]; 89112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie if (candidate * AUDIO_RESAMPLER_UP_RATIO_MAX >= samplingRate) { 90112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie updatedSamplingRate = candidate; 91112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie return NO_ERROR; 92112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 93112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 94112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // leave updatedSamplingRate unmodified 95112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie return BAD_VALUE; 96112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie} 97112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie 98112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffiestatus_t AudioProfile::checkCompatibleChannelMask(audio_channel_mask_t channelMask, 99112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie audio_channel_mask_t &updatedChannelMask, 100112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie audio_port_type_t portType, 101112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie audio_port_role_t portRole) const 102112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie{ 103112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie if (mChannelMasks.isEmpty()) { 104112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie updatedChannelMask = channelMask; 105112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie return NO_ERROR; 106112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 107112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie const bool isRecordThread = portType == AUDIO_PORT_TYPE_MIX && portRole == AUDIO_PORT_ROLE_SINK; 108112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie const bool isIndex = audio_channel_mask_get_representation(channelMask) 109112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie == AUDIO_CHANNEL_REPRESENTATION_INDEX; 110112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie int bestMatch = 0; 111112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie for (size_t i = 0; i < mChannelMasks.size(); i ++) { 112112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie audio_channel_mask_t supported = mChannelMasks[i]; 113112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie if (supported == channelMask) { 114112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // Exact matches always taken. 115112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie updatedChannelMask = channelMask; 116112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie return NO_ERROR; 117112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 118112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie 119112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // AUDIO_CHANNEL_NONE (value: 0) is used for dynamic channel support 120112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie if (isRecordThread && supported != AUDIO_CHANNEL_NONE) { 121112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // Approximate (best) match: 122112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // The match score measures how well the supported channel mask matches the 123112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // desired mask, where increasing-is-better. 124112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // 125112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // TODO: Some tweaks may be needed. 126112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // Should be a static function of the data processing library. 127112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // 128112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // In priority: 129112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // match score = 1000 if legacy channel conversion equivalent (always prefer this) 130112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // OR 131112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // match score += 100 if the channel mask representations match 132112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // match score += number of channels matched. 133112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // 134112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // If there are no matched channels, the mask may still be accepted 135112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // but the playback or record will be silent. 136112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie const bool isSupportedIndex = (audio_channel_mask_get_representation(supported) 137112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie == AUDIO_CHANNEL_REPRESENTATION_INDEX); 138112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie int match; 139112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie if (isIndex && isSupportedIndex) { 140112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // index equivalence 141112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie match = 100 + __builtin_popcount( 142112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie audio_channel_mask_get_bits(channelMask) 143112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie & audio_channel_mask_get_bits(supported)); 144112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } else if (isIndex && !isSupportedIndex) { 145112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie const uint32_t equivalentBits = 146112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie (1 << audio_channel_count_from_in_mask(supported)) - 1 ; 147112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie match = __builtin_popcount( 148112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie audio_channel_mask_get_bits(channelMask) & equivalentBits); 149112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } else if (!isIndex && isSupportedIndex) { 150112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie const uint32_t equivalentBits = 151112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie (1 << audio_channel_count_from_in_mask(channelMask)) - 1; 152112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie match = __builtin_popcount( 153112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie equivalentBits & audio_channel_mask_get_bits(supported)); 154112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } else { 155112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // positional equivalence 156112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie match = 100 + __builtin_popcount( 157112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie audio_channel_mask_get_bits(channelMask) 158112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie & audio_channel_mask_get_bits(supported)); 159112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie switch (supported) { 160112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie case AUDIO_CHANNEL_IN_FRONT_BACK: 161112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie case AUDIO_CHANNEL_IN_STEREO: 162112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie if (channelMask == AUDIO_CHANNEL_IN_MONO) { 163112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie match = 1000; 164112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 165112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie break; 166112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie case AUDIO_CHANNEL_IN_MONO: 167112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie if (channelMask == AUDIO_CHANNEL_IN_FRONT_BACK 168112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie || channelMask == AUDIO_CHANNEL_IN_STEREO) { 169112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie match = 1000; 170112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 171112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie break; 172112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie default: 173112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie break; 174112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 175112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 176112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie if (match > bestMatch) { 177112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie bestMatch = match; 178112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie updatedChannelMask = supported; 179112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 180112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 181112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 182112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie return bestMatch > 0 ? NO_ERROR : BAD_VALUE; 183112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie} 184112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie 185112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffievoid AudioProfile::dump(int fd, int spaces) const 186112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie{ 187112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie const size_t SIZE = 256; 188112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie char buffer[SIZE]; 189112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie String8 result; 190112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie 191112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie snprintf(buffer, SIZE, "%s%s%s\n", mIsDynamicFormat ? "[dynamic format]" : "", 192112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie mIsDynamicChannels ? "[dynamic channels]" : "", 193112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie mIsDynamicRate ? "[dynamic rates]" : ""); 194112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie result.append(buffer); 195112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie if (mName.length() != 0) { 196112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie snprintf(buffer, SIZE, "%*s- name: %s\n", spaces, "", mName.string()); 197112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie result.append(buffer); 198112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 199112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie std::string formatLiteral; 200112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie if (FormatConverter::toString(mFormat, formatLiteral)) { 201112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie snprintf(buffer, SIZE, "%*s- format: %s\n", spaces, "", formatLiteral.c_str()); 202112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie result.append(buffer); 203112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 204112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie if (!mSamplingRates.isEmpty()) { 205112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie snprintf(buffer, SIZE, "%*s- sampling rates:", spaces, ""); 206112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie result.append(buffer); 207112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie for (size_t i = 0; i < mSamplingRates.size(); i++) { 208112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie snprintf(buffer, SIZE, "%d", mSamplingRates[i]); 209112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie result.append(buffer); 210112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie result.append(i == (mSamplingRates.size() - 1) ? "" : ", "); 211112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 212112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie result.append("\n"); 213112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 214112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie 215112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie if (!mChannelMasks.isEmpty()) { 216112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie snprintf(buffer, SIZE, "%*s- channel masks:", spaces, ""); 217112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie result.append(buffer); 218112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie for (size_t i = 0; i < mChannelMasks.size(); i++) { 219112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie snprintf(buffer, SIZE, "0x%04x", mChannelMasks[i]); 220112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie result.append(buffer); 221112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie result.append(i == (mChannelMasks.size() - 1) ? "" : ", "); 222112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 223112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie result.append("\n"); 224112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 225112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie write(fd, result.string(), result.size()); 226112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie} 227112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie 228112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffiestatus_t AudioProfileVector::checkExactProfile(uint32_t samplingRate, 229112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie audio_channel_mask_t channelMask, 230112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie audio_format_t format) const 231112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie{ 232112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie if (isEmpty()) { 233112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie return NO_ERROR; 234112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 235112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie 236112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie for (size_t i = 0; i < size(); i++) { 237112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie const sp<AudioProfile> profile = itemAt(i); 238112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie if (profile->checkExact(samplingRate, channelMask, format) == NO_ERROR) { 239112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie return NO_ERROR; 240112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 241112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 242112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie return BAD_VALUE; 243112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie} 244112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie 245112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffiestatus_t AudioProfileVector::checkCompatibleProfile(uint32_t &samplingRate, 246112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie audio_channel_mask_t &channelMask, 247112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie audio_format_t &format, 248112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie audio_port_type_t portType, 249112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie audio_port_role_t portRole) const 250112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie{ 251112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie if (isEmpty()) { 252112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie return NO_ERROR; 253112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 254112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie 255112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie const bool checkInexact = // when port is input and format is linear pcm 256112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie portType == AUDIO_PORT_TYPE_MIX && portRole == AUDIO_PORT_ROLE_SINK 257112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie && audio_is_linear_pcm(format); 258112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie 259112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // iterate from best format to worst format (reverse order) 260112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie for (ssize_t i = size() - 1; i >= 0 ; --i) { 261112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie const sp<AudioProfile> profile = itemAt(i); 262112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie audio_format_t formatToCompare = profile->getFormat(); 263112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie if (formatToCompare == format || 264112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie (checkInexact 265112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie && formatToCompare != AUDIO_FORMAT_DEFAULT 266112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie && audio_is_linear_pcm(formatToCompare))) { 267112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // Compatible profile has been found, checks if this profile has compatible 268112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // rate and channels as well 269112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie audio_channel_mask_t updatedChannels; 270112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie uint32_t updatedRate; 271112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie if (profile->checkCompatibleChannelMask(channelMask, updatedChannels, 272112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie portType, portRole) == NO_ERROR && 273112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie profile->checkCompatibleSamplingRate(samplingRate, updatedRate) == NO_ERROR) { 274112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie // for inexact checks we take the first linear pcm format due to sorting. 275112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie format = formatToCompare; 276112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie channelMask = updatedChannels; 277112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie samplingRate = updatedRate; 278112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie return NO_ERROR; 279112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 280112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 281112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie } 282112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie return BAD_VALUE; 283112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie} 284112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie 285112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffieint AudioProfileVector::compareFormats(const sp<AudioProfile> *profile1, 286112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie const sp<AudioProfile> *profile2) 287112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie{ 288112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie return AudioPort::compareFormats((*profile1)->getFormat(), (*profile2)->getFormat()); 289112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie} 290112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie 291112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie}; // namespace android 292