AudioOutputDescriptor.cpp revision 53615e29c99c5e9d2ca77aaefd7bf5c770513120
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 229bool AudioOutputCollection::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const 230{ 231 nsecs_t sysTime = systemTime(); 232 for (size_t i = 0; i < this->size(); i++) { 233 const sp<AudioOutputDescriptor> outputDesc = this->valueAt(i); 234 if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) { 235 return true; 236 } 237 } 238 return false; 239} 240 241bool AudioOutputCollection::isStreamActiveRemotely(audio_stream_type_t stream, 242 uint32_t inPastMs) const 243{ 244 nsecs_t sysTime = systemTime(); 245 for (size_t i = 0; i < size(); i++) { 246 const sp<AudioOutputDescriptor> outputDesc = valueAt(i); 247 if (((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) && 248 outputDesc->isStreamActive(stream, inPastMs, sysTime)) { 249 // do not consider re routing (when the output is going to a dynamic policy) 250 // as "remote playback" 251 if (outputDesc->mPolicyMix == NULL) { 252 return true; 253 } 254 } 255 } 256 return false; 257} 258 259audio_io_handle_t AudioOutputCollection::getA2dpOutput() const 260{ 261 for (size_t i = 0; i < size(); i++) { 262 sp<AudioOutputDescriptor> outputDesc = valueAt(i); 263 if (!outputDesc->isDuplicated() && outputDesc->device() & AUDIO_DEVICE_OUT_ALL_A2DP) { 264 return this->keyAt(i); 265 } 266 } 267 return 0; 268} 269 270sp<AudioOutputDescriptor> AudioOutputCollection::getPrimaryOutput() const 271{ 272 for (size_t i = 0; i < size(); i++) { 273 const sp<AudioOutputDescriptor> outputDesc = valueAt(i); 274 if (outputDesc->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) { 275 return outputDesc; 276 } 277 } 278 return NULL; 279} 280 281sp<AudioOutputDescriptor> AudioOutputCollection::getOutputFromId(audio_port_handle_t id) const 282{ 283 sp<AudioOutputDescriptor> outputDesc = NULL; 284 for (size_t i = 0; i < size(); i++) { 285 outputDesc = valueAt(i); 286 if (outputDesc->mId == id) { 287 break; 288 } 289 } 290 return outputDesc; 291} 292 293bool AudioOutputCollection::isAnyOutputActive(audio_stream_type_t streamToIgnore) const 294{ 295 for (size_t s = 0 ; s < AUDIO_STREAM_CNT ; s++) { 296 if (s == (size_t) streamToIgnore) { 297 continue; 298 } 299 for (size_t i = 0; i < size(); i++) { 300 const sp<AudioOutputDescriptor> outputDesc = valueAt(i); 301 if (outputDesc->mRefCount[s] != 0) { 302 return true; 303 } 304 } 305 } 306 return false; 307} 308 309audio_devices_t AudioOutputCollection::getSupportedDevices(audio_io_handle_t handle) const 310{ 311 sp<AudioOutputDescriptor> outputDesc = valueFor(handle); 312 audio_devices_t devices = outputDesc->mProfile->mSupportedDevices.types(); 313 return devices; 314} 315 316 317status_t AudioOutputCollection::dump(int fd) const 318{ 319 const size_t SIZE = 256; 320 char buffer[SIZE]; 321 322 snprintf(buffer, SIZE, "\nOutputs dump:\n"); 323 write(fd, buffer, strlen(buffer)); 324 for (size_t i = 0; i < size(); i++) { 325 snprintf(buffer, SIZE, "- Output %d dump:\n", keyAt(i)); 326 write(fd, buffer, strlen(buffer)); 327 valueAt(i)->dump(fd); 328 } 329 330 return NO_ERROR; 331} 332 333}; //namespace android 334