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