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