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