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::AudioSession"
18//#define LOG_NDEBUG 0
19
20#include <AudioPolicyInterface.h>
21#include "AudioSession.h"
22#include "AudioGain.h"
23#include "TypeConverter.h"
24#include <cutils/log.h>
25#include <utils/String8.h>
26
27namespace android {
28
29AudioSession::AudioSession(audio_session_t session,
30                           audio_source_t inputSource,
31                           audio_format_t format,
32                           uint32_t sampleRate,
33                           audio_channel_mask_t channelMask,
34                           audio_input_flags_t flags,
35                           uid_t uid,
36                           bool isSoundTrigger,
37                           AudioMix* policyMix,
38                           AudioPolicyClientInterface *clientInterface) :
39    mSession(session), mInputSource(inputSource),
40    mConfig({ .format = format, .sample_rate = sampleRate, .channel_mask = channelMask}),
41    mFlags(flags), mUid(uid), mIsSoundTrigger(isSoundTrigger),
42    mOpenCount(1), mActiveCount(0), mPolicyMix(policyMix), mClientInterface(clientInterface),
43    mInfoProvider(NULL)
44{
45}
46
47uint32_t AudioSession::changeOpenCount(int delta)
48{
49    if ((delta + (int)mOpenCount) < 0) {
50        ALOGW("%s invalid delta %d, open count %d",
51              __FUNCTION__, delta, mOpenCount);
52        mOpenCount = (uint32_t)(-delta);
53    }
54    mOpenCount += delta;
55    ALOGV("%s open count %d", __FUNCTION__, mOpenCount);
56    return mOpenCount;
57}
58
59uint32_t AudioSession::changeActiveCount(int delta)
60{
61    const uint32_t oldActiveCount = mActiveCount;
62    if ((delta + (int)mActiveCount) < 0) {
63        ALOGW("%s invalid delta %d, active count %d",
64              __FUNCTION__, delta, mActiveCount);
65        mActiveCount = (uint32_t)(-delta);
66    }
67    mActiveCount += delta;
68    ALOGV("%s active count %d", __FUNCTION__, mActiveCount);
69    int event = RECORD_CONFIG_EVENT_NONE;
70
71    if ((oldActiveCount == 0) && (mActiveCount > 0)) {
72        event = RECORD_CONFIG_EVENT_START;
73    } else if ((oldActiveCount > 0) && (mActiveCount == 0)) {
74        event = RECORD_CONFIG_EVENT_STOP;
75    }
76
77    if (event != RECORD_CONFIG_EVENT_NONE) {
78        // Dynamic policy callback:
79        // if input maps to a dynamic policy with an activity listener, notify of state change
80        if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
81        {
82            mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
83                    (event == RECORD_CONFIG_EVENT_START) ? MIX_STATE_MIXING : MIX_STATE_IDLE);
84        }
85
86        // Recording configuration callback:
87        const AudioSessionInfoProvider* provider = mInfoProvider;
88        const audio_config_base_t deviceConfig = (provider != NULL) ? provider->getConfig() :
89                AUDIO_CONFIG_BASE_INITIALIZER;
90        const audio_patch_handle_t patchHandle = (provider != NULL) ? provider->getPatchHandle() :
91                AUDIO_PATCH_HANDLE_NONE;
92        mClientInterface->onRecordingConfigurationUpdate(event, mSession, mInputSource,
93                &mConfig, &deviceConfig, patchHandle);
94    }
95
96    return mActiveCount;
97}
98
99bool AudioSession::matches(const sp<AudioSession> &other) const
100{
101    if (other->session() == mSession &&
102        other->inputSource() == mInputSource &&
103        other->format() == mConfig.format &&
104        other->sampleRate() == mConfig.sample_rate &&
105        other->channelMask() == mConfig.channel_mask &&
106        other->flags() == mFlags &&
107        other->uid() == mUid) {
108        return true;
109    }
110    return false;
111}
112
113void AudioSession::setInfoProvider(AudioSessionInfoProvider *provider)
114{
115    mInfoProvider = provider;
116}
117
118void AudioSession::onSessionInfoUpdate() const
119{
120    if (mActiveCount > 0) {
121        // resend the callback after requerying the informations from the info provider
122        const AudioSessionInfoProvider* provider = mInfoProvider;
123        const audio_config_base_t deviceConfig = (provider != NULL) ? provider->getConfig() :
124                AUDIO_CONFIG_BASE_INITIALIZER;
125        const audio_patch_handle_t patchHandle = (provider != NULL) ? provider->getPatchHandle() :
126                AUDIO_PATCH_HANDLE_NONE;
127        mClientInterface->onRecordingConfigurationUpdate(RECORD_CONFIG_EVENT_START,
128                mSession, mInputSource,
129                &mConfig, &deviceConfig, patchHandle);
130    }
131}
132
133status_t AudioSession::dump(int fd, int spaces, int index) const
134{
135    const size_t SIZE = 256;
136    char buffer[SIZE];
137    String8 result;
138
139    snprintf(buffer, SIZE, "%*sAudio session %d:\n", spaces, "", index+1);
140    result.append(buffer);
141    snprintf(buffer, SIZE, "%*s- session: %2d\n", spaces, "", mSession);
142    result.append(buffer);
143    snprintf(buffer, SIZE, "%*s- owner uid: %2d\n", spaces, "", mUid);
144    result.append(buffer);
145    snprintf(buffer, SIZE, "%*s- input source: %d\n", spaces, "", mInputSource);
146    result.append(buffer);
147    snprintf(buffer, SIZE, "%*s- format: %08x\n", spaces, "", mConfig.format);
148    result.append(buffer);
149    snprintf(buffer, SIZE, "%*s- sample: %d\n", spaces, "", mConfig.sample_rate);
150    result.append(buffer);
151    snprintf(buffer, SIZE, "%*s- channel mask: %08x\n",
152             spaces, "", mConfig.channel_mask);
153    result.append(buffer);
154    snprintf(buffer, SIZE, "%*s- is soundtrigger: %s\n",
155             spaces, "", mIsSoundTrigger ? "true" : "false");
156    result.append(buffer);
157    snprintf(buffer, SIZE, "%*s- open count: %d\n", spaces, "", mOpenCount);
158    result.append(buffer);
159    snprintf(buffer, SIZE, "%*s- active count: %d\n", spaces, "", mActiveCount);
160    result.append(buffer);
161
162    write(fd, result.string(), result.size());
163    return NO_ERROR;
164}
165
166status_t AudioSessionCollection::addSession(audio_session_t session,
167                                         const sp<AudioSession>& audioSession,
168                                         AudioSessionInfoProvider *provider)
169{
170    ssize_t index = indexOfKey(session);
171
172    if (index >= 0) {
173        ALOGW("addSession() session %d already in", session);
174        return ALREADY_EXISTS;
175    }
176    audioSession->setInfoProvider(provider);
177    add(session, audioSession);
178    ALOGV("addSession() session %d  client %d source %d",
179            session, audioSession->uid(), audioSession->inputSource());
180    return NO_ERROR;
181}
182
183status_t AudioSessionCollection::removeSession(audio_session_t session)
184{
185    ssize_t index = indexOfKey(session);
186
187    if (index < 0) {
188        ALOGW("removeSession() session %d not in", session);
189        return ALREADY_EXISTS;
190    }
191    ALOGV("removeSession() session %d", session);
192    valueAt(index)->setInfoProvider(NULL);
193    removeItemsAt(index);
194    return NO_ERROR;
195}
196
197uint32_t AudioSessionCollection::getOpenCount() const
198{
199    uint32_t openCount = 0;
200    for (size_t i = 0; i < size(); i++) {
201        openCount += valueAt(i)->openCount();
202    }
203    return openCount;
204}
205
206AudioSessionCollection AudioSessionCollection::getActiveSessions() const
207{
208    AudioSessionCollection activeSessions;
209    for (size_t i = 0; i < size(); i++) {
210        if (valueAt(i)->activeCount() != 0) {
211            activeSessions.add(valueAt(i)->session(), valueAt(i));
212        }
213    }
214    return activeSessions;
215}
216
217bool AudioSessionCollection::hasActiveSession() const
218{
219    return getActiveSessions().size() != 0;
220}
221
222bool AudioSessionCollection::isSourceActive(audio_source_t source) const
223{
224    for (size_t i = 0; i < size(); i++) {
225        const sp<AudioSession>  audioSession = valueAt(i);
226        // AUDIO_SOURCE_HOTWORD is equivalent to AUDIO_SOURCE_VOICE_RECOGNITION only if it
227        // corresponds to an active capture triggered by a hardware hotword recognition
228        if (audioSession->activeCount() > 0 &&
229                ((audioSession->inputSource() == source) ||
230                ((source == AUDIO_SOURCE_VOICE_RECOGNITION) &&
231                 (audioSession->inputSource() == AUDIO_SOURCE_HOTWORD) &&
232                 audioSession->isSoundTrigger()))) {
233            return true;
234        }
235    }
236    return false;
237}
238
239void AudioSessionCollection::onSessionInfoUpdate() const
240{
241    for (size_t i = 0; i < size(); i++) {
242        valueAt(i)->onSessionInfoUpdate();
243    }
244}
245
246
247status_t AudioSessionCollection::dump(int fd, int spaces) const
248{
249    const size_t SIZE = 256;
250    char buffer[SIZE];
251    snprintf(buffer, SIZE, "%*sAudio Sessions:\n", spaces, "");
252    write(fd, buffer, strlen(buffer));
253    for (size_t i = 0; i < size(); i++) {
254        valueAt(i)->dump(fd, spaces + 2, i);
255    }
256    return NO_ERROR;
257}
258
259}; // namespace android
260