AudioSession.cpp revision 2f4fe9f7df8f22c6bc8745407d19df73128810ec
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 mFormat(format), mSampleRate(sampleRate), mChannelMask(channelMask), 41 mFlags(flags), mUid(uid), mIsSoundTrigger(isSoundTrigger), 42 mOpenCount(1), mActiveCount(0), mPolicyMix(policyMix), mClientInterface(clientInterface) 43{ 44} 45 46uint32_t AudioSession::changeOpenCount(int delta) 47{ 48 if ((delta + (int)mOpenCount) < 0) { 49 ALOGW("%s invalid delta %d, open count %d", 50 __FUNCTION__, delta, mOpenCount); 51 mOpenCount = (uint32_t)(-delta); 52 } 53 mOpenCount += delta; 54 ALOGV("%s open count %d", __FUNCTION__, mOpenCount); 55 return mOpenCount; 56} 57 58uint32_t AudioSession::changeActiveCount(int delta) 59{ 60 const uint32_t oldActiveCount = mActiveCount; 61 if ((delta + (int)mActiveCount) < 0) { 62 ALOGW("%s invalid delta %d, active count %d", 63 __FUNCTION__, delta, mActiveCount); 64 mActiveCount = (uint32_t)(-delta); 65 } 66 mActiveCount += delta; 67 ALOGV("%s active count %d", __FUNCTION__, mActiveCount); 68 69 if ((oldActiveCount == 0) && (mActiveCount > 0)) { 70 // if input maps to a dynamic policy with an activity listener, notify of state change 71 if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) 72 { 73 mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId, 74 MIX_STATE_MIXING); 75 } 76 mClientInterface->onRecordingConfigurationUpdate(RECORD_CONFIG_EVENT_START, 77 mSession, mInputSource); 78 } else if ((oldActiveCount > 0) && (mActiveCount == 0)) { 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->mRegistrationId, 83 MIX_STATE_IDLE); 84 } 85 mClientInterface->onRecordingConfigurationUpdate(RECORD_CONFIG_EVENT_STOP, 86 mSession, mInputSource); 87 } 88 89 return mActiveCount; 90} 91 92bool AudioSession::matches(const sp<AudioSession> &other) const 93{ 94 if (other->session() == mSession && 95 other->inputSource() == mInputSource && 96 other->format() == mFormat && 97 other->sampleRate() == mSampleRate && 98 other->channelMask() == mChannelMask && 99 other->flags() == mFlags && 100 other->uid() == mUid) { 101 return true; 102 } 103 return false; 104} 105 106 107status_t AudioSession::dump(int fd, int spaces, int index) const 108{ 109 const size_t SIZE = 256; 110 char buffer[SIZE]; 111 String8 result; 112 113 snprintf(buffer, SIZE, "%*sAudio session %d:\n", spaces, "", index+1); 114 result.append(buffer); 115 snprintf(buffer, SIZE, "%*s- session: %2d\n", spaces, "", mSession); 116 result.append(buffer); 117 snprintf(buffer, SIZE, "%*s- owner uid: %2d\n", spaces, "", mUid); 118 result.append(buffer); 119 snprintf(buffer, SIZE, "%*s- input source: %d\n", spaces, "", mInputSource); 120 result.append(buffer); 121 snprintf(buffer, SIZE, "%*s- format: %08x\n", spaces, "", mFormat); 122 result.append(buffer); 123 snprintf(buffer, SIZE, "%*s- sample: %d\n", spaces, "", mSampleRate); 124 result.append(buffer); 125 snprintf(buffer, SIZE, "%*s- channel mask: %08x\n", 126 spaces, "", mChannelMask); 127 result.append(buffer); 128 snprintf(buffer, SIZE, "%*s- is soundtrigger: %s\n", 129 spaces, "", mIsSoundTrigger ? "true" : "false"); 130 result.append(buffer); 131 snprintf(buffer, SIZE, "%*s- open count: %d\n", spaces, "", mOpenCount); 132 result.append(buffer); 133 snprintf(buffer, SIZE, "%*s- active count: %d\n", spaces, "", mActiveCount); 134 result.append(buffer); 135 136 write(fd, result.string(), result.size()); 137 return NO_ERROR; 138} 139 140status_t AudioSessionCollection::addSession(audio_session_t session, 141 const sp<AudioSession>& audioSession) 142{ 143 ssize_t index = indexOfKey(session); 144 145 if (index >= 0) { 146 ALOGW("addSession() session %d already in", session); 147 return ALREADY_EXISTS; 148 } 149 add(session, audioSession); 150 ALOGV("addSession() session %d client %d source %d", 151 session, audioSession->uid(), audioSession->inputSource()); 152 return NO_ERROR; 153} 154 155status_t AudioSessionCollection::removeSession(audio_session_t session) 156{ 157 ssize_t index = indexOfKey(session); 158 159 if (index < 0) { 160 ALOGW("removeSession() session %d not in", session); 161 return ALREADY_EXISTS; 162 } 163 ALOGV("removeSession() session %d", session); 164 removeItemsAt(index); 165 return NO_ERROR; 166} 167 168uint32_t AudioSessionCollection::getOpenCount() const 169{ 170 uint32_t openCount = 0; 171 for (size_t i = 0; i < size(); i++) { 172 openCount += valueAt(i)->openCount(); 173 } 174 return openCount; 175} 176 177AudioSessionCollection AudioSessionCollection::getActiveSessions() const 178{ 179 AudioSessionCollection activeSessions; 180 for (size_t i = 0; i < size(); i++) { 181 if (valueAt(i)->activeCount() != 0) { 182 activeSessions.add(valueAt(i)->session(), valueAt(i)); 183 } 184 } 185 return activeSessions; 186} 187 188bool AudioSessionCollection::hasActiveSession() const 189{ 190 return getActiveSessions().size() != 0; 191} 192 193bool AudioSessionCollection::isSourceActive(audio_source_t source) const 194{ 195 for (size_t i = 0; i < size(); i++) { 196 const sp<AudioSession> audioSession = valueAt(i); 197 // AUDIO_SOURCE_HOTWORD is equivalent to AUDIO_SOURCE_VOICE_RECOGNITION only if it 198 // corresponds to an active capture triggered by a hardware hotword recognition 199 if (audioSession->activeCount() > 0 && 200 ((audioSession->inputSource() == source) || 201 ((source == AUDIO_SOURCE_VOICE_RECOGNITION) && 202 (audioSession->inputSource() == AUDIO_SOURCE_HOTWORD) && 203 audioSession->isSoundTrigger()))) { 204 return true; 205 } 206 } 207 return false; 208} 209 210 211status_t AudioSessionCollection::dump(int fd, int spaces) const 212{ 213 const size_t SIZE = 256; 214 char buffer[SIZE]; 215 snprintf(buffer, SIZE, "%*sAudio Sessions:\n", spaces, ""); 216 write(fd, buffer, strlen(buffer)); 217 for (size_t i = 0; i < size(); i++) { 218 valueAt(i)->dump(fd, spaces + 2, i); 219 } 220 return NO_ERROR; 221} 222 223}; // namespace android 224