145ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie/*
245ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie * Copyright (C) 2015 The Android Open Source Project
345ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie *
445ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie * Licensed under the Apache License, Version 2.0 (the "License");
545ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie * you may not use this file except in compliance with the License.
645ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie * You may obtain a copy of the License at
745ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie *
845ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie *      http://www.apache.org/licenses/LICENSE-2.0
945ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie *
1045ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie * Unless required by applicable law or agreed to in writing, software
1145ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie * distributed under the License is distributed on an "AS IS" BASIS,
1245ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1345ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie * See the License for the specific language governing permissions and
1445ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie * limitations under the License.
1545ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie */
1645ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
1745ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie#define LOG_TAG "APM::EffectDescriptor"
1845ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie//#define LOG_NDEBUG 0
1945ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
2045ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie#include "EffectDescriptor.h"
2145ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie#include <utils/String8.h>
2245ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
2345ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffienamespace android {
2445ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
2545ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffiestatus_t EffectDescriptor::dump(int fd)
2645ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie{
2745ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    const size_t SIZE = 256;
2845ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    char buffer[SIZE];
2945ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    String8 result;
3045ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
3145ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    snprintf(buffer, SIZE, " I/O: %d\n", mIo);
3245ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    result.append(buffer);
3345ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    snprintf(buffer, SIZE, " Strategy: %d\n", mStrategy);
3445ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    result.append(buffer);
3545ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    snprintf(buffer, SIZE, " Session: %d\n", mSession);
3645ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    result.append(buffer);
3745ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    snprintf(buffer, SIZE, " Name: %s\n",  mDesc.name);
3845ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    result.append(buffer);
3945ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    snprintf(buffer, SIZE, " %s\n",  mEnabled ? "Enabled" : "Disabled");
4045ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    result.append(buffer);
4145ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    write(fd, result.string(), result.size());
4245ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
4345ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    return NO_ERROR;
4445ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie}
4545ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
4645ed3b053d9af2250f5ece9ee4e826905c3763a7François GaffieEffectDescriptorCollection::EffectDescriptorCollection() :
4745ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    mTotalEffectsCpuLoad(0),
485f1fa3053c87dd8e9dc528fb8c101907ff747746Andy Hung    mTotalEffectsMemory(0),
495f1fa3053c87dd8e9dc528fb8c101907ff747746Andy Hung    mTotalEffectsMemoryMaxUsed(0)
5045ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie{
5145ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
5245ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie}
5345ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
5445ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffiestatus_t EffectDescriptorCollection::registerEffect(const effect_descriptor_t *desc,
5545ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie                                                    audio_io_handle_t io,
5645ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie                                                    uint32_t strategy,
5745ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie                                                    int session,
5845ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie                                                    int id)
5945ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie{
6045ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    if (mTotalEffectsMemory + desc->memoryUsage > getMaxEffectsMemory()) {
6145ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        ALOGW("registerEffect() memory limit exceeded for Fx %s, Memory %d KB",
6245ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie                desc->name, desc->memoryUsage);
6345ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        return INVALID_OPERATION;
6445ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    }
6545ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    mTotalEffectsMemory += desc->memoryUsage;
665f1fa3053c87dd8e9dc528fb8c101907ff747746Andy Hung    if (mTotalEffectsMemory > mTotalEffectsMemoryMaxUsed) {
675f1fa3053c87dd8e9dc528fb8c101907ff747746Andy Hung        mTotalEffectsMemoryMaxUsed = mTotalEffectsMemory;
685f1fa3053c87dd8e9dc528fb8c101907ff747746Andy Hung    }
6945ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    ALOGV("registerEffect() effect %s, io %d, strategy %d session %d id %d",
7045ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie            desc->name, io, strategy, session, id);
7145ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    ALOGV("registerEffect() memory %d, total memory %d", desc->memoryUsage, mTotalEffectsMemory);
7245ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
7345ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    sp<EffectDescriptor> effectDesc = new EffectDescriptor();
7445ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    memcpy (&effectDesc->mDesc, desc, sizeof(effect_descriptor_t));
7545ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    effectDesc->mIo = io;
7645ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    effectDesc->mStrategy = static_cast<routing_strategy>(strategy);
7745ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    effectDesc->mSession = session;
7845ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    effectDesc->mEnabled = false;
7945ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
8045ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    add(id, effectDesc);
8145ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
8245ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    return NO_ERROR;
8345ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie}
8445ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
8545ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffiestatus_t EffectDescriptorCollection::unregisterEffect(int id)
8645ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie{
8745ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    ssize_t index = indexOfKey(id);
8845ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    if (index < 0) {
8945ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        ALOGW("unregisterEffect() unknown effect ID %d", id);
9045ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        return INVALID_OPERATION;
9145ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    }
9245ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
9345ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    sp<EffectDescriptor> effectDesc = valueAt(index);
9445ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
9545ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    setEffectEnabled(effectDesc, false);
9645ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
9745ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    if (mTotalEffectsMemory < effectDesc->mDesc.memoryUsage) {
9845ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        ALOGW("unregisterEffect() memory %d too big for total %d",
9945ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie                effectDesc->mDesc.memoryUsage, mTotalEffectsMemory);
10045ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        effectDesc->mDesc.memoryUsage = mTotalEffectsMemory;
10145ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    }
10245ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    mTotalEffectsMemory -= effectDesc->mDesc.memoryUsage;
10345ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    ALOGV("unregisterEffect() effect %s, ID %d, memory %d total memory %d",
10445ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie            effectDesc->mDesc.name, id, effectDesc->mDesc.memoryUsage, mTotalEffectsMemory);
10545ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
10645ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    removeItem(id);
10745ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
10845ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    return NO_ERROR;
10945ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie}
11045ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
11145ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffiestatus_t EffectDescriptorCollection::setEffectEnabled(int id, bool enabled)
11245ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie{
11345ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    ssize_t index = indexOfKey(id);
11445ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    if (index < 0) {
11545ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        ALOGW("unregisterEffect() unknown effect ID %d", id);
11645ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        return INVALID_OPERATION;
11745ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    }
11845ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
11945ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    return setEffectEnabled(valueAt(index), enabled);
12045ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie}
12145ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
12245ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
12345ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffiestatus_t EffectDescriptorCollection::setEffectEnabled(const sp<EffectDescriptor> &effectDesc,
12445ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie                                                      bool enabled)
12545ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie{
12645ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    if (enabled == effectDesc->mEnabled) {
12745ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        ALOGV("setEffectEnabled(%s) effect already %s",
12845ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie             enabled?"true":"false", enabled?"enabled":"disabled");
12945ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        return INVALID_OPERATION;
13045ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    }
13145ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
13245ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    if (enabled) {
13345ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        if (mTotalEffectsCpuLoad + effectDesc->mDesc.cpuLoad > getMaxEffectsCpuLoad()) {
13445ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie            ALOGW("setEffectEnabled(true) CPU Load limit exceeded for Fx %s, CPU %f MIPS",
13545ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie                 effectDesc->mDesc.name, (float)effectDesc->mDesc.cpuLoad/10);
13645ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie            return INVALID_OPERATION;
13745ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        }
13845ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        mTotalEffectsCpuLoad += effectDesc->mDesc.cpuLoad;
13945ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        ALOGV("setEffectEnabled(true) total CPU %d", mTotalEffectsCpuLoad);
14045ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    } else {
14145ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        if (mTotalEffectsCpuLoad < effectDesc->mDesc.cpuLoad) {
14245ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie            ALOGW("setEffectEnabled(false) CPU load %d too high for total %d",
14345ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie                    effectDesc->mDesc.cpuLoad, mTotalEffectsCpuLoad);
14445ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie            effectDesc->mDesc.cpuLoad = mTotalEffectsCpuLoad;
14545ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        }
14645ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        mTotalEffectsCpuLoad -= effectDesc->mDesc.cpuLoad;
14745ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        ALOGV("setEffectEnabled(false) total CPU %d", mTotalEffectsCpuLoad);
14845ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    }
14945ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    effectDesc->mEnabled = enabled;
15045ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    return NO_ERROR;
15145ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie}
15245ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
15345ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffiebool EffectDescriptorCollection::isNonOffloadableEffectEnabled()
15445ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie{
15545ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    for (size_t i = 0; i < size(); i++) {
15645ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        sp<EffectDescriptor> effectDesc = valueAt(i);
15745ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        if (effectDesc->mEnabled && (effectDesc->mStrategy == STRATEGY_MEDIA) &&
15845ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie                ((effectDesc->mDesc.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) == 0)) {
15945ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie            ALOGV("isNonOffloadableEffectEnabled() non offloadable effect %s enabled on session %d",
16045ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie                  effectDesc->mDesc.name, effectDesc->mSession);
16145ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie            return true;
16245ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        }
16345ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    }
16445ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    return false;
16545ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie}
16645ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
16745ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffieuint32_t EffectDescriptorCollection::getMaxEffectsCpuLoad() const
16845ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie{
16945ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    return MAX_EFFECTS_CPU_LOAD;
17045ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie}
17145ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
17245ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffieuint32_t EffectDescriptorCollection::getMaxEffectsMemory() const
17345ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie{
17445ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    return MAX_EFFECTS_MEMORY;
17545ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie}
17645ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
17745ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffiestatus_t EffectDescriptorCollection::dump(int fd)
17845ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie{
17945ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    const size_t SIZE = 256;
18045ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    char buffer[SIZE];
18145ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
1825f1fa3053c87dd8e9dc528fb8c101907ff747746Andy Hung    snprintf(buffer, SIZE,
1835f1fa3053c87dd8e9dc528fb8c101907ff747746Andy Hung            "\nTotal Effects CPU: %f MIPS, Total Effects memory: %d KB, Max memory used: %d KB\n",
1845f1fa3053c87dd8e9dc528fb8c101907ff747746Andy Hung             (float)mTotalEffectsCpuLoad/10, mTotalEffectsMemory, mTotalEffectsMemoryMaxUsed);
18545ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    write(fd, buffer, strlen(buffer));
18645ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
18745ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    snprintf(buffer, SIZE, "Registered effects:\n");
18845ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    write(fd, buffer, strlen(buffer));
18945ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    for (size_t i = 0; i < size(); i++) {
19045ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        snprintf(buffer, SIZE, "- Effect %d dump:\n", keyAt(i));
19145ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        write(fd, buffer, strlen(buffer));
19245ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie        valueAt(i)->dump(fd);
19345ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    }
19445ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie    return NO_ERROR;
19545ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie}
19645ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie
19745ed3b053d9af2250f5ece9ee4e826905c3763a7François Gaffie}; //namespace android
198