• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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