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::AudioInputDescriptor"
18//#define LOG_NDEBUG 0
19
20#include <AudioPolicyInterface.h>
21#include "AudioInputDescriptor.h"
22#include "IOProfile.h"
23#include "AudioGain.h"
24#include "HwModule.h"
25#include <media/AudioPolicy.h>
26#include <policy.h>
27
28namespace android {
29
30AudioInputDescriptor::AudioInputDescriptor(const sp<IOProfile>& profile,
31                                           AudioPolicyClientInterface *clientInterface)
32    : mIoHandle(0),
33      mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL),
34      mProfile(profile), mPatchHandle(AUDIO_PATCH_HANDLE_NONE), mId(0),
35      mClientInterface(clientInterface)
36{
37    if (profile != NULL) {
38        profile->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
39        if (profile->mGains.size() > 0) {
40            profile->mGains[0]->getDefaultConfig(&mGain);
41        }
42    }
43}
44
45audio_module_handle_t AudioInputDescriptor::getModuleHandle() const
46{
47    if (mProfile == 0) {
48        return AUDIO_MODULE_HANDLE_NONE;
49    }
50    return mProfile->getModuleHandle();
51}
52
53uint32_t AudioInputDescriptor::getOpenRefCount() const
54{
55    return mSessions.getOpenCount();
56}
57
58audio_port_handle_t AudioInputDescriptor::getId() const
59{
60    return mId;
61}
62
63audio_source_t AudioInputDescriptor::inputSource(bool activeOnly) const
64{
65    return getHighestPrioritySource(activeOnly);
66}
67
68void AudioInputDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
69                                             const struct audio_port_config *srcConfig) const
70{
71    ALOG_ASSERT(mProfile != 0,
72                "toAudioPortConfig() called on input with null profile %d", mIoHandle);
73    dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK|
74                            AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN;
75    if (srcConfig != NULL) {
76        dstConfig->config_mask |= srcConfig->config_mask;
77    }
78
79    AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
80
81    dstConfig->id = mId;
82    dstConfig->role = AUDIO_PORT_ROLE_SINK;
83    dstConfig->type = AUDIO_PORT_TYPE_MIX;
84    dstConfig->ext.mix.hw_module = getModuleHandle();
85    dstConfig->ext.mix.handle = mIoHandle;
86    dstConfig->ext.mix.usecase.source = inputSource();
87}
88
89void AudioInputDescriptor::toAudioPort(struct audio_port *port) const
90{
91    ALOG_ASSERT(mProfile != 0, "toAudioPort() called on input with null profile %d", mIoHandle);
92
93    mProfile->toAudioPort(port);
94    port->id = mId;
95    toAudioPortConfig(&port->active_config);
96    port->ext.mix.hw_module = getModuleHandle();
97    port->ext.mix.handle = mIoHandle;
98    port->ext.mix.latency_class = AUDIO_LATENCY_NORMAL;
99}
100
101void AudioInputDescriptor::setPreemptedSessions(const SortedVector<audio_session_t>& sessions)
102{
103    mPreemptedSessions = sessions;
104}
105
106SortedVector<audio_session_t> AudioInputDescriptor::getPreemptedSessions() const
107{
108    return mPreemptedSessions;
109}
110
111bool AudioInputDescriptor::hasPreemptedSession(audio_session_t session) const
112{
113    return (mPreemptedSessions.indexOf(session) >= 0);
114}
115
116void AudioInputDescriptor::clearPreemptedSessions()
117{
118    mPreemptedSessions.clear();
119}
120
121bool AudioInputDescriptor::isActive() const {
122    return mSessions.hasActiveSession();
123}
124
125bool AudioInputDescriptor::isSourceActive(audio_source_t source) const
126{
127    return mSessions.isSourceActive(source);
128}
129
130audio_source_t AudioInputDescriptor::getHighestPrioritySource(bool activeOnly) const
131{
132
133    return mSessions.getHighestPrioritySource(activeOnly);
134}
135
136bool AudioInputDescriptor::isSoundTrigger() const {
137    // sound trigger and non sound trigger sessions are not mixed
138    // on a given input
139    return mSessions.valueAt(0)->isSoundTrigger();
140}
141
142sp<AudioSession> AudioInputDescriptor::getAudioSession(
143                                              audio_session_t session) const {
144    return mSessions.valueFor(session);
145}
146
147AudioSessionCollection AudioInputDescriptor::getAudioSessions(bool activeOnly) const
148{
149    if (activeOnly) {
150        return mSessions.getActiveSessions();
151    } else {
152        return mSessions;
153    }
154}
155
156size_t AudioInputDescriptor::getAudioSessionCount(bool activeOnly) const
157{
158    if (activeOnly) {
159        return mSessions.getActiveSessionCount();
160    } else {
161        return mSessions.size();
162    }
163}
164
165status_t AudioInputDescriptor::addAudioSession(audio_session_t session,
166                         const sp<AudioSession>& audioSession) {
167    return mSessions.addSession(session, audioSession, /*AudioSessionInfoProvider*/this);
168}
169
170status_t AudioInputDescriptor::removeAudioSession(audio_session_t session) {
171    return mSessions.removeSession(session);
172}
173
174audio_patch_handle_t AudioInputDescriptor::getPatchHandle() const
175{
176    return mPatchHandle;
177}
178
179void AudioInputDescriptor::setPatchHandle(audio_patch_handle_t handle)
180{
181    mPatchHandle = handle;
182    mSessions.onSessionInfoUpdate();
183}
184
185audio_config_base_t AudioInputDescriptor::getConfig() const
186{
187    const audio_config_base_t config = { .sample_rate = mSamplingRate, .channel_mask = mChannelMask,
188            .format = mFormat };
189    return config;
190}
191
192status_t AudioInputDescriptor::open(const audio_config_t *config,
193                                       audio_devices_t device,
194                                       const String8& address,
195                                       audio_source_t source,
196                                       audio_input_flags_t flags,
197                                       audio_io_handle_t *input)
198{
199    audio_config_t lConfig;
200    if (config == nullptr) {
201        lConfig = AUDIO_CONFIG_INITIALIZER;
202        lConfig.sample_rate = mSamplingRate;
203        lConfig.channel_mask = mChannelMask;
204        lConfig.format = mFormat;
205    } else {
206        lConfig = *config;
207    }
208
209    mDevice = device;
210
211    ALOGV("opening input for device %08x address %s profile %p name %s",
212          mDevice, address.string(), mProfile.get(), mProfile->getName().string());
213
214    status_t status = mClientInterface->openInput(mProfile->getModuleHandle(),
215                                                  input,
216                                                  &lConfig,
217                                                  &mDevice,
218                                                  address,
219                                                  source,
220                                                  flags);
221    LOG_ALWAYS_FATAL_IF(mDevice != device,
222                        "%s openInput returned device %08x when given device %08x",
223                        __FUNCTION__, mDevice, device);
224
225    if (status == NO_ERROR) {
226        LOG_ALWAYS_FATAL_IF(*input == AUDIO_IO_HANDLE_NONE,
227                            "%s openInput returned input handle %d for device %08x",
228                            __FUNCTION__, *input, device);
229        mSamplingRate = lConfig.sample_rate;
230        mChannelMask = lConfig.channel_mask;
231        mFormat = lConfig.format;
232        mId = AudioPort::getNextUniqueId();
233        mIoHandle = *input;
234        mProfile->curOpenCount++;
235    }
236
237    return status;
238}
239
240status_t AudioInputDescriptor::start()
241{
242    if (getAudioSessionCount(true/*activeOnly*/) == 1) {
243        if (!mProfile->canStartNewIo()) {
244            ALOGI("%s mProfile->curActiveCount %d", __func__, mProfile->curActiveCount);
245            return INVALID_OPERATION;
246        }
247        mProfile->curActiveCount++;
248    }
249    return NO_ERROR;
250}
251
252void AudioInputDescriptor::stop()
253{
254    if (!isActive()) {
255        LOG_ALWAYS_FATAL_IF(mProfile->curActiveCount < 1,
256                            "%s invalid profile active count %u",
257                            __func__, mProfile->curActiveCount);
258        mProfile->curActiveCount--;
259    }
260}
261
262void AudioInputDescriptor::close()
263{
264    if (mIoHandle != AUDIO_IO_HANDLE_NONE) {
265        mClientInterface->closeInput(mIoHandle);
266        LOG_ALWAYS_FATAL_IF(mProfile->curOpenCount < 1, "%s profile open count %u",
267                            __FUNCTION__, mProfile->curOpenCount);
268        // do not call stop() here as stop() is supposed to be called after
269        // AudioSession::changeActiveCount(-1) and we don't know how many sessions
270        // are still active at this time
271        if (isActive()) {
272            mProfile->curActiveCount--;
273        }
274        mProfile->curOpenCount--;
275        mIoHandle = AUDIO_IO_HANDLE_NONE;
276    }
277}
278
279status_t AudioInputDescriptor::dump(int fd)
280{
281    const size_t SIZE = 256;
282    char buffer[SIZE];
283    String8 result;
284
285    snprintf(buffer, SIZE, " ID: %d\n", getId());
286    result.append(buffer);
287    snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
288    result.append(buffer);
289    snprintf(buffer, SIZE, " Format: %d\n", mFormat);
290    result.append(buffer);
291    snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask);
292    result.append(buffer);
293    snprintf(buffer, SIZE, " Devices %08x\n", mDevice);
294    result.append(buffer);
295
296    write(fd, result.string(), result.size());
297
298    mSessions.dump(fd, 1);
299
300    return NO_ERROR;
301}
302
303bool AudioInputCollection::isSourceActive(audio_source_t source) const
304{
305    for (size_t i = 0; i < size(); i++) {
306        const sp<AudioInputDescriptor>  inputDescriptor = valueAt(i);
307        if (inputDescriptor->isSourceActive(source)) {
308            return true;
309        }
310    }
311    return false;
312}
313
314sp<AudioInputDescriptor> AudioInputCollection::getInputFromId(audio_port_handle_t id) const
315{
316    sp<AudioInputDescriptor> inputDesc = NULL;
317    for (size_t i = 0; i < size(); i++) {
318        inputDesc = valueAt(i);
319        if (inputDesc->getId() == id) {
320            break;
321        }
322    }
323    return inputDesc;
324}
325
326uint32_t AudioInputCollection::activeInputsCountOnDevices(audio_devices_t devices) const
327{
328    uint32_t count = 0;
329    for (size_t i = 0; i < size(); i++) {
330        const sp<AudioInputDescriptor>  inputDescriptor = valueAt(i);
331        if (inputDescriptor->isActive() &&
332                ((devices == AUDIO_DEVICE_IN_DEFAULT) ||
333                 ((inputDescriptor->mDevice & devices & ~AUDIO_DEVICE_BIT_IN) != 0))) {
334            count++;
335        }
336    }
337    return count;
338}
339
340Vector<sp <AudioInputDescriptor> > AudioInputCollection::getActiveInputs(bool ignoreVirtualInputs)
341{
342    Vector<sp <AudioInputDescriptor> > activeInputs;
343
344    for (size_t i = 0; i < size(); i++) {
345        const sp<AudioInputDescriptor>  inputDescriptor = valueAt(i);
346        if ((inputDescriptor->isActive())
347                && (!ignoreVirtualInputs ||
348                    !is_virtual_input_device(inputDescriptor->mDevice))) {
349            activeInputs.add(inputDescriptor);
350        }
351    }
352    return activeInputs;
353}
354
355audio_devices_t AudioInputCollection::getSupportedDevices(audio_io_handle_t handle) const
356{
357    sp<AudioInputDescriptor> inputDesc = valueFor(handle);
358    audio_devices_t devices = inputDesc->mProfile->getSupportedDevicesType();
359    return devices;
360}
361
362status_t AudioInputCollection::dump(int fd) const
363{
364    const size_t SIZE = 256;
365    char buffer[SIZE];
366
367    snprintf(buffer, SIZE, "\nInputs dump:\n");
368    write(fd, buffer, strlen(buffer));
369    for (size_t i = 0; i < size(); i++) {
370        snprintf(buffer, SIZE, "- Input %d dump:\n", keyAt(i));
371        write(fd, buffer, strlen(buffer));
372        valueAt(i)->dump(fd);
373    }
374
375    return NO_ERROR;
376}
377
378}; //namespace android
379