AudioOutputDescriptor.cpp revision c75307b73d324d590d0dbc05b44bce9aa89b7145
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::AudioOutputDescriptor" 18//#define LOG_NDEBUG 0 19 20#include <AudioPolicyInterface.h> 21#include "AudioOutputDescriptor.h" 22#include "IOProfile.h" 23#include "AudioGain.h" 24#include "HwModule.h" 25#include <media/AudioPolicy.h> 26 27// A device mask for all audio output devices that are considered "remote" when evaluating 28// active output devices in isStreamActiveRemotely() 29#define APM_AUDIO_OUT_DEVICE_REMOTE_ALL AUDIO_DEVICE_OUT_REMOTE_SUBMIX 30 31namespace android { 32 33AudioOutputDescriptor::AudioOutputDescriptor(const sp<AudioPort>& port, 34 AudioPolicyClientInterface *clientInterface) 35 : mPort(port), mDevice(AUDIO_DEVICE_NONE), 36 mPatchHandle(0), mClientInterface(clientInterface), mId(0) 37{ 38 // clear usage count for all stream types 39 for (int i = 0; i < AUDIO_STREAM_CNT; i++) { 40 mRefCount[i] = 0; 41 mCurVolume[i] = -1.0; 42 mMuteCount[i] = 0; 43 mStopTime[i] = 0; 44 } 45 for (int i = 0; i < NUM_STRATEGIES; i++) { 46 mStrategyMutedByDevice[i] = false; 47 } 48 if (port != NULL) { 49 mSamplingRate = port->pickSamplingRate(); 50 mFormat = port->pickFormat(); 51 mChannelMask = port->pickChannelMask(); 52 if (port->mGains.size() > 0) { 53 port->mGains[0]->getDefaultConfig(&mGain); 54 } 55 } 56} 57 58audio_module_handle_t AudioOutputDescriptor::getModuleHandle() const 59{ 60 return mPort->getModuleHandle(); 61} 62 63audio_port_handle_t AudioOutputDescriptor::getId() const 64{ 65 return mId; 66} 67 68audio_devices_t AudioOutputDescriptor::device() const 69{ 70 return mDevice; 71} 72 73audio_devices_t AudioOutputDescriptor::supportedDevices() 74{ 75 return mDevice; 76} 77 78bool AudioOutputDescriptor::sharesHwModuleWith( 79 const sp<AudioOutputDescriptor> outputDesc) 80{ 81 if (outputDesc->isDuplicated()) { 82 return sharesHwModuleWith(outputDesc->subOutput1()) || 83 sharesHwModuleWith(outputDesc->subOutput2()); 84 } else { 85 return (getModuleHandle() == outputDesc->getModuleHandle()); 86 } 87} 88 89void AudioOutputDescriptor::changeRefCount(audio_stream_type_t stream, 90 int delta) 91{ 92 if ((delta + (int)mRefCount[stream]) < 0) { 93 ALOGW("changeRefCount() invalid delta %d for stream %d, refCount %d", 94 delta, stream, mRefCount[stream]); 95 mRefCount[stream] = 0; 96 return; 97 } 98 mRefCount[stream] += delta; 99 ALOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]); 100} 101 102bool AudioOutputDescriptor::isActive(uint32_t inPastMs) const 103{ 104 nsecs_t sysTime = 0; 105 if (inPastMs != 0) { 106 sysTime = systemTime(); 107 } 108 for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) { 109 if (i == AUDIO_STREAM_PATCH) { 110 continue; 111 } 112 if (isStreamActive((audio_stream_type_t)i, inPastMs, sysTime)) { 113 return true; 114 } 115 } 116 return false; 117} 118 119bool AudioOutputDescriptor::isStreamActive(audio_stream_type_t stream, 120 uint32_t inPastMs, 121 nsecs_t sysTime) const 122{ 123 if (mRefCount[stream] != 0) { 124 return true; 125 } 126 if (inPastMs == 0) { 127 return false; 128 } 129 if (sysTime == 0) { 130 sysTime = systemTime(); 131 } 132 if (ns2ms(sysTime - mStopTime[stream]) < inPastMs) { 133 return true; 134 } 135 return false; 136} 137 138 139bool AudioOutputDescriptor::isFixedVolume(audio_devices_t device __unused) 140{ 141 return false; 142} 143 144bool AudioOutputDescriptor::setVolume(float volume, 145 audio_stream_type_t stream, 146 audio_devices_t device __unused, 147 uint32_t delayMs, 148 bool force) 149{ 150 // We actually change the volume if: 151 // - the float value returned by computeVolume() changed 152 // - the force flag is set 153 if (volume != mCurVolume[stream] || force) { 154 ALOGV("setVolume() for stream %d, volume %f, delay %d", stream, volume, delayMs); 155 mCurVolume[stream] = volume; 156 return true; 157 } 158 return false; 159} 160 161void AudioOutputDescriptor::toAudioPortConfig( 162 struct audio_port_config *dstConfig, 163 const struct audio_port_config *srcConfig) const 164{ 165 dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK| 166 AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN; 167 if (srcConfig != NULL) { 168 dstConfig->config_mask |= srcConfig->config_mask; 169 } 170 AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig); 171 172 dstConfig->id = mId; 173 dstConfig->role = AUDIO_PORT_ROLE_SOURCE; 174 dstConfig->type = AUDIO_PORT_TYPE_MIX; 175 dstConfig->ext.mix.hw_module = getModuleHandle(); 176 dstConfig->ext.mix.usecase.stream = AUDIO_STREAM_DEFAULT; 177} 178 179void AudioOutputDescriptor::toAudioPort( 180 struct audio_port *port) const 181{ 182 mPort->toAudioPort(port); 183 port->id = mId; 184 port->ext.mix.hw_module = getModuleHandle(); 185} 186 187status_t AudioOutputDescriptor::dump(int fd) 188{ 189 const size_t SIZE = 256; 190 char buffer[SIZE]; 191 String8 result; 192 193 snprintf(buffer, SIZE, " ID: %d\n", mId); 194 result.append(buffer); 195 snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate); 196 result.append(buffer); 197 snprintf(buffer, SIZE, " Format: %08x\n", mFormat); 198 result.append(buffer); 199 snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask); 200 result.append(buffer); 201 snprintf(buffer, SIZE, " Devices %08x\n", device()); 202 result.append(buffer); 203 snprintf(buffer, SIZE, " Stream volume refCount muteCount\n"); 204 result.append(buffer); 205 for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) { 206 snprintf(buffer, SIZE, " %02d %.03f %02d %02d\n", 207 i, mCurVolume[i], mRefCount[i], mMuteCount[i]); 208 result.append(buffer); 209 } 210 write(fd, result.string(), result.size()); 211 212 return NO_ERROR; 213} 214 215void AudioOutputDescriptor::log(const char* indent) 216{ 217 ALOGI("%sID: %d,0x%X, [rt:%d fmt:0x%X ch:0x%X]", 218 indent, mId, mId, mSamplingRate, mFormat, mChannelMask); 219} 220 221// SwAudioOutputDescriptor implementation 222SwAudioOutputDescriptor::SwAudioOutputDescriptor( 223 const sp<IOProfile>& profile, AudioPolicyClientInterface *clientInterface) 224 : AudioOutputDescriptor(profile, clientInterface), 225 mProfile(profile), mIoHandle(0), mLatency(0), 226 mFlags((audio_output_flags_t)0), mPolicyMix(NULL), 227 mOutput1(0), mOutput2(0), mDirectOpenCount(0) 228{ 229 if (profile != NULL) { 230 mFlags = (audio_output_flags_t)profile->mFlags; 231 } 232} 233 234void SwAudioOutputDescriptor::setIoHandle(audio_io_handle_t ioHandle) 235{ 236 mId = AudioPort::getNextUniqueId(); 237 mIoHandle = ioHandle; 238} 239 240 241status_t SwAudioOutputDescriptor::dump(int fd) 242{ 243 const size_t SIZE = 256; 244 char buffer[SIZE]; 245 String8 result; 246 247 snprintf(buffer, SIZE, " Latency: %d\n", mLatency); 248 result.append(buffer); 249 snprintf(buffer, SIZE, " Flags %08x\n", mFlags); 250 result.append(buffer); 251 write(fd, result.string(), result.size()); 252 253 AudioOutputDescriptor::dump(fd); 254 255 return NO_ERROR; 256} 257 258audio_devices_t SwAudioOutputDescriptor::device() const 259{ 260 if (isDuplicated()) { 261 return (audio_devices_t)(mOutput1->mDevice | mOutput2->mDevice); 262 } else { 263 return mDevice; 264 } 265} 266 267bool SwAudioOutputDescriptor::sharesHwModuleWith( 268 const sp<AudioOutputDescriptor> outputDesc) 269{ 270 if (isDuplicated()) { 271 return mOutput1->sharesHwModuleWith(outputDesc) || mOutput2->sharesHwModuleWith(outputDesc); 272 } else if (outputDesc->isDuplicated()){ 273 return sharesHwModuleWith(outputDesc->subOutput1()) || 274 sharesHwModuleWith(outputDesc->subOutput2()); 275 } else { 276 return AudioOutputDescriptor::sharesHwModuleWith(outputDesc); 277 } 278} 279 280audio_devices_t SwAudioOutputDescriptor::supportedDevices() 281{ 282 if (isDuplicated()) { 283 return (audio_devices_t)(mOutput1->supportedDevices() | mOutput2->supportedDevices()); 284 } else { 285 return mProfile->mSupportedDevices.types() ; 286 } 287} 288 289uint32_t SwAudioOutputDescriptor::latency() 290{ 291 if (isDuplicated()) { 292 return (mOutput1->mLatency > mOutput2->mLatency) ? mOutput1->mLatency : mOutput2->mLatency; 293 } else { 294 return mLatency; 295 } 296} 297 298void SwAudioOutputDescriptor::changeRefCount(audio_stream_type_t stream, 299 int delta) 300{ 301 // forward usage count change to attached outputs 302 if (isDuplicated()) { 303 mOutput1->changeRefCount(stream, delta); 304 mOutput2->changeRefCount(stream, delta); 305 } 306 AudioOutputDescriptor::changeRefCount(stream, delta); 307} 308 309 310bool SwAudioOutputDescriptor::isFixedVolume(audio_devices_t device) 311{ 312 // unit gain if rerouting to external policy 313 if (device == AUDIO_DEVICE_OUT_REMOTE_SUBMIX) { 314 if (mPolicyMix != NULL) { 315 ALOGV("max gain when rerouting for output=%d", mIoHandle); 316 return true; 317 } 318 } 319 return false; 320} 321 322void SwAudioOutputDescriptor::toAudioPortConfig( 323 struct audio_port_config *dstConfig, 324 const struct audio_port_config *srcConfig) const 325{ 326 327 ALOG_ASSERT(!isDuplicated(), "toAudioPortConfig() called on duplicated output %d", mIoHandle); 328 AudioOutputDescriptor::toAudioPortConfig(dstConfig, srcConfig); 329 330 dstConfig->ext.mix.handle = mIoHandle; 331} 332 333void SwAudioOutputDescriptor::toAudioPort( 334 struct audio_port *port) const 335{ 336 ALOG_ASSERT(!isDuplicated(), "toAudioPort() called on duplicated output %d", mIoHandle); 337 338 AudioOutputDescriptor::toAudioPort(port); 339 340 toAudioPortConfig(&port->active_config); 341 port->ext.mix.handle = mIoHandle; 342 port->ext.mix.latency_class = 343 mFlags & AUDIO_OUTPUT_FLAG_FAST ? AUDIO_LATENCY_LOW : AUDIO_LATENCY_NORMAL; 344} 345 346bool SwAudioOutputDescriptor::setVolume(float volume, 347 audio_stream_type_t stream, 348 audio_devices_t device, 349 uint32_t delayMs, 350 bool force) 351{ 352 bool changed = AudioOutputDescriptor::setVolume(volume, stream, device, delayMs, force); 353 354 if (changed) { 355 // Force VOICE_CALL to track BLUETOOTH_SCO stream volume when bluetooth audio is 356 // enabled 357 if (stream == AUDIO_STREAM_BLUETOOTH_SCO) { 358 mClientInterface->setStreamVolume( 359 AUDIO_STREAM_VOICE_CALL, mCurVolume[stream], mIoHandle, delayMs); 360 } 361 mClientInterface->setStreamVolume(stream, mCurVolume[stream], mIoHandle, delayMs); 362 } 363 return changed; 364} 365 366// SwAudioOutputCollection implementation 367 368bool SwAudioOutputCollection::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const 369{ 370 nsecs_t sysTime = systemTime(); 371 for (size_t i = 0; i < this->size(); i++) { 372 const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i); 373 if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) { 374 return true; 375 } 376 } 377 return false; 378} 379 380bool SwAudioOutputCollection::isStreamActiveRemotely(audio_stream_type_t stream, 381 uint32_t inPastMs) const 382{ 383 nsecs_t sysTime = systemTime(); 384 for (size_t i = 0; i < size(); i++) { 385 const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i); 386 if (((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) && 387 outputDesc->isStreamActive(stream, inPastMs, sysTime)) { 388 // do not consider re routing (when the output is going to a dynamic policy) 389 // as "remote playback" 390 if (outputDesc->mPolicyMix == NULL) { 391 return true; 392 } 393 } 394 } 395 return false; 396} 397 398audio_io_handle_t SwAudioOutputCollection::getA2dpOutput() const 399{ 400 for (size_t i = 0; i < size(); i++) { 401 sp<SwAudioOutputDescriptor> outputDesc = valueAt(i); 402 if (!outputDesc->isDuplicated() && outputDesc->device() & AUDIO_DEVICE_OUT_ALL_A2DP) { 403 return this->keyAt(i); 404 } 405 } 406 return 0; 407} 408 409sp<SwAudioOutputDescriptor> SwAudioOutputCollection::getPrimaryOutput() const 410{ 411 for (size_t i = 0; i < size(); i++) { 412 const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i); 413 if (outputDesc->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) { 414 return outputDesc; 415 } 416 } 417 return NULL; 418} 419 420sp<SwAudioOutputDescriptor> SwAudioOutputCollection::getOutputFromId(audio_port_handle_t id) const 421{ 422 sp<SwAudioOutputDescriptor> outputDesc = NULL; 423 for (size_t i = 0; i < size(); i++) { 424 outputDesc = valueAt(i); 425 if (outputDesc->getId() == id) { 426 break; 427 } 428 } 429 return outputDesc; 430} 431 432bool SwAudioOutputCollection::isAnyOutputActive(audio_stream_type_t streamToIgnore) const 433{ 434 for (size_t s = 0 ; s < AUDIO_STREAM_CNT ; s++) { 435 if (s == (size_t) streamToIgnore) { 436 continue; 437 } 438 for (size_t i = 0; i < size(); i++) { 439 const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i); 440 if (outputDesc->mRefCount[s] != 0) { 441 return true; 442 } 443 } 444 } 445 return false; 446} 447 448audio_devices_t SwAudioOutputCollection::getSupportedDevices(audio_io_handle_t handle) const 449{ 450 sp<SwAudioOutputDescriptor> outputDesc = valueFor(handle); 451 audio_devices_t devices = outputDesc->mProfile->mSupportedDevices.types(); 452 return devices; 453} 454 455 456status_t SwAudioOutputCollection::dump(int fd) const 457{ 458 const size_t SIZE = 256; 459 char buffer[SIZE]; 460 461 snprintf(buffer, SIZE, "\nOutputs dump:\n"); 462 write(fd, buffer, strlen(buffer)); 463 for (size_t i = 0; i < size(); i++) { 464 snprintf(buffer, SIZE, "- Output %d dump:\n", keyAt(i)); 465 write(fd, buffer, strlen(buffer)); 466 valueAt(i)->dump(fd); 467 } 468 469 return NO_ERROR; 470} 471 472}; //namespace android 473