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 
dump(int fd)25 status_t EffectDescriptor::dump(int fd)
26 {
27     const size_t SIZE = 256;
28     char buffer[SIZE];
29     String8 result;
30 
31     snprintf(buffer, SIZE, " I/O: %d\n", mIo);
32     result.append(buffer);
33     snprintf(buffer, SIZE, " Strategy: %d\n", mStrategy);
34     result.append(buffer);
35     snprintf(buffer, SIZE, " Session: %d\n", mSession);
36     result.append(buffer);
37     snprintf(buffer, SIZE, " Name: %s\n",  mDesc.name);
38     result.append(buffer);
39     snprintf(buffer, SIZE, " %s\n",  mEnabled ? "Enabled" : "Disabled");
40     result.append(buffer);
41     write(fd, result.string(), result.size());
42 
43     return NO_ERROR;
44 }
45 
EffectDescriptorCollection()46 EffectDescriptorCollection::EffectDescriptorCollection() :
47     mTotalEffectsCpuLoad(0),
48     mTotalEffectsMemory(0)
49 {
50 
51 }
52 
registerEffect(const effect_descriptor_t * desc,audio_io_handle_t io,uint32_t strategy,int session,int id)53 status_t EffectDescriptorCollection::registerEffect(const effect_descriptor_t *desc,
54                                                     audio_io_handle_t io,
55                                                     uint32_t strategy,
56                                                     int session,
57                                                     int id)
58 {
59     if (mTotalEffectsMemory + desc->memoryUsage > getMaxEffectsMemory()) {
60         ALOGW("registerEffect() memory limit exceeded for Fx %s, Memory %d KB",
61                 desc->name, desc->memoryUsage);
62         return INVALID_OPERATION;
63     }
64     mTotalEffectsMemory += desc->memoryUsage;
65     ALOGV("registerEffect() effect %s, io %d, strategy %d session %d id %d",
66             desc->name, io, strategy, session, id);
67     ALOGV("registerEffect() memory %d, total memory %d", desc->memoryUsage, mTotalEffectsMemory);
68 
69     sp<EffectDescriptor> effectDesc = new EffectDescriptor();
70     memcpy (&effectDesc->mDesc, desc, sizeof(effect_descriptor_t));
71     effectDesc->mIo = io;
72     effectDesc->mStrategy = static_cast<routing_strategy>(strategy);
73     effectDesc->mSession = session;
74     effectDesc->mEnabled = false;
75 
76     add(id, effectDesc);
77 
78     return NO_ERROR;
79 }
80 
unregisterEffect(int id)81 status_t EffectDescriptorCollection::unregisterEffect(int id)
82 {
83     ssize_t index = indexOfKey(id);
84     if (index < 0) {
85         ALOGW("unregisterEffect() unknown effect ID %d", id);
86         return INVALID_OPERATION;
87     }
88 
89     sp<EffectDescriptor> effectDesc = valueAt(index);
90 
91     setEffectEnabled(effectDesc, false);
92 
93     if (mTotalEffectsMemory < effectDesc->mDesc.memoryUsage) {
94         ALOGW("unregisterEffect() memory %d too big for total %d",
95                 effectDesc->mDesc.memoryUsage, mTotalEffectsMemory);
96         effectDesc->mDesc.memoryUsage = mTotalEffectsMemory;
97     }
98     mTotalEffectsMemory -= effectDesc->mDesc.memoryUsage;
99     ALOGV("unregisterEffect() effect %s, ID %d, memory %d total memory %d",
100             effectDesc->mDesc.name, id, effectDesc->mDesc.memoryUsage, mTotalEffectsMemory);
101 
102     removeItem(id);
103 
104     return NO_ERROR;
105 }
106 
setEffectEnabled(int id,bool enabled)107 status_t EffectDescriptorCollection::setEffectEnabled(int id, bool enabled)
108 {
109     ssize_t index = indexOfKey(id);
110     if (index < 0) {
111         ALOGW("unregisterEffect() unknown effect ID %d", id);
112         return INVALID_OPERATION;
113     }
114 
115     return setEffectEnabled(valueAt(index), enabled);
116 }
117 
118 
setEffectEnabled(const sp<EffectDescriptor> & effectDesc,bool enabled)119 status_t EffectDescriptorCollection::setEffectEnabled(const sp<EffectDescriptor> &effectDesc,
120                                                       bool enabled)
121 {
122     if (enabled == effectDesc->mEnabled) {
123         ALOGV("setEffectEnabled(%s) effect already %s",
124              enabled?"true":"false", enabled?"enabled":"disabled");
125         return INVALID_OPERATION;
126     }
127 
128     if (enabled) {
129         if (mTotalEffectsCpuLoad + effectDesc->mDesc.cpuLoad > getMaxEffectsCpuLoad()) {
130             ALOGW("setEffectEnabled(true) CPU Load limit exceeded for Fx %s, CPU %f MIPS",
131                  effectDesc->mDesc.name, (float)effectDesc->mDesc.cpuLoad/10);
132             return INVALID_OPERATION;
133         }
134         mTotalEffectsCpuLoad += effectDesc->mDesc.cpuLoad;
135         ALOGV("setEffectEnabled(true) total CPU %d", mTotalEffectsCpuLoad);
136     } else {
137         if (mTotalEffectsCpuLoad < effectDesc->mDesc.cpuLoad) {
138             ALOGW("setEffectEnabled(false) CPU load %d too high for total %d",
139                     effectDesc->mDesc.cpuLoad, mTotalEffectsCpuLoad);
140             effectDesc->mDesc.cpuLoad = mTotalEffectsCpuLoad;
141         }
142         mTotalEffectsCpuLoad -= effectDesc->mDesc.cpuLoad;
143         ALOGV("setEffectEnabled(false) total CPU %d", mTotalEffectsCpuLoad);
144     }
145     effectDesc->mEnabled = enabled;
146     return NO_ERROR;
147 }
148 
isNonOffloadableEffectEnabled()149 bool EffectDescriptorCollection::isNonOffloadableEffectEnabled()
150 {
151     for (size_t i = 0; i < size(); i++) {
152         sp<EffectDescriptor> effectDesc = valueAt(i);
153         if (effectDesc->mEnabled && (effectDesc->mStrategy == STRATEGY_MEDIA) &&
154                 ((effectDesc->mDesc.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) == 0)) {
155             ALOGV("isNonOffloadableEffectEnabled() non offloadable effect %s enabled on session %d",
156                   effectDesc->mDesc.name, effectDesc->mSession);
157             return true;
158         }
159     }
160     return false;
161 }
162 
getMaxEffectsCpuLoad() const163 uint32_t EffectDescriptorCollection::getMaxEffectsCpuLoad() const
164 {
165     return MAX_EFFECTS_CPU_LOAD;
166 }
167 
getMaxEffectsMemory() const168 uint32_t EffectDescriptorCollection::getMaxEffectsMemory() const
169 {
170     return MAX_EFFECTS_MEMORY;
171 }
172 
dump(int fd)173 status_t EffectDescriptorCollection::dump(int fd)
174 {
175     const size_t SIZE = 256;
176     char buffer[SIZE];
177 
178     snprintf(buffer, SIZE, "\nTotal Effects CPU: %f MIPS, Total Effects memory: %d KB\n",
179              (float)mTotalEffectsCpuLoad/10, mTotalEffectsMemory);
180     write(fd, buffer, strlen(buffer));
181 
182     snprintf(buffer, SIZE, "Registered effects:\n");
183     write(fd, buffer, strlen(buffer));
184     for (size_t i = 0; i < size(); i++) {
185         snprintf(buffer, SIZE, "- Effect %d dump:\n", keyAt(i));
186         write(fd, buffer, strlen(buffer));
187         valueAt(i)->dump(fd);
188     }
189     return NO_ERROR;
190 }
191 
192 }; //namespace android
193