AudioOutputDescriptor.cpp revision aa9811945f575614b3482d09e4d969792701cebb
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 "AudioOutputDescriptor.h" 21#include "IOProfile.h" 22#include "AudioGain.h" 23#include "HwModule.h" 24#include <media/AudioPolicy.h> 25 26// A device mask for all audio output devices that are considered "remote" when evaluating 27// active output devices in isStreamActiveRemotely() 28#define APM_AUDIO_OUT_DEVICE_REMOTE_ALL AUDIO_DEVICE_OUT_REMOTE_SUBMIX 29 30namespace android { 31 32AudioOutputDescriptor::AudioOutputDescriptor(const sp<IOProfile>& profile) 33 : mId(0), mIoHandle(0), mLatency(0), 34 mFlags((audio_output_flags_t)0), mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL), 35 mPatchHandle(0), 36 mOutput1(0), mOutput2(0), mProfile(profile), mDirectOpenCount(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 (profile != NULL) { 49 mFlags = (audio_output_flags_t)profile->mFlags; 50 mSamplingRate = profile->pickSamplingRate(); 51 mFormat = profile->pickFormat(); 52 mChannelMask = profile->pickChannelMask(); 53 if (profile->mGains.size() > 0) { 54 profile->mGains[0]->getDefaultConfig(&mGain); 55 } 56 } 57} 58 59audio_module_handle_t AudioOutputDescriptor::getModuleHandle() const 60{ 61 return mProfile->getModuleHandle(); 62} 63 64audio_devices_t AudioOutputDescriptor::device() const 65{ 66 if (isDuplicated()) { 67 return (audio_devices_t)(mOutput1->mDevice | mOutput2->mDevice); 68 } else { 69 return mDevice; 70 } 71} 72 73void AudioOutputDescriptor::setIoHandle(audio_io_handle_t ioHandle) 74{ 75 mId = AudioPort::getNextUniqueId(); 76 mIoHandle = ioHandle; 77} 78 79uint32_t AudioOutputDescriptor::latency() 80{ 81 if (isDuplicated()) { 82 return (mOutput1->mLatency > mOutput2->mLatency) ? mOutput1->mLatency : mOutput2->mLatency; 83 } else { 84 return mLatency; 85 } 86} 87 88bool AudioOutputDescriptor::sharesHwModuleWith( 89 const sp<AudioOutputDescriptor> outputDesc) 90{ 91 if (isDuplicated()) { 92 return mOutput1->sharesHwModuleWith(outputDesc) || mOutput2->sharesHwModuleWith(outputDesc); 93 } else if (outputDesc->isDuplicated()){ 94 return sharesHwModuleWith(outputDesc->mOutput1) || sharesHwModuleWith(outputDesc->mOutput2); 95 } else { 96 return (mProfile->mModule == outputDesc->mProfile->mModule); 97 } 98} 99 100void AudioOutputDescriptor::changeRefCount(audio_stream_type_t stream, 101 int delta) 102{ 103 // forward usage count change to attached outputs 104 if (isDuplicated()) { 105 mOutput1->changeRefCount(stream, delta); 106 mOutput2->changeRefCount(stream, delta); 107 } 108 if ((delta + (int)mRefCount[stream]) < 0) { 109 ALOGW("changeRefCount() invalid delta %d for stream %d, refCount %d", 110 delta, stream, mRefCount[stream]); 111 mRefCount[stream] = 0; 112 return; 113 } 114 mRefCount[stream] += delta; 115 ALOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]); 116} 117 118audio_devices_t AudioOutputDescriptor::supportedDevices() 119{ 120 if (isDuplicated()) { 121 return (audio_devices_t)(mOutput1->supportedDevices() | mOutput2->supportedDevices()); 122 } else { 123 return mProfile->mSupportedDevices.types() ; 124 } 125} 126 127bool AudioOutputDescriptor::isActive(uint32_t inPastMs) const 128{ 129 nsecs_t sysTime = 0; 130 if (inPastMs != 0) { 131 sysTime = systemTime(); 132 } 133 for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) { 134 if (i == AUDIO_STREAM_PATCH) { 135 continue; 136 } 137 if (isStreamActive((audio_stream_type_t)i, inPastMs, sysTime)) { 138 return true; 139 } 140 } 141 return false; 142} 143 144bool AudioOutputDescriptor::isStreamActive(audio_stream_type_t stream, 145 uint32_t inPastMs, 146 nsecs_t sysTime) const 147{ 148 if (mRefCount[stream] != 0) { 149 return true; 150 } 151 if (inPastMs == 0) { 152 return false; 153 } 154 if (sysTime == 0) { 155 sysTime = systemTime(); 156 } 157 if (ns2ms(sysTime - mStopTime[stream]) < inPastMs) { 158 return true; 159 } 160 return false; 161} 162 163void AudioOutputDescriptor::toAudioPortConfig( 164 struct audio_port_config *dstConfig, 165 const struct audio_port_config *srcConfig) const 166{ 167 ALOG_ASSERT(!isDuplicated(), "toAudioPortConfig() called on duplicated output %d", mIoHandle); 168 169 dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK| 170 AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN; 171 if (srcConfig != NULL) { 172 dstConfig->config_mask |= srcConfig->config_mask; 173 } 174 AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig); 175 176 dstConfig->id = mId; 177 dstConfig->role = AUDIO_PORT_ROLE_SOURCE; 178 dstConfig->type = AUDIO_PORT_TYPE_MIX; 179 dstConfig->ext.mix.hw_module = mProfile->mModule->mHandle; 180 dstConfig->ext.mix.handle = mIoHandle; 181 dstConfig->ext.mix.usecase.stream = AUDIO_STREAM_DEFAULT; 182} 183 184void AudioOutputDescriptor::toAudioPort( 185 struct audio_port *port) const 186{ 187 ALOG_ASSERT(!isDuplicated(), "toAudioPort() called on duplicated output %d", mIoHandle); 188 mProfile->toAudioPort(port); 189 port->id = mId; 190 toAudioPortConfig(&port->active_config); 191 port->ext.mix.hw_module = mProfile->mModule->mHandle; 192 port->ext.mix.handle = mIoHandle; 193 port->ext.mix.latency_class = 194 mFlags & AUDIO_OUTPUT_FLAG_FAST ? AUDIO_LATENCY_LOW : AUDIO_LATENCY_NORMAL; 195} 196 197status_t AudioOutputDescriptor::dump(int fd) 198{ 199 const size_t SIZE = 256; 200 char buffer[SIZE]; 201 String8 result; 202 203 snprintf(buffer, SIZE, " ID: %d\n", mId); 204 result.append(buffer); 205 snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate); 206 result.append(buffer); 207 snprintf(buffer, SIZE, " Format: %08x\n", mFormat); 208 result.append(buffer); 209 snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask); 210 result.append(buffer); 211 snprintf(buffer, SIZE, " Latency: %d\n", mLatency); 212 result.append(buffer); 213 snprintf(buffer, SIZE, " Flags %08x\n", mFlags); 214 result.append(buffer); 215 snprintf(buffer, SIZE, " Devices %08x\n", device()); 216 result.append(buffer); 217 snprintf(buffer, SIZE, " Stream volume refCount muteCount\n"); 218 result.append(buffer); 219 for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) { 220 snprintf(buffer, SIZE, " %02d %.03f %02d %02d\n", 221 i, mCurVolume[i], mRefCount[i], mMuteCount[i]); 222 result.append(buffer); 223 } 224 write(fd, result.string(), result.size()); 225 226 return NO_ERROR; 227} 228 229void AudioOutputDescriptor::log(const char* indent) 230{ 231 ALOGI("%sID: %d,0x%X, [rt:%d fmt:0x%X ch:0x%X] hndl:%d", 232 indent, mId, mId, mSamplingRate, mFormat, mChannelMask, mIoHandle); 233} 234 235bool AudioOutputCollection::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const 236{ 237 nsecs_t sysTime = systemTime(); 238 for (size_t i = 0; i < this->size(); i++) { 239 const sp<AudioOutputDescriptor> outputDesc = this->valueAt(i); 240 if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) { 241 return true; 242 } 243 } 244 return false; 245} 246 247bool AudioOutputCollection::isStreamActiveRemotely(audio_stream_type_t stream, 248 uint32_t inPastMs) const 249{ 250 nsecs_t sysTime = systemTime(); 251 for (size_t i = 0; i < size(); i++) { 252 const sp<AudioOutputDescriptor> outputDesc = valueAt(i); 253 if (((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) && 254 outputDesc->isStreamActive(stream, inPastMs, sysTime)) { 255 // do not consider re routing (when the output is going to a dynamic policy) 256 // as "remote playback" 257 if (outputDesc->mPolicyMix == NULL) { 258 return true; 259 } 260 } 261 } 262 return false; 263} 264 265audio_io_handle_t AudioOutputCollection::getA2dpOutput() const 266{ 267 for (size_t i = 0; i < size(); i++) { 268 sp<AudioOutputDescriptor> outputDesc = valueAt(i); 269 if (!outputDesc->isDuplicated() && outputDesc->device() & AUDIO_DEVICE_OUT_ALL_A2DP) { 270 return this->keyAt(i); 271 } 272 } 273 return 0; 274} 275 276sp<AudioOutputDescriptor> AudioOutputCollection::getPrimaryOutput() const 277{ 278 for (size_t i = 0; i < size(); i++) { 279 const sp<AudioOutputDescriptor> outputDesc = valueAt(i); 280 if (outputDesc->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) { 281 return outputDesc; 282 } 283 } 284 return NULL; 285} 286 287sp<AudioOutputDescriptor> AudioOutputCollection::getOutputFromId(audio_port_handle_t id) const 288{ 289 sp<AudioOutputDescriptor> outputDesc = NULL; 290 for (size_t i = 0; i < size(); i++) { 291 outputDesc = valueAt(i); 292 if (outputDesc->mId == id) { 293 break; 294 } 295 } 296 return outputDesc; 297} 298 299bool AudioOutputCollection::isAnyOutputActive(audio_stream_type_t streamToIgnore) const 300{ 301 for (size_t s = 0 ; s < AUDIO_STREAM_CNT ; s++) { 302 if (s == (size_t) streamToIgnore) { 303 continue; 304 } 305 for (size_t i = 0; i < size(); i++) { 306 const sp<AudioOutputDescriptor> outputDesc = valueAt(i); 307 if (outputDesc->mRefCount[s] != 0) { 308 return true; 309 } 310 } 311 } 312 return false; 313} 314 315audio_devices_t AudioOutputCollection::getSupportedDevices(audio_io_handle_t handle) const 316{ 317 sp<AudioOutputDescriptor> outputDesc = valueFor(handle); 318 audio_devices_t devices = outputDesc->mProfile->mSupportedDevices.types(); 319 return devices; 320} 321 322 323status_t AudioOutputCollection::dump(int fd) const 324{ 325 const size_t SIZE = 256; 326 char buffer[SIZE]; 327 328 snprintf(buffer, SIZE, "\nOutputs dump:\n"); 329 write(fd, buffer, strlen(buffer)); 330 for (size_t i = 0; i < size(); i++) { 331 snprintf(buffer, SIZE, "- Output %d dump:\n", keyAt(i)); 332 write(fd, buffer, strlen(buffer)); 333 valueAt(i)->dump(fd); 334 } 335 336 return NO_ERROR; 337} 338 339}; //namespace android 340