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