AudioPolicyMix.cpp revision c75307b73d324d590d0dbc05b44bce9aa89b7145
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::AudioPolicyMix" 18//#define LOG_NDEBUG 0 19 20#include "AudioPolicyMix.h" 21#include "HwModule.h" 22#include "AudioPort.h" 23#include "IOProfile.h" 24#include "AudioGain.h" 25#include <AudioOutputDescriptor.h> 26 27namespace android { 28 29void AudioPolicyMix::setOutput(sp<SwAudioOutputDescriptor> &output) 30{ 31 mOutput = output; 32} 33 34const sp<SwAudioOutputDescriptor> &AudioPolicyMix::getOutput() const 35{ 36 return mOutput; 37} 38 39void AudioPolicyMix::clearOutput() 40{ 41 mOutput.clear(); 42} 43 44void AudioPolicyMix::setMix(AudioMix &mix) 45{ 46 mMix = mix; 47} 48 49android::AudioMix &AudioPolicyMix::getMix() 50{ 51 return mMix; 52} 53 54status_t AudioPolicyMixCollection::registerMix(String8 address, AudioMix mix) 55{ 56 ssize_t index = indexOfKey(address); 57 if (index >= 0) { 58 ALOGE("registerPolicyMixes(): mix for address %s already registered", address.string()); 59 return BAD_VALUE; 60 } 61 sp<AudioPolicyMix> policyMix = new AudioPolicyMix(); 62 policyMix->setMix(mix); 63 add(address, policyMix); 64 return NO_ERROR; 65} 66 67status_t AudioPolicyMixCollection::unregisterMix(String8 address) 68{ 69 ssize_t index = indexOfKey(address); 70 if (index < 0) { 71 ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string()); 72 return BAD_VALUE; 73 } 74 75 removeItemsAt(index); 76 return NO_ERROR; 77} 78 79status_t AudioPolicyMixCollection::getAudioPolicyMix(String8 address, 80 sp<AudioPolicyMix> &policyMix) const 81{ 82 ssize_t index = indexOfKey(address); 83 if (index < 0) { 84 ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string()); 85 return BAD_VALUE; 86 } 87 policyMix = valueAt(index); 88 return NO_ERROR; 89} 90 91void AudioPolicyMixCollection::closeOutput(sp<SwAudioOutputDescriptor> &desc) 92{ 93 for (size_t i = 0; i < size(); i++) { 94 sp<AudioPolicyMix> policyMix = valueAt(i); 95 if (policyMix->getOutput() == desc) { 96 policyMix->clearOutput(); 97 } 98 } 99} 100 101status_t AudioPolicyMixCollection::getOutputForAttr(audio_attributes_t attributes, 102 sp<SwAudioOutputDescriptor> &desc) 103{ 104 for (size_t i = 0; i < size(); i++) { 105 sp<AudioPolicyMix> policyMix = valueAt(i); 106 AudioMix mix = policyMix->getMix(); 107 108 if (mix.mMixType == MIX_TYPE_PLAYERS) { 109 for (size_t j = 0; j < mix.mCriteria.size(); j++) { 110 if ((RULE_MATCH_ATTRIBUTE_USAGE == mix.mCriteria[j].mRule && 111 mix.mCriteria[j].mAttr.mUsage == attributes.usage) || 112 (RULE_EXCLUDE_ATTRIBUTE_USAGE == mix.mCriteria[j].mRule && 113 mix.mCriteria[j].mAttr.mUsage != attributes.usage)) { 114 desc = policyMix->getOutput(); 115 break; 116 } 117 if (strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 && 118 strncmp(attributes.tags + strlen("addr="), 119 mix.mRegistrationId.string(), 120 AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) { 121 desc = policyMix->getOutput(); 122 break; 123 } 124 } 125 } else if (mix.mMixType == MIX_TYPE_RECORDERS) { 126 if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE && 127 strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 && 128 strncmp(attributes.tags + strlen("addr="), 129 mix.mRegistrationId.string(), 130 AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) { 131 desc = policyMix->getOutput(); 132 } 133 } 134 if (desc != 0) { 135 desc->mPolicyMix = &mix; 136 return NO_ERROR; 137 } 138 } 139 return BAD_VALUE; 140} 141 142audio_devices_t AudioPolicyMixCollection::getDeviceAndMixForInputSource(audio_source_t inputSource, 143 audio_devices_t availDevices, 144 AudioMix **policyMix) 145{ 146 for (size_t i = 0; i < size(); i++) { 147 AudioMix mix = valueAt(i)->getMix(); 148 149 if (mix.mMixType != MIX_TYPE_RECORDERS) { 150 continue; 151 } 152 for (size_t j = 0; j < mix.mCriteria.size(); j++) { 153 if ((RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET == mix.mCriteria[j].mRule && 154 mix.mCriteria[j].mAttr.mSource == inputSource) || 155 (RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET == mix.mCriteria[j].mRule && 156 mix.mCriteria[j].mAttr.mSource != inputSource)) { 157 if (availDevices & AUDIO_DEVICE_IN_REMOTE_SUBMIX) { 158 if (policyMix != NULL) { 159 *policyMix = &mix; 160 } 161 return AUDIO_DEVICE_IN_REMOTE_SUBMIX; 162 } 163 break; 164 } 165 } 166 } 167 return AUDIO_DEVICE_NONE; 168} 169 170status_t AudioPolicyMixCollection::getInputMixForAttr(audio_attributes_t attr, AudioMix *&policyMix) 171{ 172 if (strncmp(attr.tags, "addr=", strlen("addr=")) != 0) { 173 return BAD_VALUE; 174 } 175 String8 address(attr.tags + strlen("addr=")); 176 177 ssize_t index = indexOfKey(address); 178 if (index < 0) { 179 ALOGW("getInputForAttr() no policy for address %s", address.string()); 180 return BAD_VALUE; 181 } 182 sp<AudioPolicyMix> audioPolicyMix = valueAt(index); 183 AudioMix mix = audioPolicyMix->getMix(); 184 185 if (mix.mMixType != MIX_TYPE_PLAYERS) { 186 ALOGW("getInputForAttr() bad policy mix type for address %s", address.string()); 187 return BAD_VALUE; 188 } 189 policyMix = &mix; 190 return NO_ERROR; 191} 192 193}; //namespace android 194