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::EffectDescriptor" 18 //#define LOG_NDEBUG 0 19 20 #include "EffectDescriptor.h" 21 #include <utils/String8.h> 22 23 namespace android { 24 25 void EffectDescriptor::dump(String8 *dst, int spaces) const 26 { 27 dst->appendFormat("%*sID: %d\n", spaces, "", mId); 28 dst->appendFormat("%*sI/O: %d\n", spaces, "", mIo); 29 dst->appendFormat("%*sMusic Effect: %s\n", spaces, "", isMusicEffect()? "yes" : "no"); 30 dst->appendFormat("%*sSession: %d\n", spaces, "", mSession); 31 dst->appendFormat("%*sName: %s\n", spaces, "", mDesc.name); 32 dst->appendFormat("%*s%s\n", spaces, "", mEnabled ? "Enabled" : "Disabled"); 33 dst->appendFormat("%*s%s\n", spaces, "", mSuspended ? "Suspended" : "Active"); 34 } 35 36 EffectDescriptorCollection::EffectDescriptorCollection() : 37 mTotalEffectsCpuLoad(0), 38 mTotalEffectsMemory(0), 39 mTotalEffectsMemoryMaxUsed(0) 40 { 41 42 } 43 44 status_t EffectDescriptorCollection::registerEffect(const effect_descriptor_t *desc, 45 audio_io_handle_t io, 46 int session, 47 int id, bool isMusicEffect) 48 { 49 if (getEffect(id) != nullptr) { 50 ALOGW("%s effect %s already registered", __FUNCTION__, desc->name); 51 return INVALID_OPERATION; 52 } 53 54 if (mTotalEffectsMemory + desc->memoryUsage > getMaxEffectsMemory()) { 55 ALOGW("registerEffect() memory limit exceeded for Fx %s, Memory %d KB", 56 desc->name, desc->memoryUsage); 57 return INVALID_OPERATION; 58 } 59 mTotalEffectsMemory += desc->memoryUsage; 60 if (mTotalEffectsMemory > mTotalEffectsMemoryMaxUsed) { 61 mTotalEffectsMemoryMaxUsed = mTotalEffectsMemory; 62 } 63 ALOGV("registerEffect() effect %s, io %d, session %d id %d", 64 desc->name, io, session, id); 65 ALOGV("registerEffect() memory %d, total memory %d", desc->memoryUsage, mTotalEffectsMemory); 66 67 sp<EffectDescriptor> effectDesc = 68 new EffectDescriptor(desc, isMusicEffect, id, io, (audio_session_t)session); 69 add(id, effectDesc); 70 71 return NO_ERROR; 72 } 73 74 sp<EffectDescriptor> EffectDescriptorCollection::getEffect(int id) const 75 { 76 ssize_t index = indexOfKey(id); 77 if (index < 0) { 78 return nullptr; 79 } 80 return valueAt(index); 81 } 82 83 status_t EffectDescriptorCollection::unregisterEffect(int id) 84 { 85 sp<EffectDescriptor> effectDesc = getEffect(id); 86 if (effectDesc == nullptr) { 87 ALOGW("%s unknown effect ID %d", __FUNCTION__, id); 88 return INVALID_OPERATION; 89 } 90 91 if (mTotalEffectsMemory < effectDesc->mDesc.memoryUsage) { 92 ALOGW("unregisterEffect() memory %d too big for total %d", 93 effectDesc->mDesc.memoryUsage, mTotalEffectsMemory); 94 effectDesc->mDesc.memoryUsage = mTotalEffectsMemory; 95 } 96 mTotalEffectsMemory -= effectDesc->mDesc.memoryUsage; 97 ALOGV("unregisterEffect() effect %s, ID %d, memory %d total memory %d", 98 effectDesc->mDesc.name, id, effectDesc->mDesc.memoryUsage, mTotalEffectsMemory); 99 100 removeItem(id); 101 102 return NO_ERROR; 103 } 104 105 status_t EffectDescriptorCollection::setEffectEnabled(int id, bool enabled) 106 { 107 ssize_t index = indexOfKey(id); 108 if (index < 0) { 109 ALOGW("unregisterEffect() unknown effect ID %d", id); 110 return INVALID_OPERATION; 111 } 112 113 return setEffectEnabled(valueAt(index), enabled); 114 } 115 116 bool EffectDescriptorCollection::isEffectEnabled(int id) const 117 { 118 ssize_t index = indexOfKey(id); 119 if (index < 0) { 120 return false; 121 } 122 return valueAt(index)->mEnabled; 123 } 124 125 status_t EffectDescriptorCollection::setEffectEnabled(const sp<EffectDescriptor> &effectDesc, 126 bool enabled) 127 { 128 if (enabled == effectDesc->mEnabled) { 129 ALOGV("setEffectEnabled(%s) effect already %s", 130 enabled?"true":"false", enabled?"enabled":"disabled"); 131 return INVALID_OPERATION; 132 } 133 134 if (enabled) { 135 if (mTotalEffectsCpuLoad + effectDesc->mDesc.cpuLoad > getMaxEffectsCpuLoad()) { 136 ALOGW("setEffectEnabled(true) CPU Load limit exceeded for Fx %s, CPU %f MIPS", 137 effectDesc->mDesc.name, (float)effectDesc->mDesc.cpuLoad/10); 138 return INVALID_OPERATION; 139 } 140 mTotalEffectsCpuLoad += effectDesc->mDesc.cpuLoad; 141 ALOGV("setEffectEnabled(true) total CPU %d", mTotalEffectsCpuLoad); 142 } else { 143 if (mTotalEffectsCpuLoad < effectDesc->mDesc.cpuLoad) { 144 ALOGW("setEffectEnabled(false) CPU load %d too high for total %d", 145 effectDesc->mDesc.cpuLoad, mTotalEffectsCpuLoad); 146 effectDesc->mDesc.cpuLoad = mTotalEffectsCpuLoad; 147 } 148 mTotalEffectsCpuLoad -= effectDesc->mDesc.cpuLoad; 149 ALOGV("setEffectEnabled(false) total CPU %d", mTotalEffectsCpuLoad); 150 } 151 effectDesc->mEnabled = enabled; 152 return NO_ERROR; 153 } 154 155 bool EffectDescriptorCollection::isNonOffloadableEffectEnabled() const 156 { 157 for (size_t i = 0; i < size(); i++) { 158 sp<EffectDescriptor> effectDesc = valueAt(i); 159 if (effectDesc->mEnabled && (effectDesc->isMusicEffect()) && 160 ((effectDesc->mDesc.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) == 0)) { 161 ALOGV("isNonOffloadableEffectEnabled() non offloadable effect %s enabled on session %d", 162 effectDesc->mDesc.name, effectDesc->mSession); 163 return true; 164 } 165 } 166 return false; 167 } 168 169 uint32_t EffectDescriptorCollection::getMaxEffectsCpuLoad() const 170 { 171 return MAX_EFFECTS_CPU_LOAD; 172 } 173 174 uint32_t EffectDescriptorCollection::getMaxEffectsMemory() const 175 { 176 return MAX_EFFECTS_MEMORY; 177 } 178 179 void EffectDescriptorCollection::moveEffects(audio_session_t session, 180 audio_io_handle_t srcOutput, 181 audio_io_handle_t dstOutput) 182 { 183 ALOGV("%s session %d srcOutput %d dstOutput %d", __func__, session, srcOutput, dstOutput); 184 for (size_t i = 0; i < size(); i++) { 185 sp<EffectDescriptor> effect = valueAt(i); 186 if (effect->mSession == session && effect->mIo == srcOutput) { 187 effect->mIo = dstOutput; 188 } 189 } 190 } 191 192 void EffectDescriptorCollection::moveEffects(const std::vector<int>& ids, 193 audio_io_handle_t dstOutput) 194 { 195 ALOGV("%s num effects %zu, first ID %d, dstOutput %d", 196 __func__, ids.size(), ids.size() ? ids[0] : 0, dstOutput); 197 for (size_t i = 0; i < size(); i++) { 198 sp<EffectDescriptor> effect = valueAt(i); 199 if (std::find(begin(ids), end(ids), effect->mId) != end(ids)) { 200 effect->mIo = dstOutput; 201 } 202 } 203 } 204 205 EffectDescriptorCollection EffectDescriptorCollection::getEffectsForIo(audio_io_handle_t io) const 206 { 207 EffectDescriptorCollection effects; 208 for (size_t i = 0; i < size(); i++) { 209 if (valueAt(i)->mIo == io) { 210 effects.add(keyAt(i), valueAt(i)); 211 } 212 } 213 return effects; 214 } 215 216 void EffectDescriptorCollection::dump(String8 *dst, int spaces, bool verbose) const 217 { 218 if (verbose) { 219 dst->appendFormat( 220 "\n%*sTotal Effects CPU: %f MIPS, " 221 "Total Effects memory: %d KB, Max memory used: %d KB\n", 222 spaces, "", 223 (float) mTotalEffectsCpuLoad / 10, 224 mTotalEffectsMemory, 225 mTotalEffectsMemoryMaxUsed); 226 } 227 dst->appendFormat("%*sEffects:\n", spaces, ""); 228 for (size_t i = 0; i < size(); i++) { 229 dst->appendFormat("%*s- Effect %d:\n", spaces, "", keyAt(i)); 230 valueAt(i)->dump(dst, spaces + 2); 231 } 232 } 233 234 }; //namespace android 235