AudioSession.cpp revision fb66dd9f95a1168698f072c4e5c2a2cf8c49a80f
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#include <cutils/log.h> 26#include <utils/String8.h> 27 28namespace android { 29 30AudioSession::AudioSession(audio_session_t session, 31 audio_source_t inputSource, 32 audio_format_t format, 33 uint32_t sampleRate, 34 audio_channel_mask_t channelMask, 35 audio_input_flags_t flags, 36 uid_t uid, 37 bool isSoundTrigger, 38 AudioMix* policyMix, 39 AudioPolicyClientInterface *clientInterface) : 40 mSession(session), mInputSource(inputSource), 41 mFormat(format), mSampleRate(sampleRate), mChannelMask(channelMask), 42 mFlags(flags), mUid(uid), mIsSoundTrigger(isSoundTrigger), 43 mOpenCount(1), mActiveCount(0), mPolicyMix(policyMix), mClientInterface(clientInterface) 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 70 if ((oldActiveCount == 0) && (mActiveCount > 0)) { 71 // if input maps to a dynamic policy with an activity listener, notify of state change 72 if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) 73 { 74 mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId, 75 MIX_STATE_MIXING); 76 } 77 mClientInterface->onRecordingConfigurationUpdate(RECORD_CONFIG_EVENT_START, 78 mSession, mInputSource); 79 } else if ((oldActiveCount > 0) && (mActiveCount == 0)) { 80 // if input maps to a dynamic policy with an activity listener, notify of state change 81 if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) 82 { 83 mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId, 84 MIX_STATE_IDLE); 85 } 86 mClientInterface->onRecordingConfigurationUpdate(RECORD_CONFIG_EVENT_STOP, 87 mSession, mInputSource); 88 } 89 90 return mActiveCount; 91} 92 93bool AudioSession::matches(const sp<AudioSession> &other) const 94{ 95 if (other->session() == mSession && 96 other->inputSource() == mInputSource && 97 other->format() == mFormat && 98 other->sampleRate() == mSampleRate && 99 other->channelMask() == mChannelMask && 100 other->flags() == mFlags && 101 other->uid() == mUid) { 102 return true; 103 } 104 return false; 105} 106 107 108status_t AudioSession::dump(int fd, int spaces, int index) const 109{ 110 const size_t SIZE = 256; 111 char buffer[SIZE]; 112 String8 result; 113 114 snprintf(buffer, SIZE, "%*sAudio session %d:\n", spaces, "", index+1); 115 result.append(buffer); 116 snprintf(buffer, SIZE, "%*s- session: %2d\n", spaces, "", mSession); 117 result.append(buffer); 118 snprintf(buffer, SIZE, "%*s- owner uid: %2d\n", spaces, "", mUid); 119 result.append(buffer); 120 snprintf(buffer, SIZE, "%*s- input source: %d\n", spaces, "", mInputSource); 121 result.append(buffer); 122 snprintf(buffer, SIZE, "%*s- format: %08x\n", spaces, "", mFormat); 123 result.append(buffer); 124 snprintf(buffer, SIZE, "%*s- sample: %d\n", spaces, "", mSampleRate); 125 result.append(buffer); 126 snprintf(buffer, SIZE, "%*s- channel mask: %08x\n", 127 spaces, "", mChannelMask); 128 result.append(buffer); 129 snprintf(buffer, SIZE, "%*s- is soundtrigger: %s\n", 130 spaces, "", mIsSoundTrigger ? "true" : "false"); 131 result.append(buffer); 132 snprintf(buffer, SIZE, "%*s- open count: %d\n", spaces, "", mOpenCount); 133 result.append(buffer); 134 snprintf(buffer, SIZE, "%*s- active count: %d\n", spaces, "", mActiveCount); 135 result.append(buffer); 136 137 write(fd, result.string(), result.size()); 138 return NO_ERROR; 139} 140 141status_t AudioSessionCollection::addSession(audio_session_t session, 142 const sp<AudioSession>& audioSession) 143{ 144 ssize_t index = indexOfKey(session); 145 146 if (index >= 0) { 147 ALOGW("addSession() session %d already in", session); 148 return ALREADY_EXISTS; 149 } 150 add(session, audioSession); 151 ALOGV("addSession() session %d client %d source %d", 152 session, audioSession->uid(), audioSession->inputSource()); 153 return NO_ERROR; 154} 155 156status_t AudioSessionCollection::removeSession(audio_session_t session) 157{ 158 ssize_t index = indexOfKey(session); 159 160 if (index < 0) { 161 ALOGW("removeSession() session %d not in", session); 162 return ALREADY_EXISTS; 163 } 164 ALOGV("removeSession() session %d", session); 165 removeItemsAt(index); 166 return NO_ERROR; 167} 168 169uint32_t AudioSessionCollection::getOpenCount() const 170{ 171 uint32_t openCount = 0; 172 for (size_t i = 0; i < size(); i++) { 173 openCount += valueAt(i)->openCount(); 174 } 175 return openCount; 176} 177 178AudioSessionCollection AudioSessionCollection::getActiveSessions() const 179{ 180 AudioSessionCollection activeSessions; 181 for (size_t i = 0; i < size(); i++) { 182 if (valueAt(i)->activeCount() != 0) { 183 activeSessions.add(valueAt(i)->session(), valueAt(i)); 184 } 185 } 186 return activeSessions; 187} 188 189bool AudioSessionCollection::hasActiveSession() const 190{ 191 return getActiveSessions().size() != 0; 192} 193 194bool AudioSessionCollection::isSourceActive(audio_source_t source) const 195{ 196 for (size_t i = 0; i < size(); i++) { 197 const sp<AudioSession> audioSession = valueAt(i); 198 // AUDIO_SOURCE_HOTWORD is equivalent to AUDIO_SOURCE_VOICE_RECOGNITION only if it 199 // corresponds to an active capture triggered by a hardware hotword recognition 200 if (audioSession->activeCount() > 0 && 201 ((audioSession->inputSource() == source) || 202 ((source == AUDIO_SOURCE_VOICE_RECOGNITION) && 203 (audioSession->inputSource() == AUDIO_SOURCE_HOTWORD) && 204 audioSession->isSoundTrigger()))) { 205 return true; 206 } 207 } 208 return false; 209} 210 211audio_source_t AudioSessionCollection::getHighestPrioritySource(bool activeOnly) const 212{ 213 audio_source_t source = AUDIO_SOURCE_DEFAULT; 214 int32_t priority = -1; 215 216 for (size_t i = 0; i < size(); i++) { 217 const sp<AudioSession> audioSession = valueAt(i); 218 if (activeOnly && audioSession->activeCount() == 0) { 219 continue; 220 } 221 int32_t curPriority = source_priority(audioSession->inputSource()); 222 if (curPriority > priority) { 223 priority = curPriority; 224 source = audioSession->inputSource(); 225 } 226 } 227 return source; 228} 229 230status_t AudioSessionCollection::dump(int fd, int spaces) const 231{ 232 const size_t SIZE = 256; 233 char buffer[SIZE]; 234 snprintf(buffer, SIZE, "%*sAudio Sessions:\n", spaces, ""); 235 write(fd, buffer, strlen(buffer)); 236 for (size_t i = 0; i < size(); i++) { 237 valueAt(i)->dump(fd, spaces + 2, i); 238 } 239 return NO_ERROR; 240} 241 242}; // namespace android 243