AudioSession.cpp revision 2f4fe9f7df8f22c6bc8745407d19df73128810ec
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    mFormat(format), mSampleRate(sampleRate), mChannelMask(channelMask),
41    mFlags(flags), mUid(uid), mIsSoundTrigger(isSoundTrigger),
42    mOpenCount(1), mActiveCount(0), mPolicyMix(policyMix), mClientInterface(clientInterface)
43{
44}
45
46uint32_t AudioSession::changeOpenCount(int delta)
47{
48    if ((delta + (int)mOpenCount) < 0) {
49        ALOGW("%s invalid delta %d, open count %d",
50              __FUNCTION__, delta, mOpenCount);
51        mOpenCount = (uint32_t)(-delta);
52    }
53    mOpenCount += delta;
54    ALOGV("%s open count %d", __FUNCTION__, mOpenCount);
55    return mOpenCount;
56}
57
58uint32_t AudioSession::changeActiveCount(int delta)
59{
60    const uint32_t oldActiveCount = mActiveCount;
61    if ((delta + (int)mActiveCount) < 0) {
62        ALOGW("%s invalid delta %d, active count %d",
63              __FUNCTION__, delta, mActiveCount);
64        mActiveCount = (uint32_t)(-delta);
65    }
66    mActiveCount += delta;
67    ALOGV("%s active count %d", __FUNCTION__, mActiveCount);
68
69    if ((oldActiveCount == 0) && (mActiveCount > 0)) {
70        // if input maps to a dynamic policy with an activity listener, notify of state change
71        if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
72        {
73            mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId,
74                    MIX_STATE_MIXING);
75        }
76        mClientInterface->onRecordingConfigurationUpdate(RECORD_CONFIG_EVENT_START,
77                mSession, mInputSource);
78    } else if ((oldActiveCount > 0) && (mActiveCount == 0)) {
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->mRegistrationId,
83                    MIX_STATE_IDLE);
84        }
85        mClientInterface->onRecordingConfigurationUpdate(RECORD_CONFIG_EVENT_STOP,
86                mSession, mInputSource);
87    }
88
89    return mActiveCount;
90}
91
92bool AudioSession::matches(const sp<AudioSession> &other) const
93{
94    if (other->session() == mSession &&
95        other->inputSource() == mInputSource &&
96        other->format() == mFormat &&
97        other->sampleRate() == mSampleRate &&
98        other->channelMask() == mChannelMask &&
99        other->flags() == mFlags &&
100        other->uid() == mUid) {
101        return true;
102    }
103    return false;
104}
105
106
107status_t AudioSession::dump(int fd, int spaces, int index) const
108{
109    const size_t SIZE = 256;
110    char buffer[SIZE];
111    String8 result;
112
113    snprintf(buffer, SIZE, "%*sAudio session %d:\n", spaces, "", index+1);
114    result.append(buffer);
115    snprintf(buffer, SIZE, "%*s- session: %2d\n", spaces, "", mSession);
116    result.append(buffer);
117    snprintf(buffer, SIZE, "%*s- owner uid: %2d\n", spaces, "", mUid);
118    result.append(buffer);
119    snprintf(buffer, SIZE, "%*s- input source: %d\n", spaces, "", mInputSource);
120    result.append(buffer);
121    snprintf(buffer, SIZE, "%*s- format: %08x\n", spaces, "", mFormat);
122    result.append(buffer);
123    snprintf(buffer, SIZE, "%*s- sample: %d\n", spaces, "", mSampleRate);
124    result.append(buffer);
125    snprintf(buffer, SIZE, "%*s- channel mask: %08x\n",
126             spaces, "", mChannelMask);
127    result.append(buffer);
128    snprintf(buffer, SIZE, "%*s- is soundtrigger: %s\n",
129             spaces, "", mIsSoundTrigger ? "true" : "false");
130    result.append(buffer);
131    snprintf(buffer, SIZE, "%*s- open count: %d\n", spaces, "", mOpenCount);
132    result.append(buffer);
133    snprintf(buffer, SIZE, "%*s- active count: %d\n", spaces, "", mActiveCount);
134    result.append(buffer);
135
136    write(fd, result.string(), result.size());
137    return NO_ERROR;
138}
139
140status_t AudioSessionCollection::addSession(audio_session_t session,
141                                         const sp<AudioSession>& audioSession)
142{
143    ssize_t index = indexOfKey(session);
144
145    if (index >= 0) {
146        ALOGW("addSession() session %d already in", session);
147        return ALREADY_EXISTS;
148    }
149    add(session, audioSession);
150    ALOGV("addSession() session %d  client %d source %d",
151            session, audioSession->uid(), audioSession->inputSource());
152    return NO_ERROR;
153}
154
155status_t AudioSessionCollection::removeSession(audio_session_t session)
156{
157    ssize_t index = indexOfKey(session);
158
159    if (index < 0) {
160        ALOGW("removeSession() session %d not in", session);
161        return ALREADY_EXISTS;
162    }
163    ALOGV("removeSession() session %d", session);
164    removeItemsAt(index);
165    return NO_ERROR;
166}
167
168uint32_t AudioSessionCollection::getOpenCount() const
169{
170    uint32_t openCount = 0;
171    for (size_t i = 0; i < size(); i++) {
172        openCount += valueAt(i)->openCount();
173    }
174    return openCount;
175}
176
177AudioSessionCollection AudioSessionCollection::getActiveSessions() const
178{
179    AudioSessionCollection activeSessions;
180    for (size_t i = 0; i < size(); i++) {
181        if (valueAt(i)->activeCount() != 0) {
182            activeSessions.add(valueAt(i)->session(), valueAt(i));
183        }
184    }
185    return activeSessions;
186}
187
188bool AudioSessionCollection::hasActiveSession() const
189{
190    return getActiveSessions().size() != 0;
191}
192
193bool AudioSessionCollection::isSourceActive(audio_source_t source) const
194{
195    for (size_t i = 0; i < size(); i++) {
196        const sp<AudioSession>  audioSession = valueAt(i);
197        // AUDIO_SOURCE_HOTWORD is equivalent to AUDIO_SOURCE_VOICE_RECOGNITION only if it
198        // corresponds to an active capture triggered by a hardware hotword recognition
199        if (audioSession->activeCount() > 0 &&
200                ((audioSession->inputSource() == source) ||
201                ((source == AUDIO_SOURCE_VOICE_RECOGNITION) &&
202                 (audioSession->inputSource() == AUDIO_SOURCE_HOTWORD) &&
203                 audioSession->isSoundTrigger()))) {
204            return true;
205        }
206    }
207    return false;
208}
209
210
211status_t AudioSessionCollection::dump(int fd, int spaces) const
212{
213    const size_t SIZE = 256;
214    char buffer[SIZE];
215    snprintf(buffer, SIZE, "%*sAudio Sessions:\n", spaces, "");
216    write(fd, buffer, strlen(buffer));
217    for (size_t i = 0; i < size(); i++) {
218        valueAt(i)->dump(fd, spaces + 2, i);
219    }
220    return NO_ERROR;
221}
222
223}; // namespace android
224