AudioPort.cpp revision a8ecc2c72ca26389bd6b0162181d60aaeaca8149
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 "TypeConverter.h" 21#include "AudioPort.h" 22#include "HwModule.h" 23#include "AudioGain.h" 24#include <policy.h> 25 26#ifndef ARRAY_SIZE 27#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 28#endif 29 30namespace android { 31 32int32_t volatile AudioPort::mNextUniqueId = 1; 33 34// --- AudioPort class implementation 35void AudioPort::attach(const sp<HwModule>& module) 36{ 37 mModule = module; 38} 39 40audio_port_handle_t AudioPort::getNextUniqueId() 41{ 42 return static_cast<audio_port_handle_t>(android_atomic_inc(&mNextUniqueId)); 43} 44 45audio_module_handle_t AudioPort::getModuleHandle() const 46{ 47 if (mModule == 0) { 48 return 0; 49 } 50 return mModule->mHandle; 51} 52 53uint32_t AudioPort::getModuleVersion() const 54{ 55 if (mModule == 0) { 56 return 0; 57 } 58 return mModule->getHalVersion(); 59} 60 61const char *AudioPort::getModuleName() const 62{ 63 if (mModule == 0) { 64 return "invalid module"; 65 } 66 return mModule->getName(); 67} 68 69void AudioPort::toAudioPort(struct audio_port *port) const 70{ 71 port->role = mRole; 72 port->type = mType; 73 strlcpy(port->name, mName, AUDIO_PORT_MAX_NAME_LEN); 74 unsigned int i; 75 for (i = 0; i < mSamplingRates.size() && i < AUDIO_PORT_MAX_SAMPLING_RATES; i++) { 76 if (mSamplingRates[i] != 0) { 77 port->sample_rates[i] = mSamplingRates[i]; 78 } 79 } 80 port->num_sample_rates = i; 81 for (i = 0; i < mChannelMasks.size() && i < AUDIO_PORT_MAX_CHANNEL_MASKS; i++) { 82 if (mChannelMasks[i] != 0) { 83 port->channel_masks[i] = mChannelMasks[i]; 84 } 85 } 86 port->num_channel_masks = i; 87 for (i = 0; i < mFormats.size() && i < AUDIO_PORT_MAX_FORMATS; i++) { 88 if (mFormats[i] != 0) { 89 port->formats[i] = mFormats[i]; 90 } 91 } 92 port->num_formats = i; 93 94 ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size()); 95 96 for (i = 0; i < mGains.size() && i < AUDIO_PORT_MAX_GAINS; i++) { 97 port->gains[i] = mGains[i]->getGain(); 98 } 99 port->num_gains = i; 100} 101 102void AudioPort::importAudioPort(const sp<AudioPort> port) { 103 for (size_t k = 0 ; k < port->mSamplingRates.size() ; k++) { 104 const uint32_t rate = port->mSamplingRates.itemAt(k); 105 if (rate != 0) { // skip "dynamic" rates 106 bool hasRate = false; 107 for (size_t l = 0 ; l < mSamplingRates.size() ; l++) { 108 if (rate == mSamplingRates.itemAt(l)) { 109 hasRate = true; 110 break; 111 } 112 } 113 if (!hasRate) { // never import a sampling rate twice 114 mSamplingRates.add(rate); 115 } 116 } 117 } 118 for (size_t k = 0 ; k < port->mChannelMasks.size() ; k++) { 119 const audio_channel_mask_t mask = port->mChannelMasks.itemAt(k); 120 if (mask != 0) { // skip "dynamic" masks 121 bool hasMask = false; 122 for (size_t l = 0 ; l < mChannelMasks.size() ; l++) { 123 if (mask == mChannelMasks.itemAt(l)) { 124 hasMask = true; 125 break; 126 } 127 } 128 if (!hasMask) { // never import a channel mask twice 129 mChannelMasks.add(mask); 130 } 131 } 132 } 133 for (size_t k = 0 ; k < port->mFormats.size() ; k++) { 134 const audio_format_t format = port->mFormats.itemAt(k); 135 if (format != 0) { // skip "dynamic" formats 136 bool hasFormat = false; 137 for (size_t l = 0 ; l < mFormats.size() ; l++) { 138 if (format == mFormats.itemAt(l)) { 139 hasFormat = true; 140 break; 141 } 142 } 143 if (!hasFormat) { // never import a format twice 144 mFormats.add(format); 145 } 146 } 147 } 148} 149 150void AudioPort::clearCapabilities() { 151 mChannelMasks.clear(); 152 mFormats.clear(); 153 mSamplingRates.clear(); 154} 155 156void AudioPort::setSupportedFormats(const Vector <audio_format_t> &formats) 157{ 158 mFormats = formats; 159 // we sort from worst to best, so that AUDIO_FORMAT_DEFAULT is always the first entry. 160 // TODO: compareFormats could be a lambda to convert between pointer-to-format to format: 161 // [](const audio_format_t *format1, const audio_format_t *format2) { 162 // return compareFormats(*format1, *format2); 163 // } 164 mFormats.sort(compareFormats); 165} 166 167status_t AudioPort::checkExactSamplingRate(uint32_t samplingRate) const 168{ 169 if (mSamplingRates.isEmpty()) { 170 return NO_ERROR; 171 } 172 173 for (size_t i = 0; i < mSamplingRates.size(); i ++) { 174 if (mSamplingRates[i] == samplingRate) { 175 return NO_ERROR; 176 } 177 } 178 return BAD_VALUE; 179} 180 181status_t AudioPort::checkCompatibleSamplingRate(uint32_t samplingRate, 182 uint32_t *updatedSamplingRate) const 183{ 184 if (mSamplingRates.isEmpty()) { 185 if (updatedSamplingRate != NULL) { 186 *updatedSamplingRate = samplingRate; 187 } 188 return NO_ERROR; 189 } 190 191 // Search for the closest supported sampling rate that is above (preferred) 192 // or below (acceptable) the desired sampling rate, within a permitted ratio. 193 // The sampling rates do not need to be sorted in ascending order. 194 ssize_t maxBelow = -1; 195 ssize_t minAbove = -1; 196 uint32_t candidate; 197 for (size_t i = 0; i < mSamplingRates.size(); i++) { 198 candidate = mSamplingRates[i]; 199 if (candidate == samplingRate) { 200 if (updatedSamplingRate != NULL) { 201 *updatedSamplingRate = candidate; 202 } 203 return NO_ERROR; 204 } 205 // candidate < desired 206 if (candidate < samplingRate) { 207 if (maxBelow < 0 || candidate > mSamplingRates[maxBelow]) { 208 maxBelow = i; 209 } 210 // candidate > desired 211 } else { 212 if (minAbove < 0 || candidate < mSamplingRates[minAbove]) { 213 minAbove = i; 214 } 215 } 216 } 217 218 // Prefer to down-sample from a higher sampling rate, as we get the desired frequency spectrum. 219 if (minAbove >= 0) { 220 candidate = mSamplingRates[minAbove]; 221 if (candidate / AUDIO_RESAMPLER_DOWN_RATIO_MAX <= samplingRate) { 222 if (updatedSamplingRate != NULL) { 223 *updatedSamplingRate = candidate; 224 } 225 return NO_ERROR; 226 } 227 } 228 // But if we have to up-sample from a lower sampling rate, that's OK. 229 if (maxBelow >= 0) { 230 candidate = mSamplingRates[maxBelow]; 231 if (candidate * AUDIO_RESAMPLER_UP_RATIO_MAX >= samplingRate) { 232 if (updatedSamplingRate != NULL) { 233 *updatedSamplingRate = candidate; 234 } 235 return NO_ERROR; 236 } 237 } 238 // leave updatedSamplingRate unmodified 239 return BAD_VALUE; 240} 241 242status_t AudioPort::checkExactChannelMask(audio_channel_mask_t channelMask) const 243{ 244 if (mChannelMasks.isEmpty()) { 245 return NO_ERROR; 246 } 247 248 for (size_t i = 0; i < mChannelMasks.size(); i++) { 249 if (mChannelMasks[i] == channelMask) { 250 return NO_ERROR; 251 } 252 } 253 return BAD_VALUE; 254} 255 256status_t AudioPort::checkCompatibleChannelMask(audio_channel_mask_t channelMask, 257 audio_channel_mask_t *updatedChannelMask) const 258{ 259 if (mChannelMasks.isEmpty()) { 260 if (updatedChannelMask != NULL) { 261 *updatedChannelMask = channelMask; 262 } 263 return NO_ERROR; 264 } 265 266 const bool isRecordThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK; 267 const bool isIndex = audio_channel_mask_get_representation(channelMask) 268 == AUDIO_CHANNEL_REPRESENTATION_INDEX; 269 int bestMatch = 0; 270 for (size_t i = 0; i < mChannelMasks.size(); i ++) { 271 audio_channel_mask_t supported = mChannelMasks[i]; 272 if (supported == channelMask) { 273 // Exact matches always taken. 274 if (updatedChannelMask != NULL) { 275 *updatedChannelMask = channelMask; 276 } 277 return NO_ERROR; 278 } 279 280 // AUDIO_CHANNEL_NONE (value: 0) is used for dynamic channel support 281 if (isRecordThread && supported != AUDIO_CHANNEL_NONE) { 282 // Approximate (best) match: 283 // The match score measures how well the supported channel mask matches the 284 // desired mask, where increasing-is-better. 285 // 286 // TODO: Some tweaks may be needed. 287 // Should be a static function of the data processing library. 288 // 289 // In priority: 290 // match score = 1000 if legacy channel conversion equivalent (always prefer this) 291 // OR 292 // match score += 100 if the channel mask representations match 293 // match score += number of channels matched. 294 // 295 // If there are no matched channels, the mask may still be accepted 296 // but the playback or record will be silent. 297 const bool isSupportedIndex = (audio_channel_mask_get_representation(supported) 298 == AUDIO_CHANNEL_REPRESENTATION_INDEX); 299 int match; 300 if (isIndex && isSupportedIndex) { 301 // index equivalence 302 match = 100 + __builtin_popcount( 303 audio_channel_mask_get_bits(channelMask) 304 & audio_channel_mask_get_bits(supported)); 305 } else if (isIndex && !isSupportedIndex) { 306 const uint32_t equivalentBits = 307 (1 << audio_channel_count_from_in_mask(supported)) - 1 ; 308 match = __builtin_popcount( 309 audio_channel_mask_get_bits(channelMask) & equivalentBits); 310 } else if (!isIndex && isSupportedIndex) { 311 const uint32_t equivalentBits = 312 (1 << audio_channel_count_from_in_mask(channelMask)) - 1; 313 match = __builtin_popcount( 314 equivalentBits & audio_channel_mask_get_bits(supported)); 315 } else { 316 // positional equivalence 317 match = 100 + __builtin_popcount( 318 audio_channel_mask_get_bits(channelMask) 319 & audio_channel_mask_get_bits(supported)); 320 switch (supported) { 321 case AUDIO_CHANNEL_IN_FRONT_BACK: 322 case AUDIO_CHANNEL_IN_STEREO: 323 if (channelMask == AUDIO_CHANNEL_IN_MONO) { 324 match = 1000; 325 } 326 break; 327 case AUDIO_CHANNEL_IN_MONO: 328 if (channelMask == AUDIO_CHANNEL_IN_FRONT_BACK 329 || channelMask == AUDIO_CHANNEL_IN_STEREO) { 330 match = 1000; 331 } 332 break; 333 default: 334 break; 335 } 336 } 337 if (match > bestMatch) { 338 bestMatch = match; 339 if (updatedChannelMask != NULL) { 340 *updatedChannelMask = supported; 341 } else { 342 return NO_ERROR; // any match will do in this case. 343 } 344 } 345 } 346 } 347 return bestMatch > 0 ? NO_ERROR : BAD_VALUE; 348} 349 350status_t AudioPort::checkExactFormat(audio_format_t format) const 351{ 352 if (mFormats.isEmpty()) { 353 return NO_ERROR; 354 } 355 356 for (size_t i = 0; i < mFormats.size(); i ++) { 357 if (mFormats[i] == format) { 358 return NO_ERROR; 359 } 360 } 361 return BAD_VALUE; 362} 363 364status_t AudioPort::checkCompatibleFormat(audio_format_t format, audio_format_t *updatedFormat) 365 const 366{ 367 if (mFormats.isEmpty()) { 368 if (updatedFormat != NULL) { 369 *updatedFormat = format; 370 } 371 return NO_ERROR; 372 } 373 374 const bool checkInexact = // when port is input and format is linear pcm 375 mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK 376 && audio_is_linear_pcm(format); 377 378 // iterate from best format to worst format (reverse order) 379 for (ssize_t i = mFormats.size() - 1; i >= 0 ; --i) { 380 if (mFormats[i] == format || 381 (checkInexact 382 && mFormats[i] != AUDIO_FORMAT_DEFAULT 383 && audio_is_linear_pcm(mFormats[i]))) { 384 // for inexact checks we take the first linear pcm format due to sorting. 385 if (updatedFormat != NULL) { 386 *updatedFormat = mFormats[i]; 387 } 388 return NO_ERROR; 389 } 390 } 391 return BAD_VALUE; 392} 393 394uint32_t AudioPort::pickSamplingRate() const 395{ 396 // special case for uninitialized dynamic profile 397 if (mSamplingRates.size() == 1 && mSamplingRates[0] == 0) { 398 return 0; 399 } 400 401 // For direct outputs, pick minimum sampling rate: this helps ensuring that the 402 // channel count / sampling rate combination chosen will be supported by the connected 403 // sink 404 if ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) && 405 (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))) { 406 uint32_t samplingRate = UINT_MAX; 407 for (size_t i = 0; i < mSamplingRates.size(); i ++) { 408 if ((mSamplingRates[i] < samplingRate) && (mSamplingRates[i] > 0)) { 409 samplingRate = mSamplingRates[i]; 410 } 411 } 412 return (samplingRate == UINT_MAX) ? 0 : samplingRate; 413 } 414 415 uint32_t samplingRate = 0; 416 uint32_t maxRate = MAX_MIXER_SAMPLING_RATE; 417 418 // For mixed output and inputs, use max mixer sampling rates. Do not 419 // limit sampling rate otherwise 420 // For inputs, also see checkCompatibleSamplingRate(). 421 if (mType != AUDIO_PORT_TYPE_MIX) { 422 maxRate = UINT_MAX; 423 } 424 // TODO: should mSamplingRates[] be ordered in terms of our preference 425 // and we return the first (and hence most preferred) match? This is of concern if 426 // we want to choose 96kHz over 192kHz for USB driver stability or resource constraints. 427 for (size_t i = 0; i < mSamplingRates.size(); i ++) { 428 if ((mSamplingRates[i] > samplingRate) && (mSamplingRates[i] <= maxRate)) { 429 samplingRate = mSamplingRates[i]; 430 } 431 } 432 return samplingRate; 433} 434 435audio_channel_mask_t AudioPort::pickChannelMask() const 436{ 437 // special case for uninitialized dynamic profile 438 if (mChannelMasks.size() == 1 && mChannelMasks[0] == 0) { 439 return AUDIO_CHANNEL_NONE; 440 } 441 audio_channel_mask_t channelMask = AUDIO_CHANNEL_NONE; 442 443 // For direct outputs, pick minimum channel count: this helps ensuring that the 444 // channel count / sampling rate combination chosen will be supported by the connected 445 // sink 446 if ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) && 447 (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))) { 448 uint32_t channelCount = UINT_MAX; 449 for (size_t i = 0; i < mChannelMasks.size(); i ++) { 450 uint32_t cnlCount; 451 if (useInputChannelMask()) { 452 cnlCount = audio_channel_count_from_in_mask(mChannelMasks[i]); 453 } else { 454 cnlCount = audio_channel_count_from_out_mask(mChannelMasks[i]); 455 } 456 if ((cnlCount < channelCount) && (cnlCount > 0)) { 457 channelMask = mChannelMasks[i]; 458 channelCount = cnlCount; 459 } 460 } 461 return channelMask; 462 } 463 464 uint32_t channelCount = 0; 465 uint32_t maxCount = MAX_MIXER_CHANNEL_COUNT; 466 467 // For mixed output and inputs, use max mixer channel count. Do not 468 // limit channel count otherwise 469 if (mType != AUDIO_PORT_TYPE_MIX) { 470 maxCount = UINT_MAX; 471 } 472 for (size_t i = 0; i < mChannelMasks.size(); i ++) { 473 uint32_t cnlCount; 474 if (useInputChannelMask()) { 475 cnlCount = audio_channel_count_from_in_mask(mChannelMasks[i]); 476 } else { 477 cnlCount = audio_channel_count_from_out_mask(mChannelMasks[i]); 478 } 479 if ((cnlCount > channelCount) && (cnlCount <= maxCount)) { 480 channelMask = mChannelMasks[i]; 481 channelCount = cnlCount; 482 } 483 } 484 return channelMask; 485} 486 487/* format in order of increasing preference */ 488const audio_format_t AudioPort::sPcmFormatCompareTable[] = { 489 AUDIO_FORMAT_DEFAULT, 490 AUDIO_FORMAT_PCM_16_BIT, 491 AUDIO_FORMAT_PCM_8_24_BIT, 492 AUDIO_FORMAT_PCM_24_BIT_PACKED, 493 AUDIO_FORMAT_PCM_32_BIT, 494 AUDIO_FORMAT_PCM_FLOAT, 495}; 496 497int AudioPort::compareFormats(audio_format_t format1, 498 audio_format_t format2) 499{ 500 // NOTE: AUDIO_FORMAT_INVALID is also considered not PCM and will be compared equal to any 501 // compressed format and better than any PCM format. This is by design of pickFormat() 502 if (!audio_is_linear_pcm(format1)) { 503 if (!audio_is_linear_pcm(format2)) { 504 return 0; 505 } 506 return 1; 507 } 508 if (!audio_is_linear_pcm(format2)) { 509 return -1; 510 } 511 512 int index1 = -1, index2 = -1; 513 for (size_t i = 0; 514 (i < ARRAY_SIZE(sPcmFormatCompareTable)) && ((index1 == -1) || (index2 == -1)); 515 i ++) { 516 if (sPcmFormatCompareTable[i] == format1) { 517 index1 = i; 518 } 519 if (sPcmFormatCompareTable[i] == format2) { 520 index2 = i; 521 } 522 } 523 // format1 not found => index1 < 0 => format2 > format1 524 // format2 not found => index2 < 0 => format2 < format1 525 return index1 - index2; 526} 527 528audio_format_t AudioPort::pickFormat() const 529{ 530 // special case for uninitialized dynamic profile 531 if (mFormats.size() == 1 && mFormats[0] == 0) { 532 return AUDIO_FORMAT_DEFAULT; 533 } 534 535 audio_format_t format = AUDIO_FORMAT_DEFAULT; 536 audio_format_t bestFormat = 537 AudioPort::sPcmFormatCompareTable[ 538 ARRAY_SIZE(AudioPort::sPcmFormatCompareTable) - 1]; 539 // For mixed output and inputs, use best mixer output format. Do not 540 // limit format otherwise 541 if ((mType != AUDIO_PORT_TYPE_MIX) || 542 ((mRole == AUDIO_PORT_ROLE_SOURCE) && 543 (((mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) != 0)))) { 544 bestFormat = AUDIO_FORMAT_INVALID; 545 } 546 547 for (size_t i = 0; i < mFormats.size(); i ++) { 548 if ((compareFormats(mFormats[i], format) > 0) && 549 (compareFormats(mFormats[i], bestFormat) <= 0)) { 550 format = mFormats[i]; 551 } 552 } 553 return format; 554} 555 556status_t AudioPort::checkGain(const struct audio_gain_config *gainConfig, 557 int index) const 558{ 559 if (index < 0 || (size_t)index >= mGains.size()) { 560 return BAD_VALUE; 561 } 562 return mGains[index]->checkConfig(gainConfig); 563} 564 565void AudioPort::dump(int fd, int spaces) const 566{ 567 const size_t SIZE = 256; 568 char buffer[SIZE]; 569 String8 result; 570 571 if (mName.length() != 0) { 572 snprintf(buffer, SIZE, "%*s- name: %s\n", spaces, "", mName.string()); 573 result.append(buffer); 574 } 575 576 if (mSamplingRates.size() != 0) { 577 snprintf(buffer, SIZE, "%*s- sampling rates: ", spaces, ""); 578 result.append(buffer); 579 for (size_t i = 0; i < mSamplingRates.size(); i++) { 580 if (i == 0 && mSamplingRates[i] == 0) { 581 snprintf(buffer, SIZE, "Dynamic"); 582 } else { 583 snprintf(buffer, SIZE, "%d", mSamplingRates[i]); 584 } 585 result.append(buffer); 586 result.append(i == (mSamplingRates.size() - 1) ? "" : ", "); 587 } 588 result.append("\n"); 589 } 590 591 if (mChannelMasks.size() != 0) { 592 snprintf(buffer, SIZE, "%*s- channel masks: ", spaces, ""); 593 result.append(buffer); 594 for (size_t i = 0; i < mChannelMasks.size(); i++) { 595 ALOGV("AudioPort::dump mChannelMasks %zu %08x", i, mChannelMasks[i]); 596 597 if (i == 0 && mChannelMasks[i] == 0) { 598 snprintf(buffer, SIZE, "Dynamic"); 599 } else { 600 snprintf(buffer, SIZE, "0x%04x", mChannelMasks[i]); 601 } 602 result.append(buffer); 603 result.append(i == (mChannelMasks.size() - 1) ? "" : ", "); 604 } 605 result.append("\n"); 606 } 607 608 if (mFormats.size() != 0) { 609 snprintf(buffer, SIZE, "%*s- formats: ", spaces, ""); 610 result.append(buffer); 611 for (size_t i = 0; i < mFormats.size(); i++) { 612 std::string formatLiteral; 613 bool success = FormatConverter::toString(mFormats[i], formatLiteral); 614 if (i == 0 && !success) { 615 snprintf(buffer, SIZE, "Dynamic"); 616 } else { 617 if (!success) { 618 snprintf(buffer, SIZE, "%#x", mFormats[i]); 619 } else { 620 snprintf(buffer, SIZE, "%s", formatLiteral.c_str()); 621 } 622 } 623 result.append(buffer); 624 result.append(i == (mFormats.size() - 1) ? "" : ", "); 625 } 626 result.append("\n"); 627 } 628 write(fd, result.string(), result.size()); 629 if (mGains.size() != 0) { 630 snprintf(buffer, SIZE, "%*s- gains:\n", spaces, ""); 631 write(fd, buffer, strlen(buffer) + 1); 632 for (size_t i = 0; i < mGains.size(); i++) { 633 mGains[i]->dump(fd, spaces + 2, i); 634 } 635 } 636} 637 638void AudioPort::log(const char* indent) const 639{ 640 ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.string(), mType, mRole); 641} 642 643// --- AudioPortConfig class implementation 644 645AudioPortConfig::AudioPortConfig() 646{ 647 mSamplingRate = 0; 648 mChannelMask = AUDIO_CHANNEL_NONE; 649 mFormat = AUDIO_FORMAT_INVALID; 650 mGain.index = -1; 651} 652 653status_t AudioPortConfig::applyAudioPortConfig( 654 const struct audio_port_config *config, 655 struct audio_port_config *backupConfig) 656{ 657 struct audio_port_config localBackupConfig; 658 status_t status = NO_ERROR; 659 660 localBackupConfig.config_mask = config->config_mask; 661 toAudioPortConfig(&localBackupConfig); 662 663 sp<AudioPort> audioport = getAudioPort(); 664 if (audioport == 0) { 665 status = NO_INIT; 666 goto exit; 667 } 668 if (config->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) { 669 status = audioport->checkExactSamplingRate(config->sample_rate); 670 if (status != NO_ERROR) { 671 goto exit; 672 } 673 mSamplingRate = config->sample_rate; 674 } 675 if (config->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) { 676 status = audioport->checkExactChannelMask(config->channel_mask); 677 if (status != NO_ERROR) { 678 goto exit; 679 } 680 mChannelMask = config->channel_mask; 681 } 682 if (config->config_mask & AUDIO_PORT_CONFIG_FORMAT) { 683 status = audioport->checkExactFormat(config->format); 684 if (status != NO_ERROR) { 685 goto exit; 686 } 687 mFormat = config->format; 688 } 689 if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) { 690 status = audioport->checkGain(&config->gain, config->gain.index); 691 if (status != NO_ERROR) { 692 goto exit; 693 } 694 mGain = config->gain; 695 } 696 697exit: 698 if (status != NO_ERROR) { 699 applyAudioPortConfig(&localBackupConfig); 700 } 701 if (backupConfig != NULL) { 702 *backupConfig = localBackupConfig; 703 } 704 return status; 705} 706 707void AudioPortConfig::toAudioPortConfig(struct audio_port_config *dstConfig, 708 const struct audio_port_config *srcConfig) const 709{ 710 if (dstConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) { 711 dstConfig->sample_rate = mSamplingRate; 712 if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE)) { 713 dstConfig->sample_rate = srcConfig->sample_rate; 714 } 715 } else { 716 dstConfig->sample_rate = 0; 717 } 718 if (dstConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) { 719 dstConfig->channel_mask = mChannelMask; 720 if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK)) { 721 dstConfig->channel_mask = srcConfig->channel_mask; 722 } 723 } else { 724 dstConfig->channel_mask = AUDIO_CHANNEL_NONE; 725 } 726 if (dstConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT) { 727 dstConfig->format = mFormat; 728 if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT)) { 729 dstConfig->format = srcConfig->format; 730 } 731 } else { 732 dstConfig->format = AUDIO_FORMAT_INVALID; 733 } 734 sp<AudioPort> audioport = getAudioPort(); 735 if ((dstConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) && audioport != NULL) { 736 dstConfig->gain = mGain; 737 if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) 738 && audioport->checkGain(&srcConfig->gain, srcConfig->gain.index) == OK) { 739 dstConfig->gain = srcConfig->gain; 740 } 741 } else { 742 dstConfig->gain.index = -1; 743 } 744 if (dstConfig->gain.index != -1) { 745 dstConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN; 746 } else { 747 dstConfig->config_mask &= ~AUDIO_PORT_CONFIG_GAIN; 748 } 749} 750 751}; // namespace android 752