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 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 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 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 103 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 117 void AudioSession::setInfoProvider(AudioSessionInfoProvider *provider) 118 { 119 mInfoProvider = provider; 120 } 121 122 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 138 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 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 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 202 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 211 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 222 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 233 bool AudioSessionCollection::hasActiveSession() const 234 { 235 return getActiveSessionCount() != 0; 236 } 237 238 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 255 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 274 void AudioSessionCollection::onSessionInfoUpdate() const 275 { 276 for (size_t i = 0; i < size(); i++) { 277 valueAt(i)->onSessionInfoUpdate(); 278 } 279 } 280 281 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