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