• 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 "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