AudioPort.cpp revision db4c031f518ae5806af73756273ff32cd8d0e4f8
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 format 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 // we sort from worst to best, so that AUDIO_FORMAT_DEFAULT is always the first entry. 220 // TODO: compareFormats could be a lambda to convert between pointer-to-format to format: 221 // [](const audio_format_t *format1, const audio_format_t *format2) { 222 // return compareFormats(*format1, *format2); 223 // } 224 mFormats.sort(compareFormats); 225} 226 227void AudioPort::loadInChannels(char *name) 228{ 229 const char *str = strtok(name, "|"); 230 231 ALOGV("loadInChannels() %s", name); 232 233 if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) { 234 mChannelMasks.add(0); 235 return; 236 } 237 238 while (str != NULL) { 239 audio_channel_mask_t channelMask = 240 (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sInChannelsNameToEnumTable, 241 ARRAY_SIZE(sInChannelsNameToEnumTable), 242 str); 243 if (channelMask == 0) { // if not found, check the channel index table 244 channelMask = (audio_channel_mask_t) 245 ConfigParsingUtils::stringToEnum(sIndexChannelsNameToEnumTable, 246 ARRAY_SIZE(sIndexChannelsNameToEnumTable), 247 str); 248 } 249 if (channelMask != 0) { 250 ALOGV("loadInChannels() adding channelMask %#x", channelMask); 251 mChannelMasks.add(channelMask); 252 } 253 str = strtok(NULL, "|"); 254 } 255} 256 257void AudioPort::loadOutChannels(char *name) 258{ 259 const char *str = strtok(name, "|"); 260 261 ALOGV("loadOutChannels() %s", name); 262 263 // by convention, "0' in the first entry in mChannelMasks indicates the supported channel 264 // masks should be read from the output stream after it is opened for the first time 265 if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) { 266 mChannelMasks.add(0); 267 return; 268 } 269 270 while (str != NULL) { 271 audio_channel_mask_t channelMask = 272 (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sOutChannelsNameToEnumTable, 273 ARRAY_SIZE(sOutChannelsNameToEnumTable), 274 str); 275 if (channelMask == 0) { // if not found, check the channel index table 276 channelMask = (audio_channel_mask_t) 277 ConfigParsingUtils::stringToEnum(sIndexChannelsNameToEnumTable, 278 ARRAY_SIZE(sIndexChannelsNameToEnumTable), 279 str); 280 } 281 if (channelMask != 0) { 282 mChannelMasks.add(channelMask); 283 } 284 str = strtok(NULL, "|"); 285 } 286 return; 287} 288 289audio_gain_mode_t AudioPort::loadGainMode(char *name) 290{ 291 const char *str = strtok(name, "|"); 292 293 ALOGV("loadGainMode() %s", name); 294 audio_gain_mode_t mode = 0; 295 while (str != NULL) { 296 mode |= (audio_gain_mode_t)ConfigParsingUtils::stringToEnum(sGainModeNameToEnumTable, 297 ARRAY_SIZE(sGainModeNameToEnumTable), 298 str); 299 str = strtok(NULL, "|"); 300 } 301 return mode; 302} 303 304void AudioPort::loadGain(cnode *root, int index) 305{ 306 cnode *node = root->first_child; 307 308 sp<AudioGain> gain = new AudioGain(index, mUseInChannelMask); 309 310 while (node) { 311 if (strcmp(node->name, GAIN_MODE) == 0) { 312 gain->mGain.mode = loadGainMode((char *)node->value); 313 } else if (strcmp(node->name, GAIN_CHANNELS) == 0) { 314 if (mUseInChannelMask) { 315 gain->mGain.channel_mask = 316 (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sInChannelsNameToEnumTable, 317 ARRAY_SIZE(sInChannelsNameToEnumTable), 318 (char *)node->value); 319 } else { 320 gain->mGain.channel_mask = 321 (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sOutChannelsNameToEnumTable, 322 ARRAY_SIZE(sOutChannelsNameToEnumTable), 323 (char *)node->value); 324 } 325 } else if (strcmp(node->name, GAIN_MIN_VALUE) == 0) { 326 gain->mGain.min_value = atoi((char *)node->value); 327 } else if (strcmp(node->name, GAIN_MAX_VALUE) == 0) { 328 gain->mGain.max_value = atoi((char *)node->value); 329 } else if (strcmp(node->name, GAIN_DEFAULT_VALUE) == 0) { 330 gain->mGain.default_value = atoi((char *)node->value); 331 } else if (strcmp(node->name, GAIN_STEP_VALUE) == 0) { 332 gain->mGain.step_value = atoi((char *)node->value); 333 } else if (strcmp(node->name, GAIN_MIN_RAMP_MS) == 0) { 334 gain->mGain.min_ramp_ms = atoi((char *)node->value); 335 } else if (strcmp(node->name, GAIN_MAX_RAMP_MS) == 0) { 336 gain->mGain.max_ramp_ms = atoi((char *)node->value); 337 } 338 node = node->next; 339 } 340 341 ALOGV("loadGain() adding new gain mode %08x channel mask %08x min mB %d max mB %d", 342 gain->mGain.mode, gain->mGain.channel_mask, gain->mGain.min_value, gain->mGain.max_value); 343 344 if (gain->mGain.mode == 0) { 345 return; 346 } 347 mGains.add(gain); 348} 349 350void AudioPort::loadGains(cnode *root) 351{ 352 cnode *node = root->first_child; 353 int index = 0; 354 while (node) { 355 ALOGV("loadGains() loading gain %s", node->name); 356 loadGain(node, index++); 357 node = node->next; 358 } 359} 360 361status_t AudioPort::checkExactSamplingRate(uint32_t samplingRate) const 362{ 363 if (mSamplingRates.isEmpty()) { 364 return NO_ERROR; 365 } 366 367 for (size_t i = 0; i < mSamplingRates.size(); i ++) { 368 if (mSamplingRates[i] == samplingRate) { 369 return NO_ERROR; 370 } 371 } 372 return BAD_VALUE; 373} 374 375status_t AudioPort::checkCompatibleSamplingRate(uint32_t samplingRate, 376 uint32_t *updatedSamplingRate) const 377{ 378 if (mSamplingRates.isEmpty()) { 379 if (updatedSamplingRate != NULL) { 380 *updatedSamplingRate = samplingRate; 381 } 382 return NO_ERROR; 383 } 384 385 // Search for the closest supported sampling rate that is above (preferred) 386 // or below (acceptable) the desired sampling rate, within a permitted ratio. 387 // The sampling rates do not need to be sorted in ascending order. 388 ssize_t maxBelow = -1; 389 ssize_t minAbove = -1; 390 uint32_t candidate; 391 for (size_t i = 0; i < mSamplingRates.size(); i++) { 392 candidate = mSamplingRates[i]; 393 if (candidate == samplingRate) { 394 if (updatedSamplingRate != NULL) { 395 *updatedSamplingRate = candidate; 396 } 397 return NO_ERROR; 398 } 399 // candidate < desired 400 if (candidate < samplingRate) { 401 if (maxBelow < 0 || candidate > mSamplingRates[maxBelow]) { 402 maxBelow = i; 403 } 404 // candidate > desired 405 } else { 406 if (minAbove < 0 || candidate < mSamplingRates[minAbove]) { 407 minAbove = i; 408 } 409 } 410 } 411 412 // Prefer to down-sample from a higher sampling rate, as we get the desired frequency spectrum. 413 if (minAbove >= 0) { 414 candidate = mSamplingRates[minAbove]; 415 if (candidate / AUDIO_RESAMPLER_DOWN_RATIO_MAX <= samplingRate) { 416 if (updatedSamplingRate != NULL) { 417 *updatedSamplingRate = candidate; 418 } 419 return NO_ERROR; 420 } 421 } 422 // But if we have to up-sample from a lower sampling rate, that's OK. 423 if (maxBelow >= 0) { 424 candidate = mSamplingRates[maxBelow]; 425 if (candidate * AUDIO_RESAMPLER_UP_RATIO_MAX >= samplingRate) { 426 if (updatedSamplingRate != NULL) { 427 *updatedSamplingRate = candidate; 428 } 429 return NO_ERROR; 430 } 431 } 432 // leave updatedSamplingRate unmodified 433 return BAD_VALUE; 434} 435 436status_t AudioPort::checkExactChannelMask(audio_channel_mask_t channelMask) const 437{ 438 if (mChannelMasks.isEmpty()) { 439 return NO_ERROR; 440 } 441 442 for (size_t i = 0; i < mChannelMasks.size(); i++) { 443 if (mChannelMasks[i] == channelMask) { 444 return NO_ERROR; 445 } 446 } 447 return BAD_VALUE; 448} 449 450status_t AudioPort::checkCompatibleChannelMask(audio_channel_mask_t channelMask, 451 audio_channel_mask_t *updatedChannelMask) const 452{ 453 if (mChannelMasks.isEmpty()) { 454 if (updatedChannelMask != NULL) { 455 *updatedChannelMask = channelMask; 456 } 457 return NO_ERROR; 458 } 459 460 const bool isRecordThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK; 461 const bool isIndex = audio_channel_mask_get_representation(channelMask) 462 == AUDIO_CHANNEL_REPRESENTATION_INDEX; 463 int bestMatch = 0; 464 for (size_t i = 0; i < mChannelMasks.size(); i ++) { 465 audio_channel_mask_t supported = mChannelMasks[i]; 466 if (supported == channelMask) { 467 // Exact matches always taken. 468 if (updatedChannelMask != NULL) { 469 *updatedChannelMask = channelMask; 470 } 471 return NO_ERROR; 472 } 473 474 // AUDIO_CHANNEL_NONE (value: 0) is used for dynamic channel support 475 if (isRecordThread && supported != AUDIO_CHANNEL_NONE) { 476 // Approximate (best) match: 477 // The match score measures how well the supported channel mask matches the 478 // desired mask, where increasing-is-better. 479 // 480 // TODO: Some tweaks may be needed. 481 // Should be a static function of the data processing library. 482 // 483 // In priority: 484 // match score = 1000 if legacy channel conversion equivalent (always prefer this) 485 // OR 486 // match score += 100 if the channel mask representations match 487 // match score += number of channels matched. 488 // 489 // If there are no matched channels, the mask may still be accepted 490 // but the playback or record will be silent. 491 const bool isSupportedIndex = (audio_channel_mask_get_representation(supported) 492 == AUDIO_CHANNEL_REPRESENTATION_INDEX); 493 int match; 494 if (isIndex && isSupportedIndex) { 495 // index equivalence 496 match = 100 + __builtin_popcount( 497 audio_channel_mask_get_bits(channelMask) 498 & audio_channel_mask_get_bits(supported)); 499 } else if (isIndex && !isSupportedIndex) { 500 const uint32_t equivalentBits = 501 (1 << audio_channel_count_from_in_mask(supported)) - 1 ; 502 match = __builtin_popcount( 503 audio_channel_mask_get_bits(channelMask) & equivalentBits); 504 } else if (!isIndex && isSupportedIndex) { 505 const uint32_t equivalentBits = 506 (1 << audio_channel_count_from_in_mask(channelMask)) - 1; 507 match = __builtin_popcount( 508 equivalentBits & audio_channel_mask_get_bits(supported)); 509 } else { 510 // positional equivalence 511 match = 100 + __builtin_popcount( 512 audio_channel_mask_get_bits(channelMask) 513 & audio_channel_mask_get_bits(supported)); 514 switch (supported) { 515 case AUDIO_CHANNEL_IN_FRONT_BACK: 516 case AUDIO_CHANNEL_IN_STEREO: 517 if (channelMask == AUDIO_CHANNEL_IN_MONO) { 518 match = 1000; 519 } 520 break; 521 case AUDIO_CHANNEL_IN_MONO: 522 if (channelMask == AUDIO_CHANNEL_IN_FRONT_BACK 523 || channelMask == AUDIO_CHANNEL_IN_STEREO) { 524 match = 1000; 525 } 526 break; 527 default: 528 break; 529 } 530 } 531 if (match > bestMatch) { 532 bestMatch = match; 533 if (updatedChannelMask != NULL) { 534 *updatedChannelMask = supported; 535 } else { 536 return NO_ERROR; // any match will do in this case. 537 } 538 } 539 } 540 } 541 return bestMatch > 0 ? NO_ERROR : BAD_VALUE; 542} 543 544status_t AudioPort::checkExactFormat(audio_format_t format) const 545{ 546 if (mFormats.isEmpty()) { 547 return NO_ERROR; 548 } 549 550 for (size_t i = 0; i < mFormats.size(); i ++) { 551 if (mFormats[i] == format) { 552 return NO_ERROR; 553 } 554 } 555 return BAD_VALUE; 556} 557 558status_t AudioPort::checkCompatibleFormat(audio_format_t format, audio_format_t *updatedFormat) 559 const 560{ 561 if (mFormats.isEmpty()) { 562 if (updatedFormat != NULL) { 563 *updatedFormat = format; 564 } 565 return NO_ERROR; 566 } 567 568 const bool checkInexact = // when port is input and format is linear pcm 569 mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK 570 && audio_is_linear_pcm(format); 571 572 // iterate from best format to worst format (reverse order) 573 for (ssize_t i = mFormats.size() - 1; i >= 0 ; --i) { 574 if (mFormats[i] == format || 575 (checkInexact 576 && mFormats[i] != AUDIO_FORMAT_DEFAULT 577 && audio_is_linear_pcm(mFormats[i]))) { 578 // for inexact checks we take the first linear pcm format due to sorting. 579 if (updatedFormat != NULL) { 580 *updatedFormat = mFormats[i]; 581 } 582 return NO_ERROR; 583 } 584 } 585 return BAD_VALUE; 586} 587 588uint32_t AudioPort::pickSamplingRate() const 589{ 590 // special case for uninitialized dynamic profile 591 if (mSamplingRates.size() == 1 && mSamplingRates[0] == 0) { 592 return 0; 593 } 594 595 // For direct outputs, pick minimum sampling rate: this helps ensuring that the 596 // channel count / sampling rate combination chosen will be supported by the connected 597 // sink 598 if ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) && 599 (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))) { 600 uint32_t samplingRate = UINT_MAX; 601 for (size_t i = 0; i < mSamplingRates.size(); i ++) { 602 if ((mSamplingRates[i] < samplingRate) && (mSamplingRates[i] > 0)) { 603 samplingRate = mSamplingRates[i]; 604 } 605 } 606 return (samplingRate == UINT_MAX) ? 0 : samplingRate; 607 } 608 609 uint32_t samplingRate = 0; 610 uint32_t maxRate = MAX_MIXER_SAMPLING_RATE; 611 612 // For mixed output and inputs, use max mixer sampling rates. Do not 613 // limit sampling rate otherwise 614 // For inputs, also see checkCompatibleSamplingRate(). 615 if (mType != AUDIO_PORT_TYPE_MIX) { 616 maxRate = UINT_MAX; 617 } 618 // TODO: should mSamplingRates[] be ordered in terms of our preference 619 // and we return the first (and hence most preferred) match? This is of concern if 620 // we want to choose 96kHz over 192kHz for USB driver stability or resource constraints. 621 for (size_t i = 0; i < mSamplingRates.size(); i ++) { 622 if ((mSamplingRates[i] > samplingRate) && (mSamplingRates[i] <= maxRate)) { 623 samplingRate = mSamplingRates[i]; 624 } 625 } 626 return samplingRate; 627} 628 629audio_channel_mask_t AudioPort::pickChannelMask() const 630{ 631 // special case for uninitialized dynamic profile 632 if (mChannelMasks.size() == 1 && mChannelMasks[0] == 0) { 633 return AUDIO_CHANNEL_NONE; 634 } 635 audio_channel_mask_t channelMask = AUDIO_CHANNEL_NONE; 636 637 // For direct outputs, pick minimum channel count: this helps ensuring that the 638 // channel count / sampling rate combination chosen will be supported by the connected 639 // sink 640 if ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) && 641 (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))) { 642 uint32_t channelCount = UINT_MAX; 643 for (size_t i = 0; i < mChannelMasks.size(); i ++) { 644 uint32_t cnlCount; 645 if (mUseInChannelMask) { 646 cnlCount = audio_channel_count_from_in_mask(mChannelMasks[i]); 647 } else { 648 cnlCount = audio_channel_count_from_out_mask(mChannelMasks[i]); 649 } 650 if ((cnlCount < channelCount) && (cnlCount > 0)) { 651 channelMask = mChannelMasks[i]; 652 channelCount = cnlCount; 653 } 654 } 655 return channelMask; 656 } 657 658 uint32_t channelCount = 0; 659 uint32_t maxCount = MAX_MIXER_CHANNEL_COUNT; 660 661 // For mixed output and inputs, use max mixer channel count. Do not 662 // limit channel count otherwise 663 if (mType != AUDIO_PORT_TYPE_MIX) { 664 maxCount = UINT_MAX; 665 } 666 for (size_t i = 0; i < mChannelMasks.size(); i ++) { 667 uint32_t cnlCount; 668 if (mUseInChannelMask) { 669 cnlCount = audio_channel_count_from_in_mask(mChannelMasks[i]); 670 } else { 671 cnlCount = audio_channel_count_from_out_mask(mChannelMasks[i]); 672 } 673 if ((cnlCount > channelCount) && (cnlCount <= maxCount)) { 674 channelMask = mChannelMasks[i]; 675 channelCount = cnlCount; 676 } 677 } 678 return channelMask; 679} 680 681/* format in order of increasing preference */ 682const audio_format_t AudioPort::sPcmFormatCompareTable[] = { 683 AUDIO_FORMAT_DEFAULT, 684 AUDIO_FORMAT_PCM_16_BIT, 685 AUDIO_FORMAT_PCM_8_24_BIT, 686 AUDIO_FORMAT_PCM_24_BIT_PACKED, 687 AUDIO_FORMAT_PCM_32_BIT, 688 AUDIO_FORMAT_PCM_FLOAT, 689}; 690 691int AudioPort::compareFormats(audio_format_t format1, 692 audio_format_t format2) 693{ 694 // NOTE: AUDIO_FORMAT_INVALID is also considered not PCM and will be compared equal to any 695 // compressed format and better than any PCM format. This is by design of pickFormat() 696 if (!audio_is_linear_pcm(format1)) { 697 if (!audio_is_linear_pcm(format2)) { 698 return 0; 699 } 700 return 1; 701 } 702 if (!audio_is_linear_pcm(format2)) { 703 return -1; 704 } 705 706 int index1 = -1, index2 = -1; 707 for (size_t i = 0; 708 (i < ARRAY_SIZE(sPcmFormatCompareTable)) && ((index1 == -1) || (index2 == -1)); 709 i ++) { 710 if (sPcmFormatCompareTable[i] == format1) { 711 index1 = i; 712 } 713 if (sPcmFormatCompareTable[i] == format2) { 714 index2 = i; 715 } 716 } 717 // format1 not found => index1 < 0 => format2 > format1 718 // format2 not found => index2 < 0 => format2 < format1 719 return index1 - index2; 720} 721 722audio_format_t AudioPort::pickFormat() const 723{ 724 // special case for uninitialized dynamic profile 725 if (mFormats.size() == 1 && mFormats[0] == 0) { 726 return AUDIO_FORMAT_DEFAULT; 727 } 728 729 audio_format_t format = AUDIO_FORMAT_DEFAULT; 730 audio_format_t bestFormat = 731 AudioPort::sPcmFormatCompareTable[ 732 ARRAY_SIZE(AudioPort::sPcmFormatCompareTable) - 1]; 733 // For mixed output and inputs, use best mixer output format. Do not 734 // limit format otherwise 735 if ((mType != AUDIO_PORT_TYPE_MIX) || 736 ((mRole == AUDIO_PORT_ROLE_SOURCE) && 737 (((mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) != 0)))) { 738 bestFormat = AUDIO_FORMAT_INVALID; 739 } 740 741 for (size_t i = 0; i < mFormats.size(); i ++) { 742 if ((compareFormats(mFormats[i], format) > 0) && 743 (compareFormats(mFormats[i], bestFormat) <= 0)) { 744 format = mFormats[i]; 745 } 746 } 747 return format; 748} 749 750status_t AudioPort::checkGain(const struct audio_gain_config *gainConfig, 751 int index) const 752{ 753 if (index < 0 || (size_t)index >= mGains.size()) { 754 return BAD_VALUE; 755 } 756 return mGains[index]->checkConfig(gainConfig); 757} 758 759void AudioPort::dump(int fd, int spaces) const 760{ 761 const size_t SIZE = 256; 762 char buffer[SIZE]; 763 String8 result; 764 765 if (mName.length() != 0) { 766 snprintf(buffer, SIZE, "%*s- name: %s\n", spaces, "", mName.string()); 767 result.append(buffer); 768 } 769 770 if (mSamplingRates.size() != 0) { 771 snprintf(buffer, SIZE, "%*s- sampling rates: ", spaces, ""); 772 result.append(buffer); 773 for (size_t i = 0; i < mSamplingRates.size(); i++) { 774 if (i == 0 && mSamplingRates[i] == 0) { 775 snprintf(buffer, SIZE, "Dynamic"); 776 } else { 777 snprintf(buffer, SIZE, "%d", mSamplingRates[i]); 778 } 779 result.append(buffer); 780 result.append(i == (mSamplingRates.size() - 1) ? "" : ", "); 781 } 782 result.append("\n"); 783 } 784 785 if (mChannelMasks.size() != 0) { 786 snprintf(buffer, SIZE, "%*s- channel masks: ", spaces, ""); 787 result.append(buffer); 788 for (size_t i = 0; i < mChannelMasks.size(); i++) { 789 ALOGV("AudioPort::dump mChannelMasks %zu %08x", i, mChannelMasks[i]); 790 791 if (i == 0 && mChannelMasks[i] == 0) { 792 snprintf(buffer, SIZE, "Dynamic"); 793 } else { 794 snprintf(buffer, SIZE, "0x%04x", mChannelMasks[i]); 795 } 796 result.append(buffer); 797 result.append(i == (mChannelMasks.size() - 1) ? "" : ", "); 798 } 799 result.append("\n"); 800 } 801 802 if (mFormats.size() != 0) { 803 snprintf(buffer, SIZE, "%*s- formats: ", spaces, ""); 804 result.append(buffer); 805 for (size_t i = 0; i < mFormats.size(); i++) { 806 const char *formatStr = ConfigParsingUtils::enumToString(sFormatNameToEnumTable, 807 ARRAY_SIZE(sFormatNameToEnumTable), 808 mFormats[i]); 809 const bool isEmptyStr = formatStr[0] == 0; 810 if (i == 0 && isEmptyStr) { 811 snprintf(buffer, SIZE, "Dynamic"); 812 } else { 813 if (isEmptyStr) { 814 snprintf(buffer, SIZE, "%#x", mFormats[i]); 815 } else { 816 snprintf(buffer, SIZE, "%s", formatStr); 817 } 818 } 819 result.append(buffer); 820 result.append(i == (mFormats.size() - 1) ? "" : ", "); 821 } 822 result.append("\n"); 823 } 824 write(fd, result.string(), result.size()); 825 if (mGains.size() != 0) { 826 snprintf(buffer, SIZE, "%*s- gains:\n", spaces, ""); 827 write(fd, buffer, strlen(buffer) + 1); 828 for (size_t i = 0; i < mGains.size(); i++) { 829 mGains[i]->dump(fd, spaces + 2, i); 830 } 831 } 832} 833 834void AudioPort::log(const char* indent) const 835{ 836 ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.string(), mType, mRole); 837} 838 839// --- AudioPortConfig class implementation 840 841AudioPortConfig::AudioPortConfig() 842{ 843 mSamplingRate = 0; 844 mChannelMask = AUDIO_CHANNEL_NONE; 845 mFormat = AUDIO_FORMAT_INVALID; 846 mGain.index = -1; 847} 848 849status_t AudioPortConfig::applyAudioPortConfig( 850 const struct audio_port_config *config, 851 struct audio_port_config *backupConfig) 852{ 853 struct audio_port_config localBackupConfig; 854 status_t status = NO_ERROR; 855 856 localBackupConfig.config_mask = config->config_mask; 857 toAudioPortConfig(&localBackupConfig); 858 859 sp<AudioPort> audioport = getAudioPort(); 860 if (audioport == 0) { 861 status = NO_INIT; 862 goto exit; 863 } 864 if (config->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) { 865 status = audioport->checkExactSamplingRate(config->sample_rate); 866 if (status != NO_ERROR) { 867 goto exit; 868 } 869 mSamplingRate = config->sample_rate; 870 } 871 if (config->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) { 872 status = audioport->checkExactChannelMask(config->channel_mask); 873 if (status != NO_ERROR) { 874 goto exit; 875 } 876 mChannelMask = config->channel_mask; 877 } 878 if (config->config_mask & AUDIO_PORT_CONFIG_FORMAT) { 879 status = audioport->checkExactFormat(config->format); 880 if (status != NO_ERROR) { 881 goto exit; 882 } 883 mFormat = config->format; 884 } 885 if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) { 886 status = audioport->checkGain(&config->gain, config->gain.index); 887 if (status != NO_ERROR) { 888 goto exit; 889 } 890 mGain = config->gain; 891 } 892 893exit: 894 if (status != NO_ERROR) { 895 applyAudioPortConfig(&localBackupConfig); 896 } 897 if (backupConfig != NULL) { 898 *backupConfig = localBackupConfig; 899 } 900 return status; 901} 902 903void AudioPortConfig::toAudioPortConfig(struct audio_port_config *dstConfig, 904 const struct audio_port_config *srcConfig) const 905{ 906 if (dstConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) { 907 dstConfig->sample_rate = mSamplingRate; 908 if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE)) { 909 dstConfig->sample_rate = srcConfig->sample_rate; 910 } 911 } else { 912 dstConfig->sample_rate = 0; 913 } 914 if (dstConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) { 915 dstConfig->channel_mask = mChannelMask; 916 if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK)) { 917 dstConfig->channel_mask = srcConfig->channel_mask; 918 } 919 } else { 920 dstConfig->channel_mask = AUDIO_CHANNEL_NONE; 921 } 922 if (dstConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT) { 923 dstConfig->format = mFormat; 924 if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT)) { 925 dstConfig->format = srcConfig->format; 926 } 927 } else { 928 dstConfig->format = AUDIO_FORMAT_INVALID; 929 } 930 if (dstConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) { 931 dstConfig->gain = mGain; 932 if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_GAIN)) { 933 dstConfig->gain = srcConfig->gain; 934 } 935 } else { 936 dstConfig->gain.index = -1; 937 } 938 if (dstConfig->gain.index != -1) { 939 dstConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN; 940 } else { 941 dstConfig->config_mask &= ~AUDIO_PORT_CONFIG_GAIN; 942 } 943} 944 945}; // namespace android 946