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