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