AudioPort.cpp revision f27e2fbfc3284c00a60fa68edc51d436f75b1e32
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 <media/AudioResamplerPublic.h> 20#include "AudioPort.h" 21#include "HwModule.h" 22#include "AudioGain.h" 23#include "ConfigParsingUtils.h" 24#include "audio_policy_conf.h" 25#include <policy.h> 26 27namespace android { 28 29int32_t volatile AudioPort::mNextUniqueId = 1; 30 31// --- AudioPort class implementation 32 33AudioPort::AudioPort(const String8& name, audio_port_type_t type, 34 audio_port_role_t role) : 35 mName(name), mType(type), mRole(role), mFlags(0) 36{ 37 mUseInChannelMask = ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) || 38 ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK)); 39} 40 41void AudioPort::attach(const sp<HwModule>& module) 42{ 43 mModule = module; 44} 45 46audio_port_handle_t AudioPort::getNextUniqueId() 47{ 48 return static_cast<audio_port_handle_t>(android_atomic_inc(&mNextUniqueId)); 49} 50 51audio_module_handle_t AudioPort::getModuleHandle() const 52{ 53 if (mModule == 0) { 54 return 0; 55 } 56 return mModule->mHandle; 57} 58 59uint32_t AudioPort::getModuleVersion() const 60{ 61 if (mModule == 0) { 62 return 0; 63 } 64 return mModule->mHalVersion; 65} 66 67const char *AudioPort::getModuleName() const 68{ 69 if (mModule == 0) { 70 return ""; 71 } 72 return mModule->mName; 73} 74 75void AudioPort::toAudioPort(struct audio_port *port) const 76{ 77 port->role = mRole; 78 port->type = mType; 79 strlcpy(port->name, mName, AUDIO_PORT_MAX_NAME_LEN); 80 unsigned int i; 81 for (i = 0; i < mSamplingRates.size() && i < AUDIO_PORT_MAX_SAMPLING_RATES; i++) { 82 if (mSamplingRates[i] != 0) { 83 port->sample_rates[i] = mSamplingRates[i]; 84 } 85 } 86 port->num_sample_rates = i; 87 for (i = 0; i < mChannelMasks.size() && i < AUDIO_PORT_MAX_CHANNEL_MASKS; i++) { 88 if (mChannelMasks[i] != 0) { 89 port->channel_masks[i] = mChannelMasks[i]; 90 } 91 } 92 port->num_channel_masks = i; 93 for (i = 0; i < mFormats.size() && i < AUDIO_PORT_MAX_FORMATS; i++) { 94 if (mFormats[i] != 0) { 95 port->formats[i] = mFormats[i]; 96 } 97 } 98 port->num_formats = i; 99 100 ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size()); 101 102 for (i = 0; i < mGains.size() && i < AUDIO_PORT_MAX_GAINS; i++) { 103 port->gains[i] = mGains[i]->mGain; 104 } 105 port->num_gains = i; 106} 107 108void AudioPort::importAudioPort(const sp<AudioPort> port) { 109 for (size_t k = 0 ; k < port->mSamplingRates.size() ; k++) { 110 const uint32_t rate = port->mSamplingRates.itemAt(k); 111 if (rate != 0) { // skip "dynamic" rates 112 bool hasRate = false; 113 for (size_t l = 0 ; l < mSamplingRates.size() ; l++) { 114 if (rate == mSamplingRates.itemAt(l)) { 115 hasRate = true; 116 break; 117 } 118 } 119 if (!hasRate) { // never import a sampling rate twice 120 mSamplingRates.add(rate); 121 } 122 } 123 } 124 for (size_t k = 0 ; k < port->mChannelMasks.size() ; k++) { 125 const audio_channel_mask_t mask = port->mChannelMasks.itemAt(k); 126 if (mask != 0) { // skip "dynamic" masks 127 bool hasMask = false; 128 for (size_t l = 0 ; l < mChannelMasks.size() ; l++) { 129 if (mask == mChannelMasks.itemAt(l)) { 130 hasMask = true; 131 break; 132 } 133 } 134 if (!hasMask) { // never import a channel mask twice 135 mChannelMasks.add(mask); 136 } 137 } 138 } 139 for (size_t k = 0 ; k < port->mFormats.size() ; k++) { 140 const audio_format_t format = port->mFormats.itemAt(k); 141 if (format != 0) { // skip "dynamic" formats 142 bool hasFormat = false; 143 for (size_t l = 0 ; l < mFormats.size() ; l++) { 144 if (format == mFormats.itemAt(l)) { 145 hasFormat = true; 146 break; 147 } 148 } 149 if (!hasFormat) { // never import a channel mask twice 150 mFormats.add(format); 151 } 152 } 153 } 154 for (size_t k = 0 ; k < port->mGains.size() ; k++) { 155 sp<AudioGain> gain = port->mGains.itemAt(k); 156 if (gain != 0) { 157 bool hasGain = false; 158 for (size_t l = 0 ; l < mGains.size() ; l++) { 159 if (gain == mGains.itemAt(l)) { 160 hasGain = true; 161 break; 162 } 163 } 164 if (!hasGain) { // never import a gain twice 165 mGains.add(gain); 166 } 167 } 168 } 169} 170 171void AudioPort::clearCapabilities() { 172 mChannelMasks.clear(); 173 mFormats.clear(); 174 mSamplingRates.clear(); 175 mGains.clear(); 176} 177 178void AudioPort::loadSamplingRates(char *name) 179{ 180 char *str = strtok(name, "|"); 181 182 // by convention, "0' in the first entry in mSamplingRates indicates the supported sampling 183 // rates should be read from the output stream after it is opened for the first time 184 if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) { 185 mSamplingRates.add(0); 186 return; 187 } 188 189 while (str != NULL) { 190 uint32_t rate = atoi(str); 191 if (rate != 0) { 192 ALOGV("loadSamplingRates() adding rate %d", rate); 193 mSamplingRates.add(rate); 194 } 195 str = strtok(NULL, "|"); 196 } 197} 198 199void AudioPort::loadFormats(char *name) 200{ 201 char *str = strtok(name, "|"); 202 203 // by convention, "0' in the first entry in mFormats indicates the supported formats 204 // should be read from the output stream after it is opened for the first time 205 if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) { 206 mFormats.add(AUDIO_FORMAT_DEFAULT); 207 return; 208 } 209 210 while (str != NULL) { 211 audio_format_t format = (audio_format_t)ConfigParsingUtils::stringToEnum(sFormatNameToEnumTable, 212 ARRAY_SIZE(sFormatNameToEnumTable), 213 str); 214 if (format != AUDIO_FORMAT_DEFAULT) { 215 mFormats.add(format); 216 } 217 str = strtok(NULL, "|"); 218 } 219 mFormats.sort(compareFormatsGoodToBad); 220} 221 222void AudioPort::loadInChannels(char *name) 223{ 224 const char *str = strtok(name, "|"); 225 226 ALOGV("loadInChannels() %s", name); 227 228 if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) { 229 mChannelMasks.add(0); 230 return; 231 } 232 233 while (str != NULL) { 234 audio_channel_mask_t channelMask = 235 (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sInChannelsNameToEnumTable, 236 ARRAY_SIZE(sInChannelsNameToEnumTable), 237 str); 238 if (channelMask == 0) { // if not found, check the channel index table 239 channelMask = (audio_channel_mask_t) 240 ConfigParsingUtils::stringToEnum(sIndexChannelsNameToEnumTable, 241 ARRAY_SIZE(sIndexChannelsNameToEnumTable), 242 str); 243 } 244 if (channelMask != 0) { 245 ALOGV("loadInChannels() adding channelMask %#x", channelMask); 246 mChannelMasks.add(channelMask); 247 } 248 str = strtok(NULL, "|"); 249 } 250} 251 252void AudioPort::loadOutChannels(char *name) 253{ 254 const char *str = strtok(name, "|"); 255 256 ALOGV("loadOutChannels() %s", name); 257 258 // by convention, "0' in the first entry in mChannelMasks indicates the supported channel 259 // masks should be read from the output stream after it is opened for the first time 260 if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) { 261 mChannelMasks.add(0); 262 return; 263 } 264 265 while (str != NULL) { 266 audio_channel_mask_t channelMask = 267 (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sOutChannelsNameToEnumTable, 268 ARRAY_SIZE(sOutChannelsNameToEnumTable), 269 str); 270 if (channelMask != 0) { 271 mChannelMasks.add(channelMask); 272 } 273 str = strtok(NULL, "|"); 274 } 275 return; 276} 277 278audio_gain_mode_t AudioPort::loadGainMode(char *name) 279{ 280 const char *str = strtok(name, "|"); 281 282 ALOGV("loadGainMode() %s", name); 283 audio_gain_mode_t mode = 0; 284 while (str != NULL) { 285 mode |= (audio_gain_mode_t)ConfigParsingUtils::stringToEnum(sGainModeNameToEnumTable, 286 ARRAY_SIZE(sGainModeNameToEnumTable), 287 str); 288 str = strtok(NULL, "|"); 289 } 290 return mode; 291} 292 293void AudioPort::loadGain(cnode *root, int index) 294{ 295 cnode *node = root->first_child; 296 297 sp<AudioGain> gain = new AudioGain(index, mUseInChannelMask); 298 299 while (node) { 300 if (strcmp(node->name, GAIN_MODE) == 0) { 301 gain->mGain.mode = loadGainMode((char *)node->value); 302 } else if (strcmp(node->name, GAIN_CHANNELS) == 0) { 303 if (mUseInChannelMask) { 304 gain->mGain.channel_mask = 305 (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sInChannelsNameToEnumTable, 306 ARRAY_SIZE(sInChannelsNameToEnumTable), 307 (char *)node->value); 308 } else { 309 gain->mGain.channel_mask = 310 (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sOutChannelsNameToEnumTable, 311 ARRAY_SIZE(sOutChannelsNameToEnumTable), 312 (char *)node->value); 313 } 314 } else if (strcmp(node->name, GAIN_MIN_VALUE) == 0) { 315 gain->mGain.min_value = atoi((char *)node->value); 316 } else if (strcmp(node->name, GAIN_MAX_VALUE) == 0) { 317 gain->mGain.max_value = atoi((char *)node->value); 318 } else if (strcmp(node->name, GAIN_DEFAULT_VALUE) == 0) { 319 gain->mGain.default_value = atoi((char *)node->value); 320 } else if (strcmp(node->name, GAIN_STEP_VALUE) == 0) { 321 gain->mGain.step_value = atoi((char *)node->value); 322 } else if (strcmp(node->name, GAIN_MIN_RAMP_MS) == 0) { 323 gain->mGain.min_ramp_ms = atoi((char *)node->value); 324 } else if (strcmp(node->name, GAIN_MAX_RAMP_MS) == 0) { 325 gain->mGain.max_ramp_ms = atoi((char *)node->value); 326 } 327 node = node->next; 328 } 329 330 ALOGV("loadGain() adding new gain mode %08x channel mask %08x min mB %d max mB %d", 331 gain->mGain.mode, gain->mGain.channel_mask, gain->mGain.min_value, gain->mGain.max_value); 332 333 if (gain->mGain.mode == 0) { 334 return; 335 } 336 mGains.add(gain); 337} 338 339void AudioPort::loadGains(cnode *root) 340{ 341 cnode *node = root->first_child; 342 int index = 0; 343 while (node) { 344 ALOGV("loadGains() loading gain %s", node->name); 345 loadGain(node, index++); 346 node = node->next; 347 } 348} 349 350status_t AudioPort::checkExactSamplingRate(uint32_t samplingRate) const 351{ 352 if (mSamplingRates.isEmpty()) { 353 return NO_ERROR; 354 } 355 356 for (size_t i = 0; i < mSamplingRates.size(); i ++) { 357 if (mSamplingRates[i] == samplingRate) { 358 return NO_ERROR; 359 } 360 } 361 return BAD_VALUE; 362} 363 364status_t AudioPort::checkCompatibleSamplingRate(uint32_t samplingRate, 365 uint32_t *updatedSamplingRate) const 366{ 367 if (mSamplingRates.isEmpty()) { 368 if (updatedSamplingRate != NULL) { 369 *updatedSamplingRate = samplingRate; 370 } 371 return NO_ERROR; 372 } 373 374 // Search for the closest supported sampling rate that is above (preferred) 375 // or below (acceptable) the desired sampling rate, within a permitted ratio. 376 // The sampling rates do not need to be sorted in ascending order. 377 ssize_t maxBelow = -1; 378 ssize_t minAbove = -1; 379 uint32_t candidate; 380 for (size_t i = 0; i < mSamplingRates.size(); i++) { 381 candidate = mSamplingRates[i]; 382 if (candidate == samplingRate) { 383 if (updatedSamplingRate != NULL) { 384 *updatedSamplingRate = candidate; 385 } 386 return NO_ERROR; 387 } 388 // candidate < desired 389 if (candidate < samplingRate) { 390 if (maxBelow < 0 || candidate > mSamplingRates[maxBelow]) { 391 maxBelow = i; 392 } 393 // candidate > desired 394 } else { 395 if (minAbove < 0 || candidate < mSamplingRates[minAbove]) { 396 minAbove = i; 397 } 398 } 399 } 400 401 // Prefer to down-sample from a higher sampling rate, as we get the desired frequency spectrum. 402 if (minAbove >= 0) { 403 candidate = mSamplingRates[minAbove]; 404 if (candidate / AUDIO_RESAMPLER_DOWN_RATIO_MAX <= samplingRate) { 405 if (updatedSamplingRate != NULL) { 406 *updatedSamplingRate = candidate; 407 } 408 return NO_ERROR; 409 } 410 } 411 // But if we have to up-sample from a lower sampling rate, that's OK. 412 if (maxBelow >= 0) { 413 candidate = mSamplingRates[maxBelow]; 414 if (candidate * AUDIO_RESAMPLER_UP_RATIO_MAX >= samplingRate) { 415 if (updatedSamplingRate != NULL) { 416 *updatedSamplingRate = candidate; 417 } 418 return NO_ERROR; 419 } 420 } 421 // leave updatedSamplingRate unmodified 422 return BAD_VALUE; 423} 424 425status_t AudioPort::checkExactChannelMask(audio_channel_mask_t channelMask) const 426{ 427 if (mChannelMasks.isEmpty()) { 428 return NO_ERROR; 429 } 430 431 for (size_t i = 0; i < mChannelMasks.size(); i++) { 432 if (mChannelMasks[i] == channelMask) { 433 return NO_ERROR; 434 } 435 } 436 return BAD_VALUE; 437} 438 439status_t AudioPort::checkCompatibleChannelMask(audio_channel_mask_t channelMask, 440 audio_channel_mask_t *updatedChannelMask) const 441{ 442 if (mChannelMasks.isEmpty()) { 443 if (updatedChannelMask != NULL) { 444 *updatedChannelMask = channelMask; 445 } 446 return NO_ERROR; 447 } 448 449 const bool isRecordThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK; 450 const bool isIndex = audio_channel_mask_get_representation(channelMask) 451 == AUDIO_CHANNEL_REPRESENTATION_INDEX; 452 int bestMatch = 0; 453 for (size_t i = 0; i < mChannelMasks.size(); i ++) { 454 audio_channel_mask_t supported = mChannelMasks[i]; 455 if (supported == channelMask) { 456 // Exact matches always taken. 457 if (updatedChannelMask != NULL) { 458 *updatedChannelMask = channelMask; 459 } 460 return NO_ERROR; 461 } 462 463 // AUDIO_CHANNEL_NONE (value: 0) is used for dynamic channel support 464 if (isRecordThread && supported != AUDIO_CHANNEL_NONE) { 465 // Approximate (best) match: 466 // The match score measures how well the supported channel mask matches the 467 // desired mask, where increasing-is-better. 468 // 469 // TODO: Some tweaks may be needed. 470 // Should be a static function of the data processing library. 471 // 472 // In priority: 473 // match score = 1000 if legacy channel conversion equivalent (always prefer this) 474 // OR 475 // match score += 100 if the channel mask representations match 476 // match score += number of channels matched. 477 // 478 // If there are no matched channels, the mask may still be accepted 479 // but the playback or record will be silent. 480 const bool isSupportedIndex = (audio_channel_mask_get_representation(supported) 481 == AUDIO_CHANNEL_REPRESENTATION_INDEX); 482 int match; 483 if (isIndex && isSupportedIndex) { 484 // index equivalence 485 match = 100 + __builtin_popcount( 486 audio_channel_mask_get_bits(channelMask) 487 & audio_channel_mask_get_bits(supported)); 488 } else if (isIndex && !isSupportedIndex) { 489 const uint32_t equivalentBits = 490 (1 << audio_channel_count_from_in_mask(supported)) - 1 ; 491 match = __builtin_popcount( 492 audio_channel_mask_get_bits(channelMask) & equivalentBits); 493 } else if (!isIndex && isSupportedIndex) { 494 const uint32_t equivalentBits = 495 (1 << audio_channel_count_from_in_mask(channelMask)) - 1; 496 match = __builtin_popcount( 497 equivalentBits & audio_channel_mask_get_bits(supported)); 498 } else { 499 // positional equivalence 500 match = 100 + __builtin_popcount( 501 audio_channel_mask_get_bits(channelMask) 502 & audio_channel_mask_get_bits(supported)); 503 switch (supported) { 504 case AUDIO_CHANNEL_IN_FRONT_BACK: 505 case AUDIO_CHANNEL_IN_STEREO: 506 if (channelMask == AUDIO_CHANNEL_IN_MONO) { 507 match = 1000; 508 } 509 break; 510 case AUDIO_CHANNEL_IN_MONO: 511 if (channelMask == AUDIO_CHANNEL_IN_FRONT_BACK 512 || channelMask == AUDIO_CHANNEL_IN_STEREO) { 513 match = 1000; 514 } 515 break; 516 default: 517 break; 518 } 519 } 520 if (match > bestMatch) { 521 bestMatch = match; 522 if (updatedChannelMask != NULL) { 523 *updatedChannelMask = supported; 524 } else { 525 return NO_ERROR; // any match will do in this case. 526 } 527 } 528 } 529 } 530 return bestMatch > 0 ? NO_ERROR : BAD_VALUE; 531} 532 533status_t AudioPort::checkExactFormat(audio_format_t format) const 534{ 535 if (mFormats.isEmpty()) { 536 return NO_ERROR; 537 } 538 539 for (size_t i = 0; i < mFormats.size(); i ++) { 540 if (mFormats[i] == format) { 541 return NO_ERROR; 542 } 543 } 544 return BAD_VALUE; 545} 546 547status_t AudioPort::checkCompatibleFormat(audio_format_t format, audio_format_t *updatedFormat) 548 const 549{ 550 if (mFormats.isEmpty()) { 551 if (updatedFormat != NULL) { 552 *updatedFormat = format; 553 } 554 return NO_ERROR; 555 } 556 557 const bool checkInexact = // when port is input and format is linear pcm 558 mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK 559 && audio_is_linear_pcm(format); 560 561 for (size_t i = 0; i < mFormats.size(); ++i) { 562 if (mFormats[i] == format || 563 (checkInexact && audio_is_linear_pcm(mFormats[i]))) { 564 // for inexact checks we take the first linear pcm format since 565 // mFormats is sorted from best PCM format to worst PCM format. 566 if (updatedFormat != NULL) { 567 *updatedFormat = mFormats[i]; 568 } 569 return NO_ERROR; 570 } 571 } 572 return BAD_VALUE; 573} 574 575uint32_t AudioPort::pickSamplingRate() const 576{ 577 // special case for uninitialized dynamic profile 578 if (mSamplingRates.size() == 1 && mSamplingRates[0] == 0) { 579 return 0; 580 } 581 582 // For direct outputs, pick minimum sampling rate: this helps ensuring that the 583 // channel count / sampling rate combination chosen will be supported by the connected 584 // sink 585 if ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) && 586 (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))) { 587 uint32_t samplingRate = UINT_MAX; 588 for (size_t i = 0; i < mSamplingRates.size(); i ++) { 589 if ((mSamplingRates[i] < samplingRate) && (mSamplingRates[i] > 0)) { 590 samplingRate = mSamplingRates[i]; 591 } 592 } 593 return (samplingRate == UINT_MAX) ? 0 : samplingRate; 594 } 595 596 uint32_t samplingRate = 0; 597 uint32_t maxRate = MAX_MIXER_SAMPLING_RATE; 598 599 // For mixed output and inputs, use max mixer sampling rates. Do not 600 // limit sampling rate otherwise 601 if (mType != AUDIO_PORT_TYPE_MIX) { 602 maxRate = UINT_MAX; 603 } 604 for (size_t i = 0; i < mSamplingRates.size(); i ++) { 605 if ((mSamplingRates[i] > samplingRate) && (mSamplingRates[i] <= maxRate)) { 606 samplingRate = mSamplingRates[i]; 607 } 608 } 609 return samplingRate; 610} 611 612audio_channel_mask_t AudioPort::pickChannelMask() const 613{ 614 // special case for uninitialized dynamic profile 615 if (mChannelMasks.size() == 1 && mChannelMasks[0] == 0) { 616 return AUDIO_CHANNEL_NONE; 617 } 618 audio_channel_mask_t channelMask = AUDIO_CHANNEL_NONE; 619 620 // For direct outputs, pick minimum channel count: this helps ensuring that the 621 // channel count / sampling rate combination chosen will be supported by the connected 622 // sink 623 if ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) && 624 (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))) { 625 uint32_t channelCount = UINT_MAX; 626 for (size_t i = 0; i < mChannelMasks.size(); i ++) { 627 uint32_t cnlCount; 628 if (mUseInChannelMask) { 629 cnlCount = audio_channel_count_from_in_mask(mChannelMasks[i]); 630 } else { 631 cnlCount = audio_channel_count_from_out_mask(mChannelMasks[i]); 632 } 633 if ((cnlCount < channelCount) && (cnlCount > 0)) { 634 channelMask = mChannelMasks[i]; 635 channelCount = cnlCount; 636 } 637 } 638 return channelMask; 639 } 640 641 uint32_t channelCount = 0; 642 uint32_t maxCount = MAX_MIXER_CHANNEL_COUNT; 643 644 // For mixed output and inputs, use max mixer channel count. Do not 645 // limit channel count otherwise 646 if (mType != AUDIO_PORT_TYPE_MIX) { 647 maxCount = UINT_MAX; 648 } 649 for (size_t i = 0; i < mChannelMasks.size(); i ++) { 650 uint32_t cnlCount; 651 if (mUseInChannelMask) { 652 cnlCount = audio_channel_count_from_in_mask(mChannelMasks[i]); 653 } else { 654 cnlCount = audio_channel_count_from_out_mask(mChannelMasks[i]); 655 } 656 if ((cnlCount > channelCount) && (cnlCount <= maxCount)) { 657 channelMask = mChannelMasks[i]; 658 channelCount = cnlCount; 659 } 660 } 661 return channelMask; 662} 663 664/* format in order of increasing preference */ 665const audio_format_t AudioPort::sPcmFormatCompareTable[] = { 666 AUDIO_FORMAT_DEFAULT, 667 AUDIO_FORMAT_PCM_16_BIT, 668 AUDIO_FORMAT_PCM_8_24_BIT, 669 AUDIO_FORMAT_PCM_24_BIT_PACKED, 670 AUDIO_FORMAT_PCM_32_BIT, 671 AUDIO_FORMAT_PCM_FLOAT, 672}; 673 674int AudioPort::compareFormats(audio_format_t format1, 675 audio_format_t format2) 676{ 677 // NOTE: AUDIO_FORMAT_INVALID is also considered not PCM and will be compared equal to any 678 // compressed format and better than any PCM format. This is by design of pickFormat() 679 if (!audio_is_linear_pcm(format1)) { 680 if (!audio_is_linear_pcm(format2)) { 681 return 0; 682 } 683 return 1; 684 } 685 if (!audio_is_linear_pcm(format2)) { 686 return -1; 687 } 688 689 int index1 = -1, index2 = -1; 690 for (size_t i = 0; 691 (i < ARRAY_SIZE(sPcmFormatCompareTable)) && ((index1 == -1) || (index2 == -1)); 692 i ++) { 693 if (sPcmFormatCompareTable[i] == format1) { 694 index1 = i; 695 } 696 if (sPcmFormatCompareTable[i] == format2) { 697 index2 = i; 698 } 699 } 700 // format1 not found => index1 < 0 => format2 > format1 701 // format2 not found => index2 < 0 => format2 < format1 702 return index1 - index2; 703} 704 705audio_format_t AudioPort::pickFormat() const 706{ 707 // special case for uninitialized dynamic profile 708 if (mFormats.size() == 1 && mFormats[0] == 0) { 709 return AUDIO_FORMAT_DEFAULT; 710 } 711 712 audio_format_t format = AUDIO_FORMAT_DEFAULT; 713 audio_format_t bestFormat = 714 AudioPort::sPcmFormatCompareTable[ 715 ARRAY_SIZE(AudioPort::sPcmFormatCompareTable) - 1]; 716 // For mixed output and inputs, use best mixer output format. Do not 717 // limit format otherwise 718 if ((mType != AUDIO_PORT_TYPE_MIX) || 719 ((mRole == AUDIO_PORT_ROLE_SOURCE) && 720 (((mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) != 0)))) { 721 bestFormat = AUDIO_FORMAT_INVALID; 722 } 723 724 for (size_t i = 0; i < mFormats.size(); i ++) { 725 if ((compareFormats(mFormats[i], format) > 0) && 726 (compareFormats(mFormats[i], bestFormat) <= 0)) { 727 format = mFormats[i]; 728 } 729 } 730 return format; 731} 732 733status_t AudioPort::checkGain(const struct audio_gain_config *gainConfig, 734 int index) const 735{ 736 if (index < 0 || (size_t)index >= mGains.size()) { 737 return BAD_VALUE; 738 } 739 return mGains[index]->checkConfig(gainConfig); 740} 741 742void AudioPort::dump(int fd, int spaces) const 743{ 744 const size_t SIZE = 256; 745 char buffer[SIZE]; 746 String8 result; 747 748 if (mName.length() != 0) { 749 snprintf(buffer, SIZE, "%*s- name: %s\n", spaces, "", mName.string()); 750 result.append(buffer); 751 } 752 753 if (mSamplingRates.size() != 0) { 754 snprintf(buffer, SIZE, "%*s- sampling rates: ", spaces, ""); 755 result.append(buffer); 756 for (size_t i = 0; i < mSamplingRates.size(); i++) { 757 if (i == 0 && mSamplingRates[i] == 0) { 758 snprintf(buffer, SIZE, "Dynamic"); 759 } else { 760 snprintf(buffer, SIZE, "%d", mSamplingRates[i]); 761 } 762 result.append(buffer); 763 result.append(i == (mSamplingRates.size() - 1) ? "" : ", "); 764 } 765 result.append("\n"); 766 } 767 768 if (mChannelMasks.size() != 0) { 769 snprintf(buffer, SIZE, "%*s- channel masks: ", spaces, ""); 770 result.append(buffer); 771 for (size_t i = 0; i < mChannelMasks.size(); i++) { 772 ALOGV("AudioPort::dump mChannelMasks %zu %08x", i, mChannelMasks[i]); 773 774 if (i == 0 && mChannelMasks[i] == 0) { 775 snprintf(buffer, SIZE, "Dynamic"); 776 } else { 777 snprintf(buffer, SIZE, "0x%04x", mChannelMasks[i]); 778 } 779 result.append(buffer); 780 result.append(i == (mChannelMasks.size() - 1) ? "" : ", "); 781 } 782 result.append("\n"); 783 } 784 785 if (mFormats.size() != 0) { 786 snprintf(buffer, SIZE, "%*s- formats: ", spaces, ""); 787 result.append(buffer); 788 for (size_t i = 0; i < mFormats.size(); i++) { 789 const char *formatStr = ConfigParsingUtils::enumToString(sFormatNameToEnumTable, 790 ARRAY_SIZE(sFormatNameToEnumTable), 791 mFormats[i]); 792 if (i == 0 && strcmp(formatStr, "") == 0) { 793 snprintf(buffer, SIZE, "Dynamic"); 794 } else { 795 snprintf(buffer, SIZE, "%s", formatStr); 796 } 797 result.append(buffer); 798 result.append(i == (mFormats.size() - 1) ? "" : ", "); 799 } 800 result.append("\n"); 801 } 802 write(fd, result.string(), result.size()); 803 if (mGains.size() != 0) { 804 snprintf(buffer, SIZE, "%*s- gains:\n", spaces, ""); 805 write(fd, buffer, strlen(buffer) + 1); 806 for (size_t i = 0; i < mGains.size(); i++) { 807 mGains[i]->dump(fd, spaces + 2, i); 808 } 809 } 810} 811 812void AudioPort::log(const char* indent) const 813{ 814 ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.string(), mType, mRole); 815} 816 817// --- AudioPortConfig class implementation 818 819AudioPortConfig::AudioPortConfig() 820{ 821 mSamplingRate = 0; 822 mChannelMask = AUDIO_CHANNEL_NONE; 823 mFormat = AUDIO_FORMAT_INVALID; 824 mGain.index = -1; 825} 826 827status_t AudioPortConfig::applyAudioPortConfig( 828 const struct audio_port_config *config, 829 struct audio_port_config *backupConfig) 830{ 831 struct audio_port_config localBackupConfig; 832 status_t status = NO_ERROR; 833 834 localBackupConfig.config_mask = config->config_mask; 835 toAudioPortConfig(&localBackupConfig); 836 837 sp<AudioPort> audioport = getAudioPort(); 838 if (audioport == 0) { 839 status = NO_INIT; 840 goto exit; 841 } 842 if (config->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) { 843 status = audioport->checkExactSamplingRate(config->sample_rate); 844 if (status != NO_ERROR) { 845 goto exit; 846 } 847 mSamplingRate = config->sample_rate; 848 } 849 if (config->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) { 850 status = audioport->checkExactChannelMask(config->channel_mask); 851 if (status != NO_ERROR) { 852 goto exit; 853 } 854 mChannelMask = config->channel_mask; 855 } 856 if (config->config_mask & AUDIO_PORT_CONFIG_FORMAT) { 857 status = audioport->checkExactFormat(config->format); 858 if (status != NO_ERROR) { 859 goto exit; 860 } 861 mFormat = config->format; 862 } 863 if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) { 864 status = audioport->checkGain(&config->gain, config->gain.index); 865 if (status != NO_ERROR) { 866 goto exit; 867 } 868 mGain = config->gain; 869 } 870 871exit: 872 if (status != NO_ERROR) { 873 applyAudioPortConfig(&localBackupConfig); 874 } 875 if (backupConfig != NULL) { 876 *backupConfig = localBackupConfig; 877 } 878 return status; 879} 880 881void AudioPortConfig::toAudioPortConfig(struct audio_port_config *dstConfig, 882 const struct audio_port_config *srcConfig) const 883{ 884 if (dstConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) { 885 dstConfig->sample_rate = mSamplingRate; 886 if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE)) { 887 dstConfig->sample_rate = srcConfig->sample_rate; 888 } 889 } else { 890 dstConfig->sample_rate = 0; 891 } 892 if (dstConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) { 893 dstConfig->channel_mask = mChannelMask; 894 if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK)) { 895 dstConfig->channel_mask = srcConfig->channel_mask; 896 } 897 } else { 898 dstConfig->channel_mask = AUDIO_CHANNEL_NONE; 899 } 900 if (dstConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT) { 901 dstConfig->format = mFormat; 902 if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT)) { 903 dstConfig->format = srcConfig->format; 904 } 905 } else { 906 dstConfig->format = AUDIO_FORMAT_INVALID; 907 } 908 if (dstConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) { 909 dstConfig->gain = mGain; 910 if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_GAIN)) { 911 dstConfig->gain = srcConfig->gain; 912 } 913 } else { 914 dstConfig->gain.index = -1; 915 } 916 if (dstConfig->gain.index != -1) { 917 dstConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN; 918 } else { 919 dstConfig->config_mask &= ~AUDIO_PORT_CONFIG_GAIN; 920 } 921} 922 923}; // namespace android 924