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