AudioOutputDescriptor.cpp revision 98cc191247388132b6fd8a4ecd07abd6e4c5a0ed
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 26namespace android { 27 28AudioOutputDescriptor::AudioOutputDescriptor( 29 const sp<IOProfile>& profile) 30 : mId(0), mIoHandle(0), mLatency(0), 31 mFlags((audio_output_flags_t)0), mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL), 32 mPatchHandle(0), 33 mOutput1(0), mOutput2(0), mProfile(profile), mDirectOpenCount(0) 34{ 35 // clear usage count for all stream types 36 for (int i = 0; i < AUDIO_STREAM_CNT; i++) { 37 mRefCount[i] = 0; 38 mCurVolume[i] = -1.0; 39 mMuteCount[i] = 0; 40 mStopTime[i] = 0; 41 } 42 for (int i = 0; i < NUM_STRATEGIES; i++) { 43 mStrategyMutedByDevice[i] = false; 44 } 45 if (profile != NULL) { 46 mFlags = (audio_output_flags_t)profile->mFlags; 47 mSamplingRate = profile->pickSamplingRate(); 48 mFormat = profile->pickFormat(); 49 mChannelMask = profile->pickChannelMask(); 50 if (profile->mGains.size() > 0) { 51 profile->mGains[0]->getDefaultConfig(&mGain); 52 } 53 } 54} 55 56audio_devices_t AudioOutputDescriptor::device() const 57{ 58 if (isDuplicated()) { 59 return (audio_devices_t)(mOutput1->mDevice | mOutput2->mDevice); 60 } else { 61 return mDevice; 62 } 63} 64 65void AudioOutputDescriptor::setIoHandle(audio_io_handle_t ioHandle) 66{ 67 mId = AudioPort::getNextUniqueId(); 68 mIoHandle = ioHandle; 69} 70 71uint32_t AudioOutputDescriptor::latency() 72{ 73 if (isDuplicated()) { 74 return (mOutput1->mLatency > mOutput2->mLatency) ? mOutput1->mLatency : mOutput2->mLatency; 75 } else { 76 return mLatency; 77 } 78} 79 80bool AudioOutputDescriptor::sharesHwModuleWith( 81 const sp<AudioOutputDescriptor> outputDesc) 82{ 83 if (isDuplicated()) { 84 return mOutput1->sharesHwModuleWith(outputDesc) || mOutput2->sharesHwModuleWith(outputDesc); 85 } else if (outputDesc->isDuplicated()){ 86 return sharesHwModuleWith(outputDesc->mOutput1) || sharesHwModuleWith(outputDesc->mOutput2); 87 } else { 88 return (mProfile->mModule == outputDesc->mProfile->mModule); 89 } 90} 91 92void AudioOutputDescriptor::changeRefCount(audio_stream_type_t stream, 93 int delta) 94{ 95 // forward usage count change to attached outputs 96 if (isDuplicated()) { 97 mOutput1->changeRefCount(stream, delta); 98 mOutput2->changeRefCount(stream, delta); 99 } 100 if ((delta + (int)mRefCount[stream]) < 0) { 101 ALOGW("changeRefCount() invalid delta %d for stream %d, refCount %d", 102 delta, stream, mRefCount[stream]); 103 mRefCount[stream] = 0; 104 return; 105 } 106 mRefCount[stream] += delta; 107 ALOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]); 108} 109 110audio_devices_t AudioOutputDescriptor::supportedDevices() 111{ 112 if (isDuplicated()) { 113 return (audio_devices_t)(mOutput1->supportedDevices() | mOutput2->supportedDevices()); 114 } else { 115 return mProfile->mSupportedDevices.types() ; 116 } 117} 118 119bool AudioOutputDescriptor::isActive(uint32_t inPastMs) const 120{ 121 nsecs_t sysTime = 0; 122 if (inPastMs != 0) { 123 sysTime = systemTime(); 124 } 125 for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) { 126 if (i == AUDIO_STREAM_PATCH) { 127 continue; 128 } 129 if (isStreamActive((audio_stream_type_t)i, inPastMs, sysTime)) { 130 return true; 131 } 132 } 133 return false; 134} 135 136bool AudioOutputDescriptor::isStreamActive(audio_stream_type_t stream, 137 uint32_t inPastMs, 138 nsecs_t sysTime) const 139{ 140 if (mRefCount[stream] != 0) { 141 return true; 142 } 143 if (inPastMs == 0) { 144 return false; 145 } 146 if (sysTime == 0) { 147 sysTime = systemTime(); 148 } 149 if (ns2ms(sysTime - mStopTime[stream]) < inPastMs) { 150 return true; 151 } 152 return false; 153} 154 155void AudioOutputDescriptor::toAudioPortConfig( 156 struct audio_port_config *dstConfig, 157 const struct audio_port_config *srcConfig) const 158{ 159 ALOG_ASSERT(!isDuplicated(), "toAudioPortConfig() called on duplicated output %d", mIoHandle); 160 161 dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK| 162 AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN; 163 if (srcConfig != NULL) { 164 dstConfig->config_mask |= srcConfig->config_mask; 165 } 166 AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig); 167 168 dstConfig->id = mId; 169 dstConfig->role = AUDIO_PORT_ROLE_SOURCE; 170 dstConfig->type = AUDIO_PORT_TYPE_MIX; 171 dstConfig->ext.mix.hw_module = mProfile->mModule->mHandle; 172 dstConfig->ext.mix.handle = mIoHandle; 173 dstConfig->ext.mix.usecase.stream = AUDIO_STREAM_DEFAULT; 174} 175 176void AudioOutputDescriptor::toAudioPort( 177 struct audio_port *port) const 178{ 179 ALOG_ASSERT(!isDuplicated(), "toAudioPort() called on duplicated output %d", mIoHandle); 180 mProfile->toAudioPort(port); 181 port->id = mId; 182 toAudioPortConfig(&port->active_config); 183 port->ext.mix.hw_module = mProfile->mModule->mHandle; 184 port->ext.mix.handle = mIoHandle; 185 port->ext.mix.latency_class = 186 mFlags & AUDIO_OUTPUT_FLAG_FAST ? AUDIO_LATENCY_LOW : AUDIO_LATENCY_NORMAL; 187} 188 189status_t AudioOutputDescriptor::dump(int fd) 190{ 191 const size_t SIZE = 256; 192 char buffer[SIZE]; 193 String8 result; 194 195 snprintf(buffer, SIZE, " ID: %d\n", mId); 196 result.append(buffer); 197 snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate); 198 result.append(buffer); 199 snprintf(buffer, SIZE, " Format: %08x\n", mFormat); 200 result.append(buffer); 201 snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask); 202 result.append(buffer); 203 snprintf(buffer, SIZE, " Latency: %d\n", mLatency); 204 result.append(buffer); 205 snprintf(buffer, SIZE, " Flags %08x\n", mFlags); 206 result.append(buffer); 207 snprintf(buffer, SIZE, " Devices %08x\n", device()); 208 result.append(buffer); 209 snprintf(buffer, SIZE, " Stream volume refCount muteCount\n"); 210 result.append(buffer); 211 for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) { 212 snprintf(buffer, SIZE, " %02d %.03f %02d %02d\n", 213 i, mCurVolume[i], mRefCount[i], mMuteCount[i]); 214 result.append(buffer); 215 } 216 write(fd, result.string(), result.size()); 217 218 return NO_ERROR; 219} 220 221 222 223}; //namespace android 224