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
27 namespace android {
28
AudioSession(audio_session_t session,audio_source_t inputSource,audio_format_t format,uint32_t sampleRate,audio_channel_mask_t channelMask,audio_input_flags_t flags,uid_t uid,bool isSoundTrigger,AudioMix * policyMix,AudioPolicyClientInterface * clientInterface)29 AudioSession::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
changeOpenCount(int delta)47 uint32_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
changeActiveCount(int delta)59 uint32_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
matches(const sp<AudioSession> & other) const99 bool 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
setInfoProvider(AudioSessionInfoProvider * provider)113 void AudioSession::setInfoProvider(AudioSessionInfoProvider *provider)
114 {
115 mInfoProvider = provider;
116 }
117
onSessionInfoUpdate() const118 void 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
dump(int fd,int spaces,int index) const133 status_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
addSession(audio_session_t session,const sp<AudioSession> & audioSession,AudioSessionInfoProvider * provider)166 status_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
removeSession(audio_session_t session)183 status_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
getOpenCount() const197 uint32_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
getActiveSessions() const206 AudioSessionCollection 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
hasActiveSession() const217 bool AudioSessionCollection::hasActiveSession() const
218 {
219 return getActiveSessions().size() != 0;
220 }
221
isSourceActive(audio_source_t source) const222 bool 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
onSessionInfoUpdate() const239 void AudioSessionCollection::onSessionInfoUpdate() const
240 {
241 for (size_t i = 0; i < size(); i++) {
242 valueAt(i)->onSessionInfoUpdate();
243 }
244 }
245
246
dump(int fd,int spaces) const247 status_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