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