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     mRecordClientInfo({ .uid = uid, .session = session, .source = inputSource}),
42     mConfig({ .format = format, .sample_rate = sampleRate, .channel_mask = channelMask}),
43     mFlags(flags), 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, &mRecordClientInfo,
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() == mRecordClientInfo.session &&
106         other->inputSource() == mRecordClientInfo.source &&
107         other->format() == mConfig.format &&
108         other->sampleRate() == mConfig.sample_rate &&
109         other->channelMask() == mConfig.channel_mask &&
110         other->flags() == mFlags &&
111         other->uid() == mRecordClientInfo.uid) {
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                     &mRecordClientInfo, &mConfig, &deviceConfig, patchHandle);
134         }
135     }
136 }
137 
dump(int fd,int spaces,int index) const138 status_t AudioSession::dump(int fd, int spaces, int index) const
139 {
140     const size_t SIZE = 256;
141     char buffer[SIZE];
142     String8 result;
143 
144     snprintf(buffer, SIZE, "%*sAudio session %d:\n", spaces, "", index+1);
145     result.append(buffer);
146     snprintf(buffer, SIZE, "%*s- session: %2d\n", spaces, "", mRecordClientInfo.session);
147     result.append(buffer);
148     snprintf(buffer, SIZE, "%*s- owner uid: %2d\n", spaces, "", mRecordClientInfo.uid);
149     result.append(buffer);
150     snprintf(buffer, SIZE, "%*s- input source: %d\n", spaces, "", mRecordClientInfo.source);
151     result.append(buffer);
152     snprintf(buffer, SIZE, "%*s- format: %08x\n", spaces, "", mConfig.format);
153     result.append(buffer);
154     snprintf(buffer, SIZE, "%*s- sample: %d\n", spaces, "", mConfig.sample_rate);
155     result.append(buffer);
156     snprintf(buffer, SIZE, "%*s- channel mask: %08x\n",
157              spaces, "", mConfig.channel_mask);
158     result.append(buffer);
159     snprintf(buffer, SIZE, "%*s- is soundtrigger: %s\n",
160              spaces, "", mIsSoundTrigger ? "true" : "false");
161     result.append(buffer);
162     snprintf(buffer, SIZE, "%*s- open count: %d\n", spaces, "", mOpenCount);
163     result.append(buffer);
164     snprintf(buffer, SIZE, "%*s- active count: %d\n", spaces, "", mActiveCount);
165     result.append(buffer);
166 
167     write(fd, result.string(), result.size());
168     return NO_ERROR;
169 }
170 
addSession(audio_session_t session,const sp<AudioSession> & audioSession,AudioSessionInfoProvider * provider)171 status_t AudioSessionCollection::addSession(audio_session_t session,
172                                          const sp<AudioSession>& audioSession,
173                                          AudioSessionInfoProvider *provider)
174 {
175     ssize_t index = indexOfKey(session);
176 
177     if (index >= 0) {
178         ALOGW("addSession() session %d already in", session);
179         return ALREADY_EXISTS;
180     }
181     audioSession->setInfoProvider(provider);
182     add(session, audioSession);
183     ALOGV("addSession() session %d  client %d source %d",
184             session, audioSession->uid(), audioSession->inputSource());
185     return NO_ERROR;
186 }
187 
removeSession(audio_session_t session)188 status_t AudioSessionCollection::removeSession(audio_session_t session)
189 {
190     ssize_t index = indexOfKey(session);
191 
192     if (index < 0) {
193         ALOGW("removeSession() session %d not in", session);
194         return ALREADY_EXISTS;
195     }
196     ALOGV("removeSession() session %d", session);
197     valueAt(index)->setInfoProvider(NULL);
198     removeItemsAt(index);
199     return NO_ERROR;
200 }
201 
getOpenCount() const202 uint32_t AudioSessionCollection::getOpenCount() const
203 {
204     uint32_t openCount = 0;
205     for (size_t i = 0; i < size(); i++) {
206         openCount += valueAt(i)->openCount();
207     }
208     return openCount;
209 }
210 
getActiveSessions() const211 AudioSessionCollection AudioSessionCollection::getActiveSessions() const
212 {
213     AudioSessionCollection activeSessions;
214     for (size_t i = 0; i < size(); i++) {
215         if (valueAt(i)->activeCount() != 0) {
216             activeSessions.add(valueAt(i)->session(), valueAt(i));
217         }
218     }
219     return activeSessions;
220 }
221 
getActiveSessionCount() const222 size_t AudioSessionCollection::getActiveSessionCount() const
223 {
224     size_t activeCount = 0;
225     for (size_t i = 0; i < size(); i++) {
226         if (valueAt(i)->activeCount() != 0) {
227             activeCount++;
228         }
229     }
230     return activeCount;
231 }
232 
hasActiveSession() const233 bool AudioSessionCollection::hasActiveSession() const
234 {
235     return getActiveSessionCount() != 0;
236 }
237 
isSourceActive(audio_source_t source) const238 bool AudioSessionCollection::isSourceActive(audio_source_t source) const
239 {
240     for (size_t i = 0; i < size(); i++) {
241         const sp<AudioSession>  audioSession = valueAt(i);
242         // AUDIO_SOURCE_HOTWORD is equivalent to AUDIO_SOURCE_VOICE_RECOGNITION only if it
243         // corresponds to an active capture triggered by a hardware hotword recognition
244         if (audioSession->activeCount() > 0 &&
245                 ((audioSession->inputSource() == source) ||
246                 ((source == AUDIO_SOURCE_VOICE_RECOGNITION) &&
247                  (audioSession->inputSource() == AUDIO_SOURCE_HOTWORD) &&
248                  audioSession->isSoundTrigger()))) {
249             return true;
250         }
251     }
252     return false;
253 }
254 
getHighestPrioritySource(bool activeOnly) const255 audio_source_t AudioSessionCollection::getHighestPrioritySource(bool activeOnly) const
256 {
257     audio_source_t source = AUDIO_SOURCE_DEFAULT;
258     int32_t priority = -1;
259 
260     for (size_t i = 0; i < size(); i++) {
261         const sp<AudioSession>  audioSession = valueAt(i);
262         if (activeOnly && audioSession->activeCount() == 0) {
263             continue;
264         }
265         int32_t curPriority = source_priority(audioSession->inputSource());
266         if (curPriority > priority) {
267             priority = curPriority;
268             source = audioSession->inputSource();
269         }
270     }
271     return source;
272 }
273 
onSessionInfoUpdate() const274 void AudioSessionCollection::onSessionInfoUpdate() const
275 {
276     for (size_t i = 0; i < size(); i++) {
277         valueAt(i)->onSessionInfoUpdate();
278     }
279 }
280 
dump(int fd,int spaces) const281 status_t AudioSessionCollection::dump(int fd, int spaces) const
282 {
283     const size_t SIZE = 256;
284     char buffer[SIZE];
285     snprintf(buffer, SIZE, "%*sAudio Sessions:\n", spaces, "");
286     write(fd, buffer, strlen(buffer));
287     for (size_t i = 0; i < size(); i++) {
288         valueAt(i)->dump(fd, spaces + 2, i);
289     }
290     return NO_ERROR;
291 }
292 
293 } // namespace android
294