AudioPort.cpp revision e693002b0fb25099540588245892ed98103749ba
1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "APM::AudioPort" 18//#define LOG_NDEBUG 0 19#include "TypeConverter.h" 20#include "AudioPort.h" 21#include "HwModule.h" 22#include "AudioGain.h" 23#include <policy.h> 24 25#ifndef ARRAY_SIZE 26#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 27#endif 28 29namespace android { 30 31int32_t volatile AudioPort::mNextUniqueId = 1; 32 33// --- AudioPort class implementation 34void AudioPort::attach(const sp<HwModule>& module) 35{ 36 mModule = module; 37} 38 39audio_port_handle_t AudioPort::getNextUniqueId() 40{ 41 return static_cast<audio_port_handle_t>(android_atomic_inc(&mNextUniqueId)); 42} 43 44audio_module_handle_t AudioPort::getModuleHandle() const 45{ 46 if (mModule == 0) { 47 return 0; 48 } 49 return mModule->mHandle; 50} 51 52uint32_t AudioPort::getModuleVersion() const 53{ 54 if (mModule == 0) { 55 return 0; 56 } 57 return mModule->getHalVersion(); 58} 59 60const char *AudioPort::getModuleName() const 61{ 62 if (mModule == 0) { 63 return "invalid module"; 64 } 65 return mModule->getName(); 66} 67 68void AudioPort::toAudioPort(struct audio_port *port) const 69{ 70 // TODO: update this function once audio_port structure reflects the new profile definition. 71 // For compatibility reason: flatening the AudioProfile into audio_port structure. 72 SortedVector<audio_format_t> flatenedFormats; 73 SampleRateVector flatenedRates; 74 ChannelsVector flatenedChannels; 75 for (size_t profileIndex = 0; profileIndex < mProfiles.size(); profileIndex++) { 76 if (mProfiles[profileIndex]->isValid()) { 77 audio_format_t formatToExport = mProfiles[profileIndex]->getFormat(); 78 const SampleRateVector &ratesToExport = mProfiles[profileIndex]->getSampleRates(); 79 const ChannelsVector &channelsToExport = mProfiles[profileIndex]->getChannels(); 80 81 if (flatenedFormats.indexOf(formatToExport) < 0) { 82 flatenedFormats.add(formatToExport); 83 } 84 for (size_t rateIndex = 0; rateIndex < ratesToExport.size(); rateIndex++) { 85 uint32_t rate = ratesToExport[rateIndex]; 86 if (flatenedRates.indexOf(rate) < 0) { 87 flatenedRates.add(rate); 88 } 89 } 90 for (size_t chanIndex = 0; chanIndex < channelsToExport.size(); chanIndex++) { 91 audio_channel_mask_t channels = channelsToExport[chanIndex]; 92 if (flatenedChannels.indexOf(channels) < 0) { 93 flatenedChannels.add(channels); 94 } 95 } 96 if (flatenedRates.size() > AUDIO_PORT_MAX_SAMPLING_RATES || 97 flatenedChannels.size() > AUDIO_PORT_MAX_CHANNEL_MASKS || 98 flatenedFormats.size() > AUDIO_PORT_MAX_FORMATS) { 99 ALOGE("%s: bailing out: cannot export profiles to port config", __FUNCTION__); 100 return; 101 } 102 } 103 } 104 port->role = mRole; 105 port->type = mType; 106 strlcpy(port->name, mName, AUDIO_PORT_MAX_NAME_LEN); 107 port->num_sample_rates = flatenedRates.size(); 108 port->num_channel_masks = flatenedChannels.size(); 109 port->num_formats = flatenedFormats.size(); 110 for (size_t i = 0; i < flatenedRates.size(); i++) { 111 port->sample_rates[i] = flatenedRates[i]; 112 } 113 for (size_t i = 0; i < flatenedChannels.size(); i++) { 114 port->channel_masks[i] = flatenedChannels[i]; 115 } 116 for (size_t i = 0; i < flatenedFormats.size(); i++) { 117 port->formats[i] = flatenedFormats[i]; 118 } 119 120 ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size()); 121 122 uint32_t i; 123 for (i = 0; i < mGains.size() && i < AUDIO_PORT_MAX_GAINS; i++) { 124 port->gains[i] = mGains[i]->getGain(); 125 } 126 port->num_gains = i; 127} 128 129void AudioPort::importAudioPort(const sp<AudioPort> port) 130{ 131 size_t indexToImport; 132 for (indexToImport = 0; indexToImport < port->mProfiles.size(); indexToImport++) { 133 const sp<AudioProfile> &profileToImport = port->mProfiles[indexToImport]; 134 if (profileToImport->isValid()) { 135 // Import only valid port, i.e. valid format, non empty rates and channels masks 136 bool hasSameProfile = false; 137 for (size_t profileIndex = 0; profileIndex < mProfiles.size(); profileIndex++) { 138 if (*mProfiles[profileIndex] == *profileToImport) { 139 // never import a profile twice 140 hasSameProfile = true; 141 break; 142 } 143 } 144 if (hasSameProfile) { // never import a same profile twice 145 continue; 146 } 147 addAudioProfile(profileToImport); 148 } 149 } 150} 151 152void AudioPort::pickSamplingRate(uint32_t &pickedRate,const SampleRateVector &samplingRates) const 153{ 154 pickedRate = 0; 155 // For direct outputs, pick minimum sampling rate: this helps ensuring that the 156 // channel count / sampling rate combination chosen will be supported by the connected 157 // sink 158 if (isDirectOutput()) { 159 uint32_t samplingRate = UINT_MAX; 160 for (size_t i = 0; i < samplingRates.size(); i ++) { 161 if ((samplingRates[i] < samplingRate) && (samplingRates[i] > 0)) { 162 samplingRate = samplingRates[i]; 163 } 164 } 165 pickedRate = (samplingRate == UINT_MAX) ? 0 : samplingRate; 166 } else { 167 uint32_t maxRate = MAX_MIXER_SAMPLING_RATE; 168 169 // For mixed output and inputs, use max mixer sampling rates. Do not 170 // limit sampling rate otherwise 171 // For inputs, also see checkCompatibleSamplingRate(). 172 if (mType != AUDIO_PORT_TYPE_MIX) { 173 maxRate = UINT_MAX; 174 } 175 // TODO: should mSamplingRates[] be ordered in terms of our preference 176 // and we return the first (and hence most preferred) match? This is of concern if 177 // we want to choose 96kHz over 192kHz for USB driver stability or resource constraints. 178 for (size_t i = 0; i < samplingRates.size(); i ++) { 179 if ((samplingRates[i] > pickedRate) && (samplingRates[i] <= maxRate)) { 180 pickedRate = samplingRates[i]; 181 } 182 } 183 } 184} 185 186void AudioPort::pickChannelMask(audio_channel_mask_t &pickedChannelMask, 187 const ChannelsVector &channelMasks) const 188{ 189 pickedChannelMask = AUDIO_CHANNEL_NONE; 190 // For direct outputs, pick minimum channel count: this helps ensuring that the 191 // channel count / sampling rate combination chosen will be supported by the connected 192 // sink 193 if (isDirectOutput()) { 194 uint32_t channelCount = UINT_MAX; 195 for (size_t i = 0; i < channelMasks.size(); i ++) { 196 uint32_t cnlCount; 197 if (useInputChannelMask()) { 198 cnlCount = audio_channel_count_from_in_mask(channelMasks[i]); 199 } else { 200 cnlCount = audio_channel_count_from_out_mask(channelMasks[i]); 201 } 202 if ((cnlCount < channelCount) && (cnlCount > 0)) { 203 pickedChannelMask = channelMasks[i]; 204 channelCount = cnlCount; 205 } 206 } 207 } else { 208 uint32_t channelCount = 0; 209 uint32_t maxCount = MAX_MIXER_CHANNEL_COUNT; 210 211 // For mixed output and inputs, use max mixer channel count. Do not 212 // limit channel count otherwise 213 if (mType != AUDIO_PORT_TYPE_MIX) { 214 maxCount = UINT_MAX; 215 } 216 for (size_t i = 0; i < channelMasks.size(); i ++) { 217 uint32_t cnlCount; 218 if (useInputChannelMask()) { 219 cnlCount = audio_channel_count_from_in_mask(channelMasks[i]); 220 } else { 221 cnlCount = audio_channel_count_from_out_mask(channelMasks[i]); 222 } 223 if ((cnlCount > channelCount) && (cnlCount <= maxCount)) { 224 pickedChannelMask = channelMasks[i]; 225 channelCount = cnlCount; 226 } 227 } 228 } 229} 230 231/* format in order of increasing preference */ 232const audio_format_t AudioPort::sPcmFormatCompareTable[] = { 233 AUDIO_FORMAT_DEFAULT, 234 AUDIO_FORMAT_PCM_16_BIT, 235 AUDIO_FORMAT_PCM_8_24_BIT, 236 AUDIO_FORMAT_PCM_24_BIT_PACKED, 237 AUDIO_FORMAT_PCM_32_BIT, 238 AUDIO_FORMAT_PCM_FLOAT, 239}; 240 241int AudioPort::compareFormats(audio_format_t format1, audio_format_t format2) 242{ 243 // NOTE: AUDIO_FORMAT_INVALID is also considered not PCM and will be compared equal to any 244 // compressed format and better than any PCM format. This is by design of pickFormat() 245 if (!audio_is_linear_pcm(format1)) { 246 if (!audio_is_linear_pcm(format2)) { 247 return 0; 248 } 249 return 1; 250 } 251 if (!audio_is_linear_pcm(format2)) { 252 return -1; 253 } 254 255 int index1 = -1, index2 = -1; 256 for (size_t i = 0; 257 (i < ARRAY_SIZE(sPcmFormatCompareTable)) && ((index1 == -1) || (index2 == -1)); 258 i ++) { 259 if (sPcmFormatCompareTable[i] == format1) { 260 index1 = i; 261 } 262 if (sPcmFormatCompareTable[i] == format2) { 263 index2 = i; 264 } 265 } 266 // format1 not found => index1 < 0 => format2 > format1 267 // format2 not found => index2 < 0 => format2 < format1 268 return index1 - index2; 269} 270 271bool AudioPort::isBetterFormatMatch(audio_format_t newFormat, 272 audio_format_t currentFormat, 273 audio_format_t targetFormat) 274{ 275 if (newFormat == currentFormat) { 276 return false; 277 } 278 if (currentFormat == AUDIO_FORMAT_INVALID) { 279 return true; 280 } 281 if (newFormat == targetFormat) { 282 return true; 283 } 284 int currentDiffBytes = (int)audio_bytes_per_sample(targetFormat) - 285 audio_bytes_per_sample(currentFormat); 286 int newDiffBytes = (int)audio_bytes_per_sample(targetFormat) - 287 audio_bytes_per_sample(newFormat); 288 289 if (abs(newDiffBytes) < abs(currentDiffBytes)) { 290 return true; 291 } else if (abs(newDiffBytes) == abs(currentDiffBytes)) { 292 return (newDiffBytes >= 0); 293 } 294 return false; 295} 296 297void AudioPort::pickAudioProfile(uint32_t &samplingRate, 298 audio_channel_mask_t &channelMask, 299 audio_format_t &format) const 300{ 301 format = AUDIO_FORMAT_DEFAULT; 302 samplingRate = 0; 303 channelMask = AUDIO_CHANNEL_NONE; 304 305 // special case for uninitialized dynamic profile 306 if (!mProfiles.hasValidProfile()) { 307 return; 308 } 309 audio_format_t bestFormat = sPcmFormatCompareTable[ARRAY_SIZE(sPcmFormatCompareTable) - 1]; 310 // For mixed output and inputs, use best mixer output format. 311 // Do not limit format otherwise 312 if ((mType != AUDIO_PORT_TYPE_MIX) || isDirectOutput()) { 313 bestFormat = AUDIO_FORMAT_INVALID; 314 } 315 316 for (size_t i = 0; i < mProfiles.size(); i ++) { 317 if (!mProfiles[i]->isValid()) { 318 continue; 319 } 320 audio_format_t formatToCompare = mProfiles[i]->getFormat(); 321 if ((compareFormats(formatToCompare, format) > 0) && 322 (compareFormats(formatToCompare, bestFormat) <= 0)) { 323 uint32_t pickedSamplingRate = 0; 324 audio_channel_mask_t pickedChannelMask = AUDIO_CHANNEL_NONE; 325 pickChannelMask(pickedChannelMask, mProfiles[i]->getChannels()); 326 pickSamplingRate(pickedSamplingRate, mProfiles[i]->getSampleRates()); 327 328 if (formatToCompare != AUDIO_FORMAT_DEFAULT && pickedChannelMask != AUDIO_CHANNEL_NONE 329 && pickedSamplingRate != 0) { 330 format = formatToCompare; 331 channelMask = pickedChannelMask; 332 samplingRate = pickedSamplingRate; 333 // TODO: shall we return on the first one or still trying to pick a better Profile? 334 } 335 } 336 } 337 ALOGV("%s Port[nm:%s] profile rate=%d, format=%d, channels=%d", __FUNCTION__, mName.string(), 338 samplingRate, channelMask, format); 339} 340 341status_t AudioPort::checkGain(const struct audio_gain_config *gainConfig, int index) const 342{ 343 if (index < 0 || (size_t)index >= mGains.size()) { 344 return BAD_VALUE; 345 } 346 return mGains[index]->checkConfig(gainConfig); 347} 348 349void AudioPort::dump(int fd, int spaces, bool verbose) const 350{ 351 const size_t SIZE = 256; 352 char buffer[SIZE]; 353 String8 result; 354 355 if (!mName.isEmpty()) { 356 snprintf(buffer, SIZE, "%*s- name: %s\n", spaces, "", mName.string()); 357 result.append(buffer); 358 write(fd, result.string(), result.size()); 359 } 360 if (verbose) { 361 mProfiles.dump(fd, spaces); 362 363 if (mGains.size() != 0) { 364 snprintf(buffer, SIZE, "%*s- gains:\n", spaces, ""); 365 result = buffer; 366 write(fd, result.string(), result.size()); 367 for (size_t i = 0; i < mGains.size(); i++) { 368 mGains[i]->dump(fd, spaces + 2, i); 369 } 370 } 371 } 372} 373 374void AudioPort::log(const char* indent) const 375{ 376 ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.string(), mType, mRole); 377} 378 379// --- AudioPortConfig class implementation 380 381AudioPortConfig::AudioPortConfig() 382{ 383 mSamplingRate = 0; 384 mChannelMask = AUDIO_CHANNEL_NONE; 385 mFormat = AUDIO_FORMAT_INVALID; 386 mGain.index = -1; 387} 388 389status_t AudioPortConfig::applyAudioPortConfig(const struct audio_port_config *config, 390 struct audio_port_config *backupConfig) 391{ 392 struct audio_port_config localBackupConfig; 393 status_t status = NO_ERROR; 394 395 localBackupConfig.config_mask = config->config_mask; 396 toAudioPortConfig(&localBackupConfig); 397 398 sp<AudioPort> audioport = getAudioPort(); 399 if (audioport == 0) { 400 status = NO_INIT; 401 goto exit; 402 } 403 status = audioport->checkExactAudioProfile(config->sample_rate, 404 config->channel_mask, 405 config->format); 406 if (status != NO_ERROR) { 407 goto exit; 408 } 409 if (config->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) { 410 mSamplingRate = config->sample_rate; 411 } 412 if (config->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) { 413 mChannelMask = config->channel_mask; 414 } 415 if (config->config_mask & AUDIO_PORT_CONFIG_FORMAT) { 416 mFormat = config->format; 417 } 418 if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) { 419 status = audioport->checkGain(&config->gain, config->gain.index); 420 if (status != NO_ERROR) { 421 goto exit; 422 } 423 mGain = config->gain; 424 } 425 426exit: 427 if (status != NO_ERROR) { 428 applyAudioPortConfig(&localBackupConfig); 429 } 430 if (backupConfig != NULL) { 431 *backupConfig = localBackupConfig; 432 } 433 return status; 434} 435 436void AudioPortConfig::toAudioPortConfig(struct audio_port_config *dstConfig, 437 const struct audio_port_config *srcConfig) const 438{ 439 if (dstConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) { 440 dstConfig->sample_rate = mSamplingRate; 441 if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE)) { 442 dstConfig->sample_rate = srcConfig->sample_rate; 443 } 444 } else { 445 dstConfig->sample_rate = 0; 446 } 447 if (dstConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) { 448 dstConfig->channel_mask = mChannelMask; 449 if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK)) { 450 dstConfig->channel_mask = srcConfig->channel_mask; 451 } 452 } else { 453 dstConfig->channel_mask = AUDIO_CHANNEL_NONE; 454 } 455 if (dstConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT) { 456 dstConfig->format = mFormat; 457 if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT)) { 458 dstConfig->format = srcConfig->format; 459 } 460 } else { 461 dstConfig->format = AUDIO_FORMAT_INVALID; 462 } 463 sp<AudioPort> audioport = getAudioPort(); 464 if ((dstConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) && audioport != NULL) { 465 dstConfig->gain = mGain; 466 if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) 467 && audioport->checkGain(&srcConfig->gain, srcConfig->gain.index) == OK) { 468 dstConfig->gain = srcConfig->gain; 469 } 470 } else { 471 dstConfig->gain.index = -1; 472 } 473 if (dstConfig->gain.index != -1) { 474 dstConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN; 475 } else { 476 dstConfig->config_mask &= ~AUDIO_PORT_CONFIG_GAIN; 477 } 478} 479 480}; // namespace android 481