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 27namespace android { 28 29AudioSession::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 47uint32_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 59uint32_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 99bool 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 113void AudioSession::setInfoProvider(AudioSessionInfoProvider *provider) 114{ 115 mInfoProvider = provider; 116} 117 118void 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 133status_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 166status_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 183status_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 197uint32_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 206AudioSessionCollection 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 217bool AudioSessionCollection::hasActiveSession() const 218{ 219 return getActiveSessions().size() != 0; 220} 221 222bool 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 239void AudioSessionCollection::onSessionInfoUpdate() const 240{ 241 for (size_t i = 0; i < size(); i++) { 242 valueAt(i)->onSessionInfoUpdate(); 243 } 244} 245 246 247status_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