AudioSession.cpp revision 4b2fcd8abf90b1bd95539f9f4ef2ac39ce9e2df1
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 "policy.h"
22#include "AudioSession.h"
23#include "AudioGain.h"
24#include "TypeConverter.h"
25#include <cutils/log.h>
26#include <utils/String8.h>
27
28namespace android {
29
30AudioSession::AudioSession(audio_session_t session,
31                           audio_source_t inputSource,
32                           audio_format_t format,
33                           uint32_t sampleRate,
34                           audio_channel_mask_t channelMask,
35                           audio_input_flags_t flags,
36                           uid_t uid,
37                           bool isSoundTrigger,
38                           AudioMix* policyMix,
39                           AudioPolicyClientInterface *clientInterface) :
40    mSession(session), mInputSource(inputSource),
41    mFormat(format), mSampleRate(sampleRate), mChannelMask(channelMask),
42    mFlags(flags), mUid(uid), mIsSoundTrigger(isSoundTrigger),
43    mOpenCount(1), mActiveCount(0), mPolicyMix(policyMix), mClientInterface(clientInterface)
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
70    if ((oldActiveCount == 0) && (mActiveCount > 0)) {
71        // if input maps to a dynamic policy with an activity listener, notify of state change
72        if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
73        {
74            mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId,
75                    MIX_STATE_MIXING);
76        }
77        mClientInterface->onRecordingConfigurationUpdate(RECORD_CONFIG_EVENT_START,
78                mSession, mInputSource);
79    } else if ((oldActiveCount > 0) && (mActiveCount == 0)) {
80        // if input maps to a dynamic policy with an activity listener, notify of state change
81        if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
82        {
83            mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId,
84                    MIX_STATE_IDLE);
85        }
86        mClientInterface->onRecordingConfigurationUpdate(RECORD_CONFIG_EVENT_STOP,
87                mSession, mInputSource);
88    }
89
90    return mActiveCount;
91}
92
93bool AudioSession::matches(const sp<AudioSession> &other) const
94{
95    if (other->session() == mSession &&
96        other->inputSource() == mInputSource &&
97        other->format() == mFormat &&
98        other->sampleRate() == mSampleRate &&
99        other->channelMask() == mChannelMask &&
100        other->flags() == mFlags &&
101        other->uid() == mUid) {
102        return true;
103    }
104    return false;
105}
106
107
108status_t AudioSession::dump(int fd, int spaces, int index) const
109{
110    const size_t SIZE = 256;
111    char buffer[SIZE];
112    String8 result;
113
114    snprintf(buffer, SIZE, "%*sAudio session %d:\n", spaces, "", index+1);
115    result.append(buffer);
116    snprintf(buffer, SIZE, "%*s- session: %2d\n", spaces, "", mSession);
117    result.append(buffer);
118    snprintf(buffer, SIZE, "%*s- owner uid: %2d\n", spaces, "", mUid);
119    result.append(buffer);
120    snprintf(buffer, SIZE, "%*s- input source: %d\n", spaces, "", mInputSource);
121    result.append(buffer);
122    snprintf(buffer, SIZE, "%*s- format: %08x\n", spaces, "", mFormat);
123    result.append(buffer);
124    snprintf(buffer, SIZE, "%*s- sample: %d\n", spaces, "", mSampleRate);
125    result.append(buffer);
126    snprintf(buffer, SIZE, "%*s- channel mask: %08x\n",
127             spaces, "", mChannelMask);
128    result.append(buffer);
129    snprintf(buffer, SIZE, "%*s- is soundtrigger: %s\n",
130             spaces, "", mIsSoundTrigger ? "true" : "false");
131    result.append(buffer);
132    snprintf(buffer, SIZE, "%*s- open count: %d\n", spaces, "", mOpenCount);
133    result.append(buffer);
134    snprintf(buffer, SIZE, "%*s- active count: %d\n", spaces, "", mActiveCount);
135    result.append(buffer);
136
137    write(fd, result.string(), result.size());
138    return NO_ERROR;
139}
140
141status_t AudioSessionCollection::addSession(audio_session_t session,
142                                         const sp<AudioSession>& audioSession)
143{
144    ssize_t index = indexOfKey(session);
145
146    if (index >= 0) {
147        ALOGW("addSession() session %d already in", session);
148        return ALREADY_EXISTS;
149    }
150    add(session, audioSession);
151    ALOGV("addSession() session %d  client %d source %d",
152            session, audioSession->uid(), audioSession->inputSource());
153    return NO_ERROR;
154}
155
156status_t AudioSessionCollection::removeSession(audio_session_t session)
157{
158    ssize_t index = indexOfKey(session);
159
160    if (index < 0) {
161        ALOGW("removeSession() session %d not in", session);
162        return ALREADY_EXISTS;
163    }
164    ALOGV("removeSession() session %d", session);
165    removeItemsAt(index);
166    return NO_ERROR;
167}
168
169uint32_t AudioSessionCollection::getOpenCount() const
170{
171    uint32_t openCount = 0;
172    for (size_t i = 0; i < size(); i++) {
173        openCount += valueAt(i)->openCount();
174    }
175    return openCount;
176}
177
178AudioSessionCollection AudioSessionCollection::getActiveSessions() const
179{
180    AudioSessionCollection activeSessions;
181    for (size_t i = 0; i < size(); i++) {
182        if (valueAt(i)->activeCount() != 0) {
183            activeSessions.add(valueAt(i)->session(), valueAt(i));
184        }
185    }
186    return activeSessions;
187}
188
189bool AudioSessionCollection::hasActiveSession() const
190{
191    return getActiveSessions().size() != 0;
192}
193
194bool AudioSessionCollection::isSourceActive(audio_source_t source) const
195{
196    for (size_t i = 0; i < size(); i++) {
197        const sp<AudioSession>  audioSession = valueAt(i);
198        // AUDIO_SOURCE_HOTWORD is equivalent to AUDIO_SOURCE_VOICE_RECOGNITION only if it
199        // corresponds to an active capture triggered by a hardware hotword recognition
200        if (audioSession->activeCount() > 0 &&
201                ((audioSession->inputSource() == source) ||
202                ((source == AUDIO_SOURCE_VOICE_RECOGNITION) &&
203                 (audioSession->inputSource() == AUDIO_SOURCE_HOTWORD) &&
204                 audioSession->isSoundTrigger()))) {
205            return true;
206        }
207    }
208    return false;
209}
210
211audio_source_t AudioSessionCollection::getHighestPrioritySource(bool activeOnly) const
212{
213    audio_source_t source = AUDIO_SOURCE_DEFAULT;
214    int32_t priority = -1;
215
216    for (size_t i = 0; i < size(); i++) {
217        const sp<AudioSession>  audioSession = valueAt(i);
218        if (activeOnly && audioSession->activeCount() == 0) {
219            continue;
220        }
221        int32_t curPriority = source_priority(audioSession->inputSource());
222        if (curPriority > priority) {
223            priority = curPriority;
224            source = audioSession->inputSource();
225        }
226    }
227    return source;
228}
229
230status_t AudioSessionCollection::dump(int fd, int spaces) const
231{
232    const size_t SIZE = 256;
233    char buffer[SIZE];
234    snprintf(buffer, SIZE, "%*sAudio Sessions:\n", spaces, "");
235    write(fd, buffer, strlen(buffer));
236    for (size_t i = 0; i < size(); i++) {
237        valueAt(i)->dump(fd, spaces + 2, i);
238    }
239    return NO_ERROR;
240}
241
242}; // namespace android
243