/*
**
** Copyright 2012, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/


#define LOG_TAG "AudioFlinger"
//#define LOG_NDEBUG 0

#include "Effects.h"

#include "Client.h"
#include "EffectConfiguration.h"

#include <afutils/DumpTryLock.h>
#include <audio_utils/channels.h>
#include <audio_utils/primitives.h>
#include <media/AudioCommonTypes.h>
#include <media/AudioContainers.h>
#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioEffect.h>
#include <media/ShmemCompat.h>
#include <media/TypeConverter.h>
#include <media/audiohal/EffectHalInterface.h>
#include <media/audiohal/EffectsFactoryHalInterface.h>
#include <mediautils/MethodStatistics.h>
#include <mediautils/ServiceUtilities.h>
#include <mediautils/TimeCheck.h>
#include <system/audio_effects/effect_aec.h>
#include <system/audio_effects/effect_downmix.h>
#include <system/audio_effects/effect_dynamicsprocessing.h>
#include <system/audio_effects/effect_hapticgenerator.h>
#include <system/audio_effects/effect_ns.h>
#include <system/audio_effects/effect_spatializer.h>
#include <system/audio_effects/effect_visualizer.h>
#include <utils/Log.h>

#include <algorithm>

// ----------------------------------------------------------------------------

// Note: the following macro is used for extremely verbose logging message.  In
// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to
// 0; but one side effect of this is to turn all LOGV's as well.  Some messages
// are so verbose that we want to suppress them even when we have ALOG_ASSERT
// turned on.  Do not uncomment the #def below unless you really know what you
// are doing and want to see all of the extremely verbose messages.
//#define VERY_VERY_VERBOSE_LOGGING
#ifdef VERY_VERY_VERBOSE_LOGGING
#define ALOGVV ALOGV
#else
#define ALOGVV(a...) do { } while(0)
#endif

#define DEFAULT_OUTPUT_SAMPLE_RATE 48000

namespace android {

using aidl_utils::statusTFromBinderStatus;
using audioflinger::EffectConfiguration;
using binder::Status;

namespace {

// Append a POD value into a vector of bytes.
template<typename T>
void appendToBuffer(const T& value, std::vector<uint8_t>* buffer) {
    const uint8_t* ar(reinterpret_cast<const uint8_t*>(&value));
    buffer->insert(buffer->end(), ar, ar + sizeof(T));
}

// Write a POD value into a vector of bytes (clears the previous buffer
// content).
template<typename T>
void writeToBuffer(const T& value, std::vector<uint8_t>* buffer) {
    buffer->clear();
    appendToBuffer(value, buffer);
}

}  // namespace

// ----------------------------------------------------------------------------
//  EffectBase implementation
// ----------------------------------------------------------------------------

#undef LOG_TAG
#define LOG_TAG "EffectBase"

EffectBase::EffectBase(const sp<EffectCallbackInterface>& callback,
                                        effect_descriptor_t *desc,
                                        int id,
                                        audio_session_t sessionId,
                                        bool pinned)
    : mPinned(pinned),
      mCallback(callback), mId(id), mSessionId(sessionId),
      mDescriptor(*desc)
{
}

// must be called with EffectModule::mutex() held
status_t EffectBase::setEnabled_l(bool enabled)
{

    ALOGV("setEnabled %p enabled %d", this, enabled);

    if (enabled != isEnabled()) {
        switch (mState) {
        // going from disabled to enabled
        case IDLE:
            mState = STARTING;
            break;
        case STOPPED:
            mState = RESTART;
            break;
        case STOPPING:
            mState = ACTIVE;
            break;

        // going from enabled to disabled
        case RESTART:
            mState = STOPPED;
            break;
        case STARTING:
            mState = IDLE;
            break;
        case ACTIVE:
            mState = STOPPING;
            break;
        case DESTROYED:
            return NO_ERROR; // simply ignore as we are being destroyed
        }
        for (size_t i = 1; i < mHandles.size(); i++) {
            IAfEffectHandle *h = mHandles[i];
            if (h != NULL && !h->disconnected()) {
                h->setEnabled(enabled);
            }
        }
    }
    return NO_ERROR;
}

status_t EffectBase::setEnabled(bool enabled, bool fromHandle)
{
    status_t status;
    {
        audio_utils::lock_guard _l(mutex());
        status = setEnabled_l(enabled);
    }
    if (fromHandle) {
        if (enabled) {
            if (status != NO_ERROR) {
                getCallback()->checkSuspendOnEffectEnabled(this, false, false /*threadLocked*/);
            } else {
                getCallback()->onEffectEnable(this);
            }
        } else {
            getCallback()->onEffectDisable(this);
        }
    }
    return status;
}

bool EffectBase::isEnabled() const
{
    switch (mState) {
    case RESTART:
    case STARTING:
    case ACTIVE:
        return true;
    case IDLE:
    case STOPPING:
    case STOPPED:
    case DESTROYED:
    default:
        return false;
    }
}

void EffectBase::setSuspended(bool suspended)
{
    audio_utils::lock_guard _l(mutex());
    mSuspended = suspended;
}

bool EffectBase::suspended() const
{
    audio_utils::lock_guard _l(mutex());
    return mSuspended;
}

status_t EffectBase::addHandle(IAfEffectHandle *handle)
{
    status_t status;

    audio_utils::lock_guard _l(mutex());
    int priority = handle->priority();
    size_t size = mHandles.size();
    IAfEffectHandle *controlHandle = nullptr;
    size_t i;
    for (i = 0; i < size; i++) {
        IAfEffectHandle *h = mHandles[i];
        if (h == NULL || h->disconnected()) {
            continue;
        }
        // first non destroyed handle is considered in control
        if (controlHandle == NULL) {
            controlHandle = h;
        }
        if (h->priority() <= priority) {
            break;
        }
    }
    // if inserted in first place, move effect control from previous owner to this handle
    if (i == 0) {
        bool enabled = false;
        if (controlHandle != NULL) {
            enabled = controlHandle->enabled();
            controlHandle->setControl(false/*hasControl*/, true /*signal*/, enabled /*enabled*/);
        }
        handle->setControl(true /*hasControl*/, false /*signal*/, enabled /*enabled*/);
        status = NO_ERROR;
    } else {
        status = ALREADY_EXISTS;
    }
    ALOGV("addHandle() %p added handle %p in position %zu", this, handle, i);
    mHandles.insertAt(handle, i);
    return status;
}

status_t EffectBase::updatePolicyState()
{
    status_t status = NO_ERROR;
    bool doRegister = false;
    bool registered = false;
    bool doEnable = false;
    bool enabled = false;
    audio_io_handle_t io = AUDIO_IO_HANDLE_NONE;
    product_strategy_t strategy = PRODUCT_STRATEGY_NONE;

    {
        audio_utils::lock_guard _l(mutex());

        if ((isInternal_l() && !mPolicyRegistered)
                || !getCallback()->isAudioPolicyReady()) {
            return NO_ERROR;
        }

        // register effect when first handle is attached and unregister when last handle is removed
        if (mPolicyRegistered != mHandles.size() > 0) {
            doRegister = true;
            mPolicyRegistered = mHandles.size() > 0;
            if (mPolicyRegistered) {
                const auto callback = getCallback();
                io = callback->io();
                strategy = callback->strategy();
            }
        }
        // enable effect when registered according to enable state requested by controlling handle
        if (mHandles.size() > 0) {
            IAfEffectHandle *handle = controlHandle_l();
            if (handle != nullptr && mPolicyEnabled != handle->enabled()) {
                doEnable = true;
                mPolicyEnabled = handle->enabled();
            }
        }
        registered = mPolicyRegistered;
        enabled = mPolicyEnabled;
        // The simultaneous release of two EffectHandles with the same EffectModule
        // may cause us to call this method at the same time.
        // This may deadlock under some circumstances (b/180941720).  Avoid this.
        if (!doRegister && !(registered && doEnable)) {
            return NO_ERROR;
        }
    }
    policyMutex().lock();
    ALOGV("%s name %s id %d session %d doRegister %d registered %d doEnable %d enabled %d",
        __func__, mDescriptor.name, mId, mSessionId, doRegister, registered, doEnable, enabled);
    if (doRegister) {
        if (registered) {
            status = AudioSystem::registerEffect(
                &mDescriptor,
                io,
                strategy,
                mSessionId,
                mId);
        } else {
            status = AudioSystem::unregisterEffect(mId);
        }
    }
    if (registered && doEnable) {
        status = AudioSystem::setEffectEnabled(mId, enabled);
    }
    policyMutex().unlock();

    return status;
}


ssize_t EffectBase::removeHandle(IAfEffectHandle *handle)
{
    audio_utils::lock_guard _l(mutex());
    return removeHandle_l(handle);
}

ssize_t EffectBase::removeHandle_l(IAfEffectHandle *handle)
{
    size_t size = mHandles.size();
    size_t i;
    for (i = 0; i < size; i++) {
        if (mHandles[i] == handle) {
            break;
        }
    }
    if (i == size) {
        ALOGW("%s %p handle not found %p", __FUNCTION__, this, handle);
        return BAD_VALUE;
    }
    ALOGV("removeHandle_l() %p removed handle %p in position %zu", this, handle, i);

    mHandles.removeAt(i);
    // if removed from first place, move effect control from this handle to next in line
    if (i == 0) {
        IAfEffectHandle *h = controlHandle_l();
        if (h != NULL) {
            h->setControl(true /*hasControl*/, true /*signal*/ , handle->enabled() /*enabled*/);
        }
    }

    // Prevent calls to process() and other functions on effect interface from now on.
    // The effect engine will be released by the destructor when the last strong reference on
    // this object is released which can happen after next process is called.
    if (mHandles.size() == 0 && !mPinned) {
        mState = DESTROYED;
    }

    return mHandles.size();
}

// must be called with EffectModule::mutex() held
IAfEffectHandle *EffectBase::controlHandle_l()
{
    // the first valid handle in the list has control over the module
    for (size_t i = 0; i < mHandles.size(); i++) {
        IAfEffectHandle *h = mHandles[i];
        if (h != NULL && !h->disconnected()) {
            return h;
        }
    }

    return NULL;
}

// unsafe method called when the effect parent thread has been destroyed
ssize_t EffectBase::disconnectHandle(IAfEffectHandle *handle, bool unpinIfLast)
{
    const auto callback = getCallback();
    ALOGV("disconnect() %p handle %p", this, handle);
    if (callback->disconnectEffectHandle(handle, unpinIfLast)) {
        return mHandles.size();
    }

    audio_utils::lock_guard _l(mutex());
    ssize_t numHandles = removeHandle_l(handle);
    if ((numHandles == 0) && (!mPinned || unpinIfLast)) {
        mutex().unlock();
        callback->updateOrphanEffectChains(this);
        mutex().lock();
    }
    return numHandles;
}

bool EffectBase::purgeHandles()
{
    bool enabled = false;
    audio_utils::lock_guard _l(mutex());
    IAfEffectHandle *handle = controlHandle_l();
    if (handle != NULL) {
        enabled = handle->enabled();
    }
    mHandles.clear();
    return enabled;
}

void EffectBase::checkSuspendOnEffectEnabled(bool enabled, bool threadLocked) {
    getCallback()->checkSuspendOnEffectEnabled(this, enabled, threadLocked);
}

static String8 effectFlagsToString(uint32_t flags) {
    String8 s;

    s.append("conn. mode: ");
    switch (flags & EFFECT_FLAG_TYPE_MASK) {
    case EFFECT_FLAG_TYPE_INSERT: s.append("insert"); break;
    case EFFECT_FLAG_TYPE_AUXILIARY: s.append("auxiliary"); break;
    case EFFECT_FLAG_TYPE_REPLACE: s.append("replace"); break;
    case EFFECT_FLAG_TYPE_PRE_PROC: s.append("preproc"); break;
    case EFFECT_FLAG_TYPE_POST_PROC: s.append("postproc"); break;
    default: s.append("unknown/reserved"); break;
    }
    s.append(", ");

    s.append("insert pref: ");
    switch (flags & EFFECT_FLAG_INSERT_MASK) {
    case EFFECT_FLAG_INSERT_ANY: s.append("any"); break;
    case EFFECT_FLAG_INSERT_FIRST: s.append("first"); break;
    case EFFECT_FLAG_INSERT_LAST: s.append("last"); break;
    case EFFECT_FLAG_INSERT_EXCLUSIVE: s.append("exclusive"); break;
    default: s.append("unknown/reserved"); break;
    }
    s.append(", ");

    s.append("volume mgmt: ");
    switch (flags & EFFECT_FLAG_VOLUME_MASK) {
    case EFFECT_FLAG_VOLUME_NONE: s.append("none"); break;
    case EFFECT_FLAG_VOLUME_CTRL: s.append("implements control"); break;
    case EFFECT_FLAG_VOLUME_IND: s.append("requires indication"); break;
    case EFFECT_FLAG_VOLUME_MONITOR: s.append("monitors volume"); break;
    default: s.append("unknown/reserved"); break;
    }
    s.append(", ");

    uint32_t devind = flags & EFFECT_FLAG_DEVICE_MASK;
    if (devind) {
        s.append("device indication: ");
        switch (devind) {
        case EFFECT_FLAG_DEVICE_IND: s.append("requires updates"); break;
        default: s.append("unknown/reserved"); break;
        }
        s.append(", ");
    }

    s.append("input mode: ");
    switch (flags & EFFECT_FLAG_INPUT_MASK) {
    case EFFECT_FLAG_INPUT_DIRECT: s.append("direct"); break;
    case EFFECT_FLAG_INPUT_PROVIDER: s.append("provider"); break;
    case EFFECT_FLAG_INPUT_BOTH: s.append("direct+provider"); break;
    default: s.append("not set"); break;
    }
    s.append(", ");

    s.append("output mode: ");
    switch (flags & EFFECT_FLAG_OUTPUT_MASK) {
    case EFFECT_FLAG_OUTPUT_DIRECT: s.append("direct"); break;
    case EFFECT_FLAG_OUTPUT_PROVIDER: s.append("provider"); break;
    case EFFECT_FLAG_OUTPUT_BOTH: s.append("direct+provider"); break;
    default: s.append("not set"); break;
    }
    s.append(", ");

    uint32_t accel = flags & EFFECT_FLAG_HW_ACC_MASK;
    if (accel) {
        s.append("hardware acceleration: ");
        switch (accel) {
        case EFFECT_FLAG_HW_ACC_SIMPLE: s.append("non-tunneled"); break;
        case EFFECT_FLAG_HW_ACC_TUNNEL: s.append("tunneled"); break;
        default: s.append("unknown/reserved"); break;
        }
        s.append(", ");
    }

    uint32_t modeind = flags & EFFECT_FLAG_AUDIO_MODE_MASK;
    if (modeind) {
        s.append("mode indication: ");
        switch (modeind) {
        case EFFECT_FLAG_AUDIO_MODE_IND: s.append("required"); break;
        default: s.append("unknown/reserved"); break;
        }
        s.append(", ");
    }

    uint32_t srcind = flags & EFFECT_FLAG_AUDIO_SOURCE_MASK;
    if (srcind) {
        s.append("source indication: ");
        switch (srcind) {
        case EFFECT_FLAG_AUDIO_SOURCE_IND: s.append("required"); break;
        default: s.append("unknown/reserved"); break;
        }
        s.append(", ");
    }

    if (flags & EFFECT_FLAG_OFFLOAD_MASK) {
        s.append("offloadable, ");
    }

    int len = s.length();
    if (s.length() > 2) {
        (void) s.lockBuffer(len);
        s.unlockBuffer(len - 2);
    }
    return s;
}

void EffectBase::dump(int fd, const Vector<String16>& args __unused) const
NO_THREAD_SAFETY_ANALYSIS // conditional try lock
{
    String8 result;

    result.appendFormat("\tEffect ID %d:\n", mId);

    const bool locked = afutils::dumpTryLock(mutex());
    // failed to lock - AudioFlinger is probably deadlocked
    if (!locked) {
        result.append("\t\tCould not lock Fx mutex:\n");
    }

    result.append("\t\tSession State Registered Enabled Suspended:\n");
    result.appendFormat("\t\t%05d   %03d   %s          %s       %s\n",
            mSessionId, mState, mPolicyRegistered ? "y" : "n",
            mPolicyEnabled ? "y" : "n", mSuspended ? "y" : "n");

    result.append("\t\tDescriptor:\n");
    char uuidStr[64];
    AudioEffect::guidToString(&mDescriptor.uuid, uuidStr, sizeof(uuidStr));
    result.appendFormat("\t\t- UUID: %s\n", uuidStr);
    AudioEffect::guidToString(&mDescriptor.type, uuidStr, sizeof(uuidStr));
    result.appendFormat("\t\t- TYPE: %s\n", uuidStr);
    result.appendFormat("\t\t- apiVersion: %08X\n\t\t- flags: %08X (%s)\n",
            mDescriptor.apiVersion,
            mDescriptor.flags,
            effectFlagsToString(mDescriptor.flags).c_str());
    result.appendFormat("\t\t- name: %s\n",
            mDescriptor.name);

    result.appendFormat("\t\t- implementor: %s\n",
            mDescriptor.implementor);

    result.appendFormat("\t\t%zu Clients:\n", mHandles.size());
    result.append("\t\t\t  Pid Priority Ctrl Locked client server\n");
    char buffer[256];
    for (size_t i = 0; i < mHandles.size(); ++i) {
        IAfEffectHandle *handle = mHandles[i];
        if (handle != NULL && !handle->disconnected()) {
            handle->dumpToBuffer(buffer, sizeof(buffer));
            result.append(buffer);
        }
    }
    if (locked) {
        mutex().unlock();
    }

    write(fd, result.c_str(), result.length());
}

// ----------------------------------------------------------------------------
//  EffectModule implementation
// ----------------------------------------------------------------------------

#undef LOG_TAG
#define LOG_TAG "EffectModule"

EffectModule::EffectModule(const sp<EffectCallbackInterface>& callback,
                                         effect_descriptor_t *desc,
                                         int id,
                                         audio_session_t sessionId,
                                         bool pinned,
                                         audio_port_handle_t deviceId)
    : EffectBase(callback, desc, id, sessionId, pinned),
      // clear mConfig to ensure consistent initial value of buffer framecount
      // in case buffers are associated by setInBuffer() or setOutBuffer()
      // prior to configure().
      mConfig{{}, {}},
      mStatus(NO_INIT),
      mMaxDisableWaitCnt(1), // set by configure(), should be >= 1
      mDisableWaitCnt(0),    // set by process() and updateState()
      mOffloaded(false),
      mIsOutput(false)
      , mSupportsFloat(false)
{
    ALOGV("Constructor %p pinned %d", this, pinned);
    int lStatus;

    // create effect engine from effect factory
    mStatus = callback->createEffectHal(
            &desc->uuid, sessionId, deviceId, &mEffectInterface);
    if (mStatus != NO_ERROR) {
        return;
    }
    lStatus = init();
    if (lStatus < 0) {
        mStatus = lStatus;
        goto Error;
    }

    setOffloaded(callback->isOffload(), callback->io());
    ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface.get());

    return;
Error:
    mEffectInterface.clear();
    ALOGV("Constructor Error %d", mStatus);
}

EffectModule::~EffectModule()
{
    ALOGV("Destructor %p", this);
    if (mEffectInterface != 0) {
        char uuidStr[64];
        AudioEffect::guidToString(&mDescriptor.uuid, uuidStr, sizeof(uuidStr));
        ALOGW("EffectModule %p destructor called with unreleased interface, effect %s",
                this, uuidStr);
        release_l();
    }

}

bool EffectModule::updateState() {
    audio_utils::lock_guard _l(mutex());

    bool started = false;
    switch (mState) {
    case RESTART:
        reset_l();
        FALLTHROUGH_INTENDED;

    case STARTING:
        // clear auxiliary effect input buffer for next accumulation
        if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
            memset(mConfig.inputCfg.buffer.raw,
                   0,
                   mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
        }
        if (start_l() == NO_ERROR) {
            mState = ACTIVE;
            started = true;
        } else {
            mState = IDLE;
        }
        break;
    case STOPPING:
        // volume control for offload and direct threads must take effect immediately.
        if (stop_l() == NO_ERROR
            && !(isVolumeControl() && isOffloadedOrDirect())) {
            mDisableWaitCnt = mMaxDisableWaitCnt;
        } else {
            mDisableWaitCnt = 1; // will cause immediate transition to IDLE
        }
        mState = STOPPED;
        break;
    case STOPPED:
        // mDisableWaitCnt is forced to 1 by process() when the engine indicates the end of the
        // turn off sequence.
        if (--mDisableWaitCnt == 0) {
            reset_l();
            mState = IDLE;
        }
        break;
    case ACTIVE:
        for (size_t i = 0; i < mHandles.size(); i++) {
            if (!mHandles[i]->disconnected()) {
                mHandles[i]->framesProcessed(mConfig.inputCfg.buffer.frameCount);
            }
        }
        break;
    default: //IDLE , ACTIVE, DESTROYED
        break;
    }

    return started;
}

void EffectModule::process()
{
    audio_utils::lock_guard _l(mutex());

    if (mState == DESTROYED || mEffectInterface == 0 || mInBuffer == 0 || mOutBuffer == 0) {
        return;
    }

    const uint32_t inChannelCount =
            audio_channel_count_from_out_mask(mConfig.inputCfg.channels);
    const uint32_t outChannelCount =
            audio_channel_count_from_out_mask(mConfig.outputCfg.channels);
    const bool auxType =
            (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY;

    // safeInputOutputSampleCount is 0 if the channel count between input and output
    // buffers do not match. This prevents automatic accumulation or copying between the
    // input and output effect buffers without an intermediary effect process.
    // TODO: consider implementing channel conversion.
    const size_t safeInputOutputSampleCount =
            mInChannelCountRequested != mOutChannelCountRequested ? 0
                    : mOutChannelCountRequested * std::min(
                            mConfig.inputCfg.buffer.frameCount,
                            mConfig.outputCfg.buffer.frameCount);
    const auto accumulateInputToOutput = [this, safeInputOutputSampleCount]() {
        accumulate_float(
                mConfig.outputCfg.buffer.f32,
                mConfig.inputCfg.buffer.f32,
                safeInputOutputSampleCount);
    };
    const auto copyInputToOutput = [this, safeInputOutputSampleCount]() {
        memcpy(
                mConfig.outputCfg.buffer.f32,
                mConfig.inputCfg.buffer.f32,
                safeInputOutputSampleCount * sizeof(*mConfig.outputCfg.buffer.f32));
    };

    if (isProcessEnabled()) {
        int ret;
        if (isProcessImplemented()) {
            if (auxType) {
                // We overwrite the aux input buffer here and clear after processing.
                // aux input is always mono.

                if (!mSupportsFloat) {
                    memcpy_to_i16_from_float(
                            mConfig.inputCfg.buffer.s16,
                            mConfig.inputCfg.buffer.f32,
                            mConfig.inputCfg.buffer.frameCount);
                }
            }
            sp<EffectBufferHalInterface> inBuffer = mInBuffer;
            sp<EffectBufferHalInterface> outBuffer = mOutBuffer;

            if (!auxType && mInChannelCountRequested != inChannelCount) {
                adjust_channels(
                        inBuffer->audioBuffer()->f32, mInChannelCountRequested,
                        mInConversionBuffer->audioBuffer()->f32, inChannelCount,
                        sizeof(float),
                        sizeof(float)
                        * mInChannelCountRequested * mConfig.inputCfg.buffer.frameCount);
                inBuffer = mInConversionBuffer;
            }
            if (mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE
                    && mOutChannelCountRequested != outChannelCount) {
                adjust_selected_channels(
                        outBuffer->audioBuffer()->f32, mOutChannelCountRequested,
                        mOutConversionBuffer->audioBuffer()->f32, outChannelCount,
                        sizeof(float),
                        sizeof(float)
                        * mOutChannelCountRequested * mConfig.outputCfg.buffer.frameCount);
                outBuffer = mOutConversionBuffer;
            }
            if (!mSupportsFloat) { // convert input to int16_t as effect doesn't support float.
                if (!auxType) {
                    if (mInConversionBuffer == nullptr) {
                        ALOGW("%s: mInConversionBuffer is null, bypassing", __func__);
                        goto data_bypass;
                    }
                    memcpy_to_i16_from_float(
                            mInConversionBuffer->audioBuffer()->s16,
                            inBuffer->audioBuffer()->f32,
                            inChannelCount * mConfig.inputCfg.buffer.frameCount);
                    inBuffer = mInConversionBuffer;
                }
                if (mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
                    if (mOutConversionBuffer == nullptr) {
                        ALOGW("%s: mOutConversionBuffer is null, bypassing", __func__);
                        goto data_bypass;
                    }
                    memcpy_to_i16_from_float(
                            mOutConversionBuffer->audioBuffer()->s16,
                            outBuffer->audioBuffer()->f32,
                            outChannelCount * mConfig.outputCfg.buffer.frameCount);
                    outBuffer = mOutConversionBuffer;
                }
            }
            ret = mEffectInterface->process();
            if (!mSupportsFloat) { // convert output int16_t back to float.
                sp<EffectBufferHalInterface> target =
                        mOutChannelCountRequested != outChannelCount
                        ? mOutConversionBuffer : mOutBuffer;

                memcpy_to_float_from_i16(
                        target->audioBuffer()->f32,
                        mOutConversionBuffer->audioBuffer()->s16,
                        outChannelCount * mConfig.outputCfg.buffer.frameCount);
            }
            if (mOutChannelCountRequested != outChannelCount) {
                adjust_selected_channels(mOutConversionBuffer->audioBuffer()->f32, outChannelCount,
                        mOutBuffer->audioBuffer()->f32, mOutChannelCountRequested,
                        sizeof(float),
                        sizeof(float) * outChannelCount * mConfig.outputCfg.buffer.frameCount);
            }
        } else {
            data_bypass:
            if (!auxType  /* aux effects do not require data bypass */
                    && mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
                if (mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
                    accumulateInputToOutput();
                } else {
                    copyInputToOutput();
                }
            }
            ret = -ENODATA;
        }

        // force transition to IDLE state when engine is ready
        if (mState == STOPPED && ret == -ENODATA) {
            mDisableWaitCnt = 1;
        }

        // clear auxiliary effect input buffer for next accumulation
        if (auxType) {
            const size_t size =
                    mConfig.inputCfg.buffer.frameCount * inChannelCount * sizeof(float);
            memset(mConfig.inputCfg.buffer.raw, 0, size);
        }
    } else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT &&
                // mInBuffer->audioBuffer()->raw != mOutBuffer->audioBuffer()->raw
                mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
        // If an insert effect is idle and input buffer is different from output buffer,
        // accumulate input onto output
        if (getCallback()->activeTrackCnt() != 0) {
            // similar handling with data_bypass above.
            if (mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
                accumulateInputToOutput();
            } else { // EFFECT_BUFFER_ACCESS_WRITE
                copyInputToOutput();
            }
        }
    }
}

void EffectModule::reset_l()
{
    if (mStatus != NO_ERROR || mEffectInterface == 0) {
        return;
    }

    int reply = 0;
    uint32_t replySize = sizeof(reply);
    mEffectInterface->command(EFFECT_CMD_RESET, 0, NULL, &replySize, &reply);
}

status_t EffectModule::configure()
{
    ALOGVV("configure() started");
    status_t status;
    uint32_t size;
    audio_channel_mask_t channelMask;
    sp<EffectCallbackInterface> callback;

    if (mEffectInterface == 0) {
        status = NO_INIT;
        goto exit;
    }

    // TODO: handle configuration of effects replacing track process
    // TODO: handle configuration of input (record) SW effects above the HAL,
    // similar to output EFFECT_FLAG_TYPE_INSERT/REPLACE,
    // in which case input channel masks should be used here.
    callback = getCallback();
    channelMask = callback->inChannelMask(mId);
    mConfig.inputCfg.channels = channelMask;
    mConfig.outputCfg.channels = callback->outChannelMask();

    if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
        if (mConfig.inputCfg.channels != AUDIO_CHANNEL_OUT_MONO) {
            mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_MONO;
            ALOGV("Overriding auxiliary effect input channels %#x as MONO",
                    mConfig.inputCfg.channels);
        }
    }
    if (isHapticGenerator()) {
        audio_channel_mask_t hapticChannelMask = callback->hapticChannelMask();
        mConfig.inputCfg.channels |= hapticChannelMask;
        mConfig.outputCfg.channels |= hapticChannelMask;
    }
    mInChannelCountRequested =
            audio_channel_count_from_out_mask(mConfig.inputCfg.channels);
    mOutChannelCountRequested =
            audio_channel_count_from_out_mask(mConfig.outputCfg.channels);

    mConfig.inputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
    mConfig.outputCfg.format = AUDIO_FORMAT_PCM_FLOAT;

    // Don't use sample rate for thread if effect isn't offloadable.
    if (callback->isOffloadOrDirect() && !isOffloaded()) {
        mConfig.inputCfg.samplingRate = DEFAULT_OUTPUT_SAMPLE_RATE;
        ALOGV("Overriding effect input as 48kHz");
    } else {
        mConfig.inputCfg.samplingRate = callback->sampleRate();
    }
    mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
    mConfig.inputCfg.bufferProvider.cookie = NULL;
    mConfig.inputCfg.bufferProvider.getBuffer = NULL;
    mConfig.inputCfg.bufferProvider.releaseBuffer = NULL;
    mConfig.outputCfg.bufferProvider.cookie = NULL;
    mConfig.outputCfg.bufferProvider.getBuffer = NULL;
    mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
    mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
    // Insert effect:
    // - in global sessions (e.g AUDIO_SESSION_OUTPUT_MIX),
    // always overwrites output buffer: input buffer == output buffer
    // - in other sessions:
    //      last effect in the chain accumulates in output buffer: input buffer != output buffer
    //      other effect: overwrites output buffer: input buffer == output buffer
    // Auxiliary effect:
    //      accumulates in output buffer: input buffer != output buffer
    // Therefore: accumulate <=> input buffer != output buffer
    mConfig.outputCfg.accessMode = requiredEffectBufferAccessMode();
    mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
    mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
    mConfig.inputCfg.buffer.frameCount = callback->frameCount();
    mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
    mIsOutput = callback->isOutput();

    ALOGV("configure() %p chain %p buffer %p framecount %zu",
          this, callback->chain().promote().get(),
          mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);

    status_t cmdStatus;
    size = sizeof(int);
    status = mEffectInterface->command(EFFECT_CMD_SET_CONFIG,
                                       sizeof(mConfig),
                                       &mConfig,
                                       &size,
                                       &cmdStatus);
    if (status == NO_ERROR) {
        status = cmdStatus;
    }

    if (status != NO_ERROR &&
            EffectConfiguration::isHidl() && // only HIDL effects support channel conversion
            mIsOutput &&
            (mConfig.inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO
                    || mConfig.outputCfg.channels != AUDIO_CHANNEL_OUT_STEREO)) {
        // Older effects may require exact STEREO position mask.
        if (mConfig.inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO
                && (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_AUXILIARY) {
            ALOGV("Overriding effect input channels %#x as STEREO", mConfig.inputCfg.channels);
            mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
        }
        if (mConfig.outputCfg.channels != AUDIO_CHANNEL_OUT_STEREO) {
            ALOGV("Overriding effect output channels %#x as STEREO", mConfig.outputCfg.channels);
            mConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
        }
        size = sizeof(int);
        status = mEffectInterface->command(EFFECT_CMD_SET_CONFIG,
                                           sizeof(mConfig),
                                           &mConfig,
                                           &size,
                                           &cmdStatus);
        if (status == NO_ERROR) {
            status = cmdStatus;
        }
    }

    if (status == NO_ERROR) {
        mSupportsFloat = true;
    }

    // only HIDL effects support integer conversion.
    if (status != NO_ERROR && EffectConfiguration::isHidl()) {
        ALOGV("EFFECT_CMD_SET_CONFIG failed with float format, retry with int16_t.");
        mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
        mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
        size = sizeof(int);
        status = mEffectInterface->command(EFFECT_CMD_SET_CONFIG,
                                           sizeof(mConfig),
                                           &mConfig,
                                           &size,
                                           &cmdStatus);
        if (status == NO_ERROR) {
            status = cmdStatus;
        }
        if (status == NO_ERROR) {
            mSupportsFloat = false;
            ALOGVV("config worked with 16 bit");
        } else {
            ALOGE("%s failed %d with int16_t (as well as float)", __func__, status);
        }
    }

    if (status == NO_ERROR) {
        // Establish Buffer strategy
        setInBuffer(mInBuffer);
        setOutBuffer(mOutBuffer);

        // Update visualizer latency
        if (memcmp(&mDescriptor.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) {
            uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
            effect_param_t *p = (effect_param_t *)buf32;

            p->psize = sizeof(uint32_t);
            p->vsize = sizeof(uint32_t);
            size = sizeof(int);
            *(int32_t *)p->data = VISUALIZER_PARAM_LATENCY;

            uint32_t latency = callback->latency();

            *((int32_t *)p->data + 1)= latency;
            mEffectInterface->command(EFFECT_CMD_SET_PARAM,
                    sizeof(effect_param_t) + 8,
                    &buf32,
                    &size,
                    &cmdStatus);
        }
    }

    // mConfig.outputCfg.buffer.frameCount cannot be zero.
    mMaxDisableWaitCnt = (uint32_t)std::max(
            (uint64_t)1, // mMaxDisableWaitCnt must be greater than zero.
            (uint64_t)MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate
                / ((uint64_t)1000 * mConfig.outputCfg.buffer.frameCount));

exit:
    // TODO: consider clearing mConfig on error.
    mStatus = status;
    ALOGVV("configure ended");
    return status;
}

status_t EffectModule::init()
{
    audio_utils::lock_guard _l(mutex());
    if (mEffectInterface == 0) {
        return NO_INIT;
    }
    status_t cmdStatus;
    uint32_t size = sizeof(status_t);
    status_t status = mEffectInterface->command(EFFECT_CMD_INIT,
                                                0,
                                                NULL,
                                                &size,
                                                &cmdStatus);
    if (status == 0) {
        status = cmdStatus;
    }
    return status;
}

void EffectModule::addEffectToHal_l()
{
    if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
         (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
        if (mCurrentHalStream == getCallback()->io()) {
            return;
        }

        (void)getCallback()->addEffectToHal(mEffectInterface);
        mCurrentHalStream = getCallback()->io();
    }
}

// start() must be called with PlaybackThread::mutex() or EffectChain::mutex() held
status_t EffectModule::start()
{
    status_t status;
    {
        audio_utils::lock_guard _l(mutex());
        status = start_l();
    }
    if (status == NO_ERROR) {
        getCallback()->resetVolume();
    }
    return status;
}

status_t EffectModule::start_l()
{
    if (mEffectInterface == 0) {
        return NO_INIT;
    }
    if (mStatus != NO_ERROR) {
        return mStatus;
    }
    status_t cmdStatus;
    uint32_t size = sizeof(status_t);
    status_t status = mEffectInterface->command(EFFECT_CMD_ENABLE,
                                                0,
                                                NULL,
                                                &size,
                                                &cmdStatus);
    if (status == 0) {
        status = cmdStatus;
    }
    if (status == 0) {
        addEffectToHal_l();
    }
    return status;
}

status_t EffectModule::stop()
{
    audio_utils::lock_guard _l(mutex());
    return stop_l();
}

status_t EffectModule::stop_l()
{
    if (mEffectInterface == 0) {
        return NO_INIT;
    }
    if (mStatus != NO_ERROR) {
        return mStatus;
    }
    status_t cmdStatus = NO_ERROR;
    uint32_t size = sizeof(status_t);

    if (isVolumeControl() && isOffloadedOrDirect()) {
        // We have the EffectChain and EffectModule lock, permit a reentrant call to setVolume:
        // resetVolume_l --> setVolume_l --> EffectModule::setVolume
        mSetVolumeReentrantTid = gettid();
        getCallback()->resetVolume();
        mSetVolumeReentrantTid = INVALID_PID;
    }

    status_t status = mEffectInterface->command(EFFECT_CMD_DISABLE,
                                                0,
                                                NULL,
                                                &size,
                                                &cmdStatus);
    if (status == NO_ERROR) {
        status = cmdStatus;
    }
    if (status == NO_ERROR) {
        status = removeEffectFromHal_l();
    }
    return status;
}

// must be called with EffectChain::mutex() held
void EffectModule::release_l()
{
    if (mEffectInterface != 0) {
        removeEffectFromHal_l();
        // release effect engine
        mEffectInterface->close();
        mEffectInterface.clear();
    }
}

status_t EffectModule::removeEffectFromHal_l()
{
    if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
             (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
        if (mCurrentHalStream != getCallback()->io()) {
            return (mCurrentHalStream == AUDIO_IO_HANDLE_NONE) ? NO_ERROR : INVALID_OPERATION;
        }
        getCallback()->removeEffectFromHal(mEffectInterface);
        mCurrentHalStream = AUDIO_IO_HANDLE_NONE;
    }
    return NO_ERROR;
}

// round up delta valid if value and divisor are positive.
template <typename T>
static T roundUpDelta(const T &value, const T &divisor) {
    T remainder = value % divisor;
    return remainder == 0 ? 0 : divisor - remainder;
}

status_t EffectModule::command(int32_t cmdCode,
                     const std::vector<uint8_t>& cmdData,
                     int32_t maxReplySize,
                     std::vector<uint8_t>* reply)
{
    audio_utils::lock_guard _l(mutex());
    ALOGVV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface.get());

    if (mState == DESTROYED || mEffectInterface == 0) {
        return NO_INIT;
    }
    if (mStatus != NO_ERROR) {
        return mStatus;
    }
    if (maxReplySize < 0 || maxReplySize > EFFECT_PARAM_SIZE_MAX) {
        return -EINVAL;
    }
    size_t cmdSize = cmdData.size();
    const effect_param_t* param = cmdSize >= sizeof(effect_param_t)
                                  ? reinterpret_cast<const effect_param_t*>(cmdData.data())
                                  : nullptr;
    if (cmdCode == EFFECT_CMD_GET_PARAM &&
            (param == nullptr || param->psize > cmdSize - sizeof(effect_param_t))) {
        android_errorWriteLog(0x534e4554, "32438594");
        android_errorWriteLog(0x534e4554, "33003822");
        return -EINVAL;
    }
    if (cmdCode == EFFECT_CMD_GET_PARAM &&
            (maxReplySize < static_cast<signed>(sizeof(effect_param_t)) ||
                   param->psize > maxReplySize - sizeof(effect_param_t))) {
        android_errorWriteLog(0x534e4554, "29251553");
        return -EINVAL;
    }
    if (cmdCode == EFFECT_CMD_GET_PARAM &&
            (static_cast<signed>(sizeof(effect_param_t)) > maxReplySize
                    || param->psize > maxReplySize - sizeof(effect_param_t)
                    || param->vsize > maxReplySize - sizeof(effect_param_t)
                            - param->psize
                    || roundUpDelta(param->psize, (uint32_t) sizeof(int)) >
                            maxReplySize
                                    - sizeof(effect_param_t)
                                    - param->psize
                                    - param->vsize)) {
        ALOGV("\tLVM_ERROR : EFFECT_CMD_GET_PARAM: reply size inconsistent");
                     android_errorWriteLog(0x534e4554, "32705438");
        return -EINVAL;
    }
    if ((cmdCode == EFFECT_CMD_SET_PARAM
            || cmdCode == EFFECT_CMD_SET_PARAM_DEFERRED)
            &&  // DEFERRED not generally used
                    (param == nullptr
                            || param->psize > cmdSize - sizeof(effect_param_t)
                            || param->vsize > cmdSize - sizeof(effect_param_t)
                                    - param->psize
                            || roundUpDelta(param->psize,
                                            (uint32_t) sizeof(int)) >
                                    cmdSize
                                            - sizeof(effect_param_t)
                                            - param->psize
                                            - param->vsize)) {
        android_errorWriteLog(0x534e4554, "30204301");
        return -EINVAL;
    }
    uint32_t replySize = maxReplySize;
    reply->resize(replySize);
    status_t status = mEffectInterface->command(cmdCode,
                                                cmdSize,
                                                const_cast<uint8_t*>(cmdData.data()),
                                                &replySize,
                                                reply->data());
    reply->resize(status == NO_ERROR ? replySize : 0);
    if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
        for (size_t i = 1; i < mHandles.size(); i++) {
            IAfEffectHandle *h = mHandles[i];
            if (h != NULL && !h->disconnected()) {
                h->commandExecuted(cmdCode, cmdData, *reply);
            }
        }
    }
    return status;
}

bool EffectModule::isProcessEnabled() const
{
    if (mStatus != NO_ERROR) {
        return false;
    }

    switch (mState) {
    case RESTART:
    case ACTIVE:
    case STOPPING:
    case STOPPED:
        return true;
    case IDLE:
    case STARTING:
    case DESTROYED:
    default:
        return false;
    }
}

bool EffectModule::isOffloadedOrDirect() const
{
    return getCallback()->isOffloadOrDirect();
}

bool EffectModule::isVolumeControlEnabled() const
{
    return (isVolumeControl() && (isOffloadedOrDirect() ? isEnabled() : isProcessEnabled()));
}

void EffectModule::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
    ALOGVV("setInBuffer %p",(&buffer));

    // mConfig.inputCfg.buffer.frameCount may be zero if configure() is not called yet.
    if (buffer != 0) {
        mConfig.inputCfg.buffer.raw = buffer->audioBuffer()->raw;
        buffer->setFrameCount(mConfig.inputCfg.buffer.frameCount);
    } else {
        mConfig.inputCfg.buffer.raw = NULL;
    }
    mInBuffer = buffer;
    mEffectInterface->setInBuffer(buffer);

    // aux effects do in place conversion to float - we don't allocate mInConversionBuffer.
    // Theoretically insert effects can also do in-place conversions (destroying
    // the original buffer) when the output buffer is identical to the input buffer,
    // but we don't optimize for it here.
    const bool auxType = (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY;
    const uint32_t inChannelCount =
            audio_channel_count_from_out_mask(mConfig.inputCfg.channels);
    const bool formatMismatch = !mSupportsFloat || mInChannelCountRequested != inChannelCount;
    if (!auxType && formatMismatch && mInBuffer != nullptr) {
        // we need to translate - create hidl shared buffer and intercept
        const size_t inFrameCount = mConfig.inputCfg.buffer.frameCount;
        // Use FCC_2 in case mInChannelCountRequested is mono and the effect is stereo.
        const uint32_t inChannels = std::max((uint32_t)FCC_2, mInChannelCountRequested);
        const size_t size = inChannels * inFrameCount * std::max(sizeof(int16_t), sizeof(float));

        ALOGV("%s: setInBuffer updating for inChannels:%d inFrameCount:%zu total size:%zu",
                __func__, inChannels, inFrameCount, size);

        if (size > 0 && (mInConversionBuffer == nullptr
                || size > mInConversionBuffer->getSize())) {
            mInConversionBuffer.clear();
            ALOGV("%s: allocating mInConversionBuffer %zu", __func__, size);
            (void)getCallback()->allocateHalBuffer(size, &mInConversionBuffer);
        }
        if (mInConversionBuffer != nullptr) {
            mInConversionBuffer->setFrameCount(inFrameCount);
            mEffectInterface->setInBuffer(mInConversionBuffer);
        } else if (size > 0) {
            ALOGE("%s cannot create mInConversionBuffer", __func__);
        }
    }
}

void EffectModule::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
    ALOGVV("setOutBuffer %p",(&buffer));

    // mConfig.outputCfg.buffer.frameCount may be zero if configure() is not called yet.
    if (buffer != 0) {
        mConfig.outputCfg.buffer.raw = buffer->audioBuffer()->raw;
        buffer->setFrameCount(mConfig.outputCfg.buffer.frameCount);
    } else {
        mConfig.outputCfg.buffer.raw = NULL;
    }
    mOutBuffer = buffer;
    mEffectInterface->setOutBuffer(buffer);

    // Note: Any effect that does not accumulate does not need mOutConversionBuffer and
    // can do in-place conversion from int16_t to float.  We don't optimize here.
    const uint32_t outChannelCount =
            audio_channel_count_from_out_mask(mConfig.outputCfg.channels);
    const bool formatMismatch = !mSupportsFloat || mOutChannelCountRequested != outChannelCount;
    if (formatMismatch && mOutBuffer != nullptr) {
        const size_t outFrameCount = mConfig.outputCfg.buffer.frameCount;
        // Use FCC_2 in case mOutChannelCountRequested is mono and the effect is stereo.
        const uint32_t outChannels = std::max((uint32_t)FCC_2, mOutChannelCountRequested);
        const size_t size = outChannels * outFrameCount * std::max(sizeof(int16_t), sizeof(float));

        ALOGV("%s: setOutBuffer updating for outChannels:%d outFrameCount:%zu total size:%zu",
                __func__, outChannels, outFrameCount, size);

        if (size > 0 && (mOutConversionBuffer == nullptr
                || size > mOutConversionBuffer->getSize())) {
            mOutConversionBuffer.clear();
            ALOGV("%s: allocating mOutConversionBuffer %zu", __func__, size);
            (void)getCallback()->allocateHalBuffer(size, &mOutConversionBuffer);
        }
        if (mOutConversionBuffer != nullptr) {
            mOutConversionBuffer->setFrameCount(outFrameCount);
            mEffectInterface->setOutBuffer(mOutConversionBuffer);
        } else if (size > 0) {
            ALOGE("%s cannot create mOutConversionBuffer", __func__);
        }
    }
}

status_t EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
{
    AutoLockReentrant _l(mutex(), mSetVolumeReentrantTid);
    if (mStatus != NO_ERROR) {
        return mStatus;
    }
    status_t status = NO_ERROR;
    // Send volume indication if EFFECT_FLAG_VOLUME_IND is set and read back altered volume
    // if controller flag is set (Note that controller == TRUE => EFFECT_FLAG_VOLUME_CTRL set)
    if (isProcessEnabled() &&
            ((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
             (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND ||
             (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_MONITOR)) {
        status = setVolumeInternal(left, right, controller);
    }
    return status;
}

status_t EffectModule::setVolumeInternal(
        uint32_t *left, uint32_t *right, bool controller) {
    uint32_t volume[2] = {*left, *right};
    uint32_t *pVolume = controller ? volume : nullptr;
    uint32_t size = sizeof(volume);
    status_t status = mEffectInterface->command(EFFECT_CMD_SET_VOLUME,
                                                size,
                                                volume,
                                                &size,
                                                pVolume);
    if (controller && status == NO_ERROR && size == sizeof(volume)) {
        *left = volume[0];
        *right = volume[1];
    }
    return status;
}

void EffectChain::setVolumeForOutput_l(uint32_t left, uint32_t right)
{
    // for offload or direct thread, if the effect chain has non-offloadable
    // effect and any effect module within the chain has volume control, then
    // volume control is delegated to effect, otherwise, set volume to hal.
    if (mEffectCallback->isOffloadOrDirect() &&
        !(isNonOffloadableEnabled_l() && hasVolumeControlEnabled_l())) {
        float vol_l = (float)left / (1 << 24);
        float vol_r = (float)right / (1 << 24);
        mEffectCallback->setVolumeForOutput(vol_l, vol_r);
    }
}

status_t EffectModule::sendSetAudioDevicesCommand(
        const AudioDeviceTypeAddrVector &devices, uint32_t cmdCode)
{
    audio_devices_t deviceType = deviceTypesToBitMask(getAudioDeviceTypes(devices));
    if (deviceType == AUDIO_DEVICE_NONE) {
        return NO_ERROR;
    }

    audio_utils::lock_guard _l(mutex());
    if (mStatus != NO_ERROR) {
        return mStatus;
    }
    status_t status = NO_ERROR;
    if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
        status_t cmdStatus;
        uint32_t size = sizeof(status_t);
        // FIXME: use audio device types and addresses when the hal interface is ready.
        status = mEffectInterface->command(cmdCode,
                                           sizeof(uint32_t),
                                           &deviceType,
                                           &size,
                                           &cmdStatus);
    }
    return status;
}

status_t EffectModule::setDevices(const AudioDeviceTypeAddrVector &devices)
{
    return sendSetAudioDevicesCommand(devices, EFFECT_CMD_SET_DEVICE);
}

status_t EffectModule::setInputDevice(const AudioDeviceTypeAddr &device)
{
    return sendSetAudioDevicesCommand({device}, EFFECT_CMD_SET_INPUT_DEVICE);
}

status_t EffectModule::setMode(audio_mode_t mode)
{
    audio_utils::lock_guard _l(mutex());
    if (mStatus != NO_ERROR) {
        return mStatus;
    }
    status_t status = NO_ERROR;
    if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
        status_t cmdStatus;
        uint32_t size = sizeof(status_t);
        status = mEffectInterface->command(EFFECT_CMD_SET_AUDIO_MODE,
                                           sizeof(audio_mode_t),
                                           &mode,
                                           &size,
                                           &cmdStatus);
        if (status == NO_ERROR) {
            status = cmdStatus;
        }
    }
    return status;
}

status_t EffectModule::setAudioSource(audio_source_t source)
{
    audio_utils::lock_guard _l(mutex());
    if (mStatus != NO_ERROR) {
        return mStatus;
    }
    status_t status = NO_ERROR;
    if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_SOURCE_MASK) == EFFECT_FLAG_AUDIO_SOURCE_IND) {
        uint32_t size = 0;
        status = mEffectInterface->command(EFFECT_CMD_SET_AUDIO_SOURCE,
                                           sizeof(audio_source_t),
                                           &source,
                                           &size,
                                           NULL);
    }
    return status;
}

status_t EffectModule::setOffloaded(bool offloaded, audio_io_handle_t io)
{
    audio_utils::lock_guard _l(mutex());
    if (mStatus != NO_ERROR) {
        return mStatus;
    }
    status_t status = NO_ERROR;
    if ((mDescriptor.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) != 0) {
        status_t cmdStatus;
        uint32_t size = sizeof(status_t);
        effect_offload_param_t cmd;

        cmd.isOffload = offloaded;
        cmd.ioHandle = io;
        status = mEffectInterface->command(EFFECT_CMD_OFFLOAD,
                                           sizeof(effect_offload_param_t),
                                           &cmd,
                                           &size,
                                           &cmdStatus);
        if (status == NO_ERROR) {
            status = cmdStatus;
        }
        mOffloaded = (status == NO_ERROR) ? offloaded : false;
    } else {
        if (offloaded) {
            status = INVALID_OPERATION;
        }
        mOffloaded = false;
    }
    ALOGV("setOffloaded() offloaded %d io %d status %d", offloaded, io, status);
    return status;
}

bool EffectModule::isOffloaded() const
{
    audio_utils::lock_guard _l(mutex());
    return mOffloaded;
}

/*static*/
bool IAfEffectModule::isHapticGenerator(const effect_uuid_t *type) {
    return memcmp(type, FX_IID_HAPTICGENERATOR, sizeof(effect_uuid_t)) == 0;
}

bool EffectModule::isHapticGenerator() const {
    return IAfEffectModule::isHapticGenerator(&mDescriptor.type);
}

status_t EffectModule::setHapticIntensity(int id, os::HapticScale intensity)
{
    if (mStatus != NO_ERROR) {
        return mStatus;
    }
    if (!isHapticGenerator()) {
        ALOGW("Should not set haptic intensity for effects that are not HapticGenerator");
        return INVALID_OPERATION;
    }

    std::vector<uint8_t> request(sizeof(effect_param_t) + 3 * sizeof(uint32_t));
    effect_param_t *param = (effect_param_t*) request.data();
    param->psize = sizeof(int32_t);
    param->vsize = sizeof(int32_t) * 2;
    *(int32_t*)param->data = HG_PARAM_HAPTIC_INTENSITY;
    *((int32_t*)param->data + 1) = id;
    *((int32_t*)param->data + 2) = static_cast<int32_t>(intensity);
    std::vector<uint8_t> response;
    status_t status = command(EFFECT_CMD_SET_PARAM, request, sizeof(int32_t), &response);
    if (status == NO_ERROR) {
        LOG_ALWAYS_FATAL_IF(response.size() != 4);
        status = *reinterpret_cast<const status_t*>(response.data());
    }
    return status;
}

status_t EffectModule::setVibratorInfo(const media::AudioVibratorInfo& vibratorInfo)
{
    if (mStatus != NO_ERROR) {
        return mStatus;
    }
    if (!isHapticGenerator()) {
        ALOGW("Should not set vibrator info for effects that are not HapticGenerator");
        return INVALID_OPERATION;
    }

    const size_t paramCount = 3;
    std::vector<uint8_t> request(
            sizeof(effect_param_t) + sizeof(int32_t) + paramCount * sizeof(float));
    effect_param_t *param = (effect_param_t*) request.data();
    param->psize = sizeof(int32_t);
    param->vsize = paramCount * sizeof(float);
    *(int32_t*)param->data = HG_PARAM_VIBRATOR_INFO;
    float* vibratorInfoPtr = reinterpret_cast<float*>(param->data + sizeof(int32_t));
    vibratorInfoPtr[0] = vibratorInfo.resonantFrequency;
    vibratorInfoPtr[1] = vibratorInfo.qFactor;
    vibratorInfoPtr[2] = vibratorInfo.maxAmplitude;
    std::vector<uint8_t> response;
    status_t status = command(EFFECT_CMD_SET_PARAM, request, sizeof(int32_t), &response);
    if (status == NO_ERROR) {
        LOG_ALWAYS_FATAL_IF(response.size() != sizeof(status_t));
        status = *reinterpret_cast<const status_t*>(response.data());
    }
    return status;
}

status_t EffectModule::getConfigs(
        audio_config_base_t* inputCfg, audio_config_base_t* outputCfg, bool* isOutput) const {
    audio_utils::lock_guard _l(mutex());
    if (mConfig.inputCfg.mask == 0 || mConfig.outputCfg.mask == 0) {
        return NO_INIT;
    }
    inputCfg->sample_rate = mConfig.inputCfg.samplingRate;
    inputCfg->channel_mask = static_cast<audio_channel_mask_t>(mConfig.inputCfg.channels);
    inputCfg->format = static_cast<audio_format_t>(mConfig.inputCfg.format);
    outputCfg->sample_rate = mConfig.outputCfg.samplingRate;
    outputCfg->channel_mask = static_cast<audio_channel_mask_t>(mConfig.outputCfg.channels);
    outputCfg->format = static_cast<audio_format_t>(mConfig.outputCfg.format);
    *isOutput = mIsOutput;
    return NO_ERROR;
}

static std::string dumpInOutBuffer(bool isInput, const sp<EffectBufferHalInterface> &buffer) {
    std::stringstream ss;

    if (buffer == nullptr) {
        return "nullptr"; // make different than below
    } else if (buffer->externalData() != nullptr) {
        ss << (isInput ? buffer->externalData() : buffer->audioBuffer()->raw)
                << " -> "
                << (isInput ? buffer->audioBuffer()->raw : buffer->externalData());
    } else {
        ss << buffer->audioBuffer()->raw;
    }
    return ss.str();
}

void EffectModule::dump(int fd, const Vector<String16>& args) const
NO_THREAD_SAFETY_ANALYSIS  // conditional try lock
{
    EffectBase::dump(fd, args);

    String8 result;
    const bool locked = afutils::dumpTryLock(mutex());

    result.append("\t\tStatus Engine:\n");
    result.appendFormat("\t\t%03d    %p\n",
            mStatus, mEffectInterface.get());

    result.appendFormat("\t\t- data: %s\n", mSupportsFloat ? "float" : "int16");

    result.append("\t\t- Input configuration:\n");
    result.append("\t\t\tBuffer     Frames  Smp rate Channels Format\n");
    result.appendFormat("\t\t\t%p %05zu   %05d    %08x %6d (%s)\n",
            mConfig.inputCfg.buffer.raw,
            mConfig.inputCfg.buffer.frameCount,
            mConfig.inputCfg.samplingRate,
            mConfig.inputCfg.channels,
            mConfig.inputCfg.format,
            toString(static_cast<audio_format_t>(mConfig.inputCfg.format)).c_str());

    result.append("\t\t- Output configuration:\n");
    result.append("\t\t\tBuffer     Frames  Smp rate Channels Format\n");
    result.appendFormat("\t\t\t%p %05zu   %05d    %08x %6d (%s)\n",
            mConfig.outputCfg.buffer.raw,
            mConfig.outputCfg.buffer.frameCount,
            mConfig.outputCfg.samplingRate,
            mConfig.outputCfg.channels,
            mConfig.outputCfg.format,
            toString(static_cast<audio_format_t>(mConfig.outputCfg.format)).c_str());

    result.appendFormat("\t\t- HAL buffers:\n"
            "\t\t\tIn(%s) InConversion(%s) Out(%s) OutConversion(%s)\n",
            dumpInOutBuffer(true /* isInput */, mInBuffer).c_str(),
            dumpInOutBuffer(true /* isInput */, mInConversionBuffer).c_str(),
            dumpInOutBuffer(false /* isInput */, mOutBuffer).c_str(),
            dumpInOutBuffer(false /* isInput */, mOutConversionBuffer).c_str());

    write(fd, result.c_str(), result.length());

    if (mEffectInterface != 0) {
        dprintf(fd, "\tEffect ID %d HAL dump:\n", mId);
        (void)mEffectInterface->dump(fd);
    }

    if (locked) {
        mutex().unlock();
    }
}

// ----------------------------------------------------------------------------
//  EffectHandle implementation
// ----------------------------------------------------------------------------

#undef LOG_TAG
#define LOG_TAG "EffectHandle"

/* static */
sp<IAfEffectHandle> IAfEffectHandle::create(
        const sp<IAfEffectBase>& effect,
        const sp<Client>& client,
        const sp<media::IEffectClient>& effectClient,
        int32_t priority, bool notifyFramesProcessed)
{
    return sp<EffectHandle>::make(
            effect, client, effectClient, priority, notifyFramesProcessed);
}

EffectHandle::EffectHandle(const sp<IAfEffectBase>& effect,
                                         const sp<Client>& client,
                                         const sp<media::IEffectClient>& effectClient,
                                         int32_t priority, bool notifyFramesProcessed)
    : BnEffect(),
    mEffect(effect), mEffectClient(effectClient), mClient(client), mCblk(NULL),
    mPriority(priority), mHasControl(false), mEnabled(false), mDisconnected(false),
    mNotifyFramesProcessed(notifyFramesProcessed)
{
    ALOGV("constructor %p client %p", this, client.get());
    setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);

    if (client == 0) {
        return;
    }
    int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
    mCblkMemory = client->allocator().allocate(mediautils::NamedAllocRequest{
            {static_cast<size_t>(EFFECT_PARAM_BUFFER_SIZE + bufOffset)},
            std::string("Effect ID: ")
                    .append(std::to_string(effect->id()))
                    .append(" Session ID: ")
                    .append(std::to_string(static_cast<int>(effect->sessionId())))
                    .append(" \n")
            });
    if (mCblkMemory == 0 ||
            (mCblk = static_cast<effect_param_cblk_t *>(mCblkMemory->unsecurePointer())) == NULL) {
        ALOGE("not enough memory for Effect size=%zu", EFFECT_PARAM_BUFFER_SIZE +
                sizeof(effect_param_cblk_t));
        mCblkMemory.clear();
        return;
    }
    new(mCblk) effect_param_cblk_t();
    mBuffer = (uint8_t *)mCblk + bufOffset;
}

EffectHandle::~EffectHandle()
{
    ALOGV("Destructor %p", this);
    disconnect(false);
}

// Creates an association between Binder code to name for IEffect.
#define IEFFECT_BINDER_METHOD_MACRO_LIST \
BINDER_METHOD_ENTRY(enable) \
BINDER_METHOD_ENTRY(disable) \
BINDER_METHOD_ENTRY(command) \
BINDER_METHOD_ENTRY(disconnect) \
BINDER_METHOD_ENTRY(getCblk) \
BINDER_METHOD_ENTRY(getConfig) \

// singleton for Binder Method Statistics for IEffect
mediautils::MethodStatistics<int>& getIEffectStatistics() {
    using Code = int;

#pragma push_macro("BINDER_METHOD_ENTRY")
#undef BINDER_METHOD_ENTRY
#define BINDER_METHOD_ENTRY(ENTRY) \
        {(Code)media::BnEffect::TRANSACTION_##ENTRY, #ENTRY},

    static mediautils::MethodStatistics<Code> methodStatistics{
        IEFFECT_BINDER_METHOD_MACRO_LIST
        METHOD_STATISTICS_BINDER_CODE_NAMES(Code)
    };
#pragma pop_macro("BINDER_METHOD_ENTRY")

    return methodStatistics;
}

status_t EffectHandle::onTransact(
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
    const std::string methodName = getIEffectStatistics().getMethodForCode(code);
    mediautils::TimeCheck check(
            std::string("IEffect::").append(methodName),
            [code](bool timeout, float elapsedMs) {
        if (timeout) {
            ; // we don't timeout right now on the effect interface.
        } else {
            getIEffectStatistics().event(code, elapsedMs);
        }
    }, {} /* timeoutDuration */, {} /* secondChanceDuration */, false /* crashOnTimeout */);
    return BnEffect::onTransact(code, data, reply, flags);
}

status_t EffectHandle::initCheck() const
{
    return mClient == 0 || mCblkMemory != 0 ? OK : NO_MEMORY;
}

#define RETURN(code) \
  *_aidl_return = (code); \
  return Status::ok();

#define VALUE_OR_RETURN_STATUS_AS_OUT(exp)              \
    ({                                                  \
        auto _tmp = (exp);                              \
        if (!_tmp.ok()) { RETURN(_tmp.error()); }       \
        std::move(_tmp.value());                        \
    })

Status EffectHandle::enable(int32_t* _aidl_return)
{
    audio_utils::lock_guard _l(mutex());
    ALOGV("enable %p", this);
    sp<IAfEffectBase> effect = mEffect.promote();
    if (effect == 0 || mDisconnected) {
        RETURN(DEAD_OBJECT);
    }
    if (!mHasControl) {
        RETURN(INVALID_OPERATION);
    }

    if (mEnabled) {
        RETURN(NO_ERROR);
    }

    mEnabled = true;

    status_t status = effect->updatePolicyState();
    if (status != NO_ERROR) {
        mEnabled = false;
        RETURN(status);
    }

    effect->checkSuspendOnEffectEnabled(true, false /*threadLocked*/);

    // checkSuspendOnEffectEnabled() can suspend this same effect when enabled
    if (effect->suspended()) {
        RETURN(NO_ERROR);
    }

    status = effect->setEnabled(true, true /*fromHandle*/);
    if (status != NO_ERROR) {
        mEnabled = false;
    }
    RETURN(status);
}

Status EffectHandle::disable(int32_t* _aidl_return)
{
    ALOGV("disable %p", this);
    audio_utils::lock_guard _l(mutex());
    sp<IAfEffectBase> effect = mEffect.promote();
    if (effect == 0 || mDisconnected) {
        RETURN(DEAD_OBJECT);
    }
    if (!mHasControl) {
        RETURN(INVALID_OPERATION);
    }

    if (!mEnabled) {
        RETURN(NO_ERROR);
    }
    mEnabled = false;

    effect->updatePolicyState();

    if (effect->suspended()) {
        RETURN(NO_ERROR);
    }

    status_t status = effect->setEnabled(false, true /*fromHandle*/);
    RETURN(status);
}

Status EffectHandle::disconnect()
{
    ALOGV("%s %p", __FUNCTION__, this);
    disconnect(true);
    return Status::ok();
}

void EffectHandle::disconnect(bool unpinIfLast)
{
    audio_utils::lock_guard _l(mutex());
    ALOGV("disconnect(%s) %p", unpinIfLast ? "true" : "false", this);
    if (mDisconnected) {
        if (unpinIfLast) {
            android_errorWriteLog(0x534e4554, "32707507");
        }
        return;
    }
    mDisconnected = true;
    {
        sp<IAfEffectBase> effect = mEffect.promote();
        if (effect != 0) {
            if (effect->disconnectHandle(this, unpinIfLast) > 0) {
                ALOGW("%s Effect handle %p disconnected after thread destruction",
                    __func__, this);
            }
            effect->updatePolicyState();
        }
    }

    if (mClient != 0) {
        if (mCblk != NULL) {
            // unlike ~TrackBase(), mCblk is never a local new, so don't delete
            mCblk->~effect_param_cblk_t();   // destroy our shared-structure.
        }
        mCblkMemory.clear();    // free the shared memory before releasing the heap it belongs to
        // Client destructor must run with AudioFlinger client mutex locked
        audio_utils::lock_guard _l2(mClient->afClientCallback()->clientMutex());
        mClient.clear();
    }
}

Status EffectHandle::getCblk(media::SharedFileRegion* _aidl_return) {
    LOG_ALWAYS_FATAL_IF(!convertIMemoryToSharedFileRegion(mCblkMemory, _aidl_return));
    return Status::ok();
}

Status EffectHandle::getConfig(
        media::EffectConfig* _config, int32_t* _aidl_return) {
    audio_utils::lock_guard _l(mutex());
    sp<IAfEffectBase> effect = mEffect.promote();
    if (effect == nullptr || mDisconnected) {
        RETURN(DEAD_OBJECT);
    }
    sp<IAfEffectModule> effectModule = effect->asEffectModule();
    if (effectModule == nullptr) {
        RETURN(INVALID_OPERATION);
    }
    audio_config_base_t inputCfg = AUDIO_CONFIG_BASE_INITIALIZER;
    audio_config_base_t outputCfg = AUDIO_CONFIG_BASE_INITIALIZER;
    bool isOutput;
    status_t status = effectModule->getConfigs(&inputCfg, &outputCfg, &isOutput);
    if (status == NO_ERROR) {
        constexpr bool isInput = false; // effects always use 'OUT' channel masks.
        _config->inputCfg = VALUE_OR_RETURN_STATUS_AS_OUT(
                legacy2aidl_audio_config_base_t_AudioConfigBase(inputCfg, isInput));
        _config->outputCfg = VALUE_OR_RETURN_STATUS_AS_OUT(
                legacy2aidl_audio_config_base_t_AudioConfigBase(outputCfg, isInput));
        _config->isOnInputStream = !isOutput;
    }
    RETURN(status);
}

Status EffectHandle::command(int32_t cmdCode,
                       const std::vector<uint8_t>& cmdData,
                       int32_t maxResponseSize,
                       std::vector<uint8_t>* response,
                       int32_t* _aidl_return)
{
    ALOGVV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p",
            cmdCode, mHasControl, mEffect.unsafe_get());

    // reject commands reserved for internal use by audio framework if coming from outside
    // of audioserver
    switch(cmdCode) {
        case EFFECT_CMD_ENABLE:
        case EFFECT_CMD_DISABLE:
        case EFFECT_CMD_SET_PARAM:
        case EFFECT_CMD_SET_PARAM_DEFERRED:
        case EFFECT_CMD_SET_PARAM_COMMIT:
        case EFFECT_CMD_GET_PARAM:
            break;
        default:
            if (cmdCode >= EFFECT_CMD_FIRST_PROPRIETARY) {
                break;
            }
            android_errorWriteLog(0x534e4554, "62019992");
            RETURN(BAD_VALUE);
    }

    if (cmdCode == EFFECT_CMD_ENABLE) {
        if (maxResponseSize < static_cast<signed>(sizeof(int))) {
            android_errorWriteLog(0x534e4554, "32095713");
            RETURN(BAD_VALUE);
        }
        writeToBuffer(NO_ERROR, response);
        return enable(_aidl_return);
    } else if (cmdCode == EFFECT_CMD_DISABLE) {
        if (maxResponseSize < static_cast<signed>(sizeof(int))) {
            android_errorWriteLog(0x534e4554, "32095713");
            RETURN(BAD_VALUE);
        }
        writeToBuffer(NO_ERROR, response);
        return disable(_aidl_return);
    }

    audio_utils::lock_guard _l(mutex());
    sp<IAfEffectBase> effect = mEffect.promote();
    if (effect == 0 || mDisconnected) {
        RETURN(DEAD_OBJECT);
    }
    // only get parameter command is permitted for applications not controlling the effect
    if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) {
        RETURN(INVALID_OPERATION);
    }

    // handle commands that are not forwarded transparently to effect engine
    if (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) {
        if (mClient == 0) {
            RETURN(INVALID_OPERATION);
        }

        if (maxResponseSize < (signed)sizeof(int)) {
            android_errorWriteLog(0x534e4554, "32095713");
            RETURN(BAD_VALUE);
        }
        writeToBuffer(NO_ERROR, response);

        // No need to trylock() here as this function is executed in the binder thread serving a
        // particular client process:  no risk to block the whole media server process or mixer
        // threads if we are stuck here
        Mutex::Autolock _l2(mCblk->lock);
        // keep local copy of index in case of client corruption b/32220769
        const uint32_t clientIndex = mCblk->clientIndex;
        const uint32_t serverIndex = mCblk->serverIndex;
        if (clientIndex > EFFECT_PARAM_BUFFER_SIZE ||
            serverIndex > EFFECT_PARAM_BUFFER_SIZE) {
            mCblk->serverIndex = 0;
            mCblk->clientIndex = 0;
            RETURN(BAD_VALUE);
        }
        status_t status = NO_ERROR;
        std::vector<uint8_t> param;
        for (uint32_t index = serverIndex; index < clientIndex;) {
            int *p = (int *)(mBuffer + index);
            const int size = *p++;
            if (size < 0
                    || size > EFFECT_PARAM_BUFFER_SIZE
                    || ((uint8_t *)p + size) > mBuffer + clientIndex) {
                ALOGW("command(): invalid parameter block size");
                status = BAD_VALUE;
                break;
            }

            std::copy(reinterpret_cast<const uint8_t*>(p),
                      reinterpret_cast<const uint8_t*>(p) + size,
                      std::back_inserter(param));

            std::vector<uint8_t> replyBuffer;
            status_t ret = effect->command(EFFECT_CMD_SET_PARAM,
                                            param,
                                            sizeof(int),
                                            &replyBuffer);
            int reply = *reinterpret_cast<const int*>(replyBuffer.data());

            // verify shared memory: server index shouldn't change; client index can't go back.
            if (serverIndex != mCblk->serverIndex
                    || clientIndex > mCblk->clientIndex) {
                android_errorWriteLog(0x534e4554, "32220769");
                status = BAD_VALUE;
                break;
            }

            // stop at first error encountered
            if (ret != NO_ERROR) {
                status = ret;
                writeToBuffer(reply, response);
                break;
            } else if (reply != NO_ERROR) {
                writeToBuffer(reply, response);
                break;
            }
            index += size;
        }
        mCblk->serverIndex = 0;
        mCblk->clientIndex = 0;
        RETURN(status);
    }

    status_t status = effect->command(cmdCode,
                                      cmdData,
                                      maxResponseSize,
                                      response);
    RETURN(status);
}

void EffectHandle::setControl(bool hasControl, bool signal, bool enabled)
{
    ALOGV("setControl %p control %d", this, hasControl);

    mHasControl = hasControl;
    mEnabled = enabled;

    if (signal && mEffectClient != 0) {
        mEffectClient->controlStatusChanged(hasControl);
    }
}

void EffectHandle::commandExecuted(uint32_t cmdCode,
                         const std::vector<uint8_t>& cmdData,
                         const std::vector<uint8_t>& replyData)
{
    if (mEffectClient != 0) {
        mEffectClient->commandExecuted(cmdCode, cmdData, replyData);
    }
}



void EffectHandle::setEnabled(bool enabled)
{
    if (mEffectClient != 0) {
        mEffectClient->enableStatusChanged(enabled);
    }
}

void EffectHandle::framesProcessed(int32_t frames) const
{
    if (mEffectClient != 0 && mNotifyFramesProcessed) {
        mEffectClient->framesProcessed(frames);
    }
}

void EffectHandle::dumpToBuffer(char* buffer, size_t size) const
NO_THREAD_SAFETY_ANALYSIS  // conditional try lock
{
    const bool locked = mCblk != nullptr && afutils::dumpTryLock(mCblk->lock);

    snprintf(buffer, size, "\t\t\t%5d    %5d  %3s    %3s  %5u  %5u\n",
            (mClient == 0) ? getpid() : mClient->pid(),
            mPriority,
            mHasControl ? "yes" : "no",
            locked ? "yes" : "no",
            mCblk ? mCblk->clientIndex : 0,
            mCblk ? mCblk->serverIndex : 0
            );

    if (locked) {
        mCblk->lock.unlock();
    }
}

#undef LOG_TAG
#define LOG_TAG "EffectChain"

/* static */
sp<IAfEffectChain> IAfEffectChain::create(
        const sp<IAfThreadBase>& thread,
        audio_session_t sessionId)
{
    return sp<EffectChain>::make(thread, sessionId);
}

EffectChain::EffectChain(const sp<IAfThreadBase>& thread,
                                       audio_session_t sessionId)
    : mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
      mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
      mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX),
      mEffectCallback(new EffectCallback(wp<EffectChain>(this), thread))
{
    mStrategy = thread->getStrategyForStream(AUDIO_STREAM_MUSIC);
    mMaxTailBuffers = ((kProcessTailDurationMs * thread->sampleRate()) / 1000) /
                                    thread->frameCount();
}

// getEffectFromDesc_l() must be called with IAfThreadBase::mutex() held
sp<IAfEffectModule> EffectChain::getEffectFromDesc_l(
        effect_descriptor_t *descriptor) const
{
    size_t size = mEffects.size();

    for (size_t i = 0; i < size; i++) {
        if (memcmp(&mEffects[i]->desc().uuid, &descriptor->uuid, sizeof(effect_uuid_t)) == 0) {
            return mEffects[i];
        }
    }
    return 0;
}

// getEffectFromId_l() must be called with IAfThreadBase::mutex() held
sp<IAfEffectModule> EffectChain::getEffectFromId_l(int id) const
{
    size_t size = mEffects.size();

    for (size_t i = 0; i < size; i++) {
        // by convention, return first effect if id provided is 0 (0 is never a valid id)
        if (id == 0 || mEffects[i]->id() == id) {
            return mEffects[i];
        }
    }
    return 0;
}

// getEffectFromType_l() must be called with IAfThreadBase::mutex() held
sp<IAfEffectModule> EffectChain::getEffectFromType_l(
        const effect_uuid_t *type) const
{
    size_t size = mEffects.size();

    for (size_t i = 0; i < size; i++) {
        if (memcmp(&mEffects[i]->desc().type, type, sizeof(effect_uuid_t)) == 0) {
            return mEffects[i];
        }
    }
    return 0;
}

std::vector<int> EffectChain::getEffectIds() const
{
    std::vector<int> ids;
    audio_utils::lock_guard _l(mutex());
    for (size_t i = 0; i < mEffects.size(); i++) {
        ids.push_back(mEffects[i]->id());
    }
    return ids;
}

void EffectChain::clearInputBuffer()
{
    audio_utils::lock_guard _l(mutex());
    clearInputBuffer_l();
}

// Must be called with EffectChain::mutex() locked
void EffectChain::clearInputBuffer_l()
{
    if (mInBuffer == NULL) {
        return;
    }
    const size_t frameSize = audio_bytes_per_sample(AUDIO_FORMAT_PCM_FLOAT)
            * mEffectCallback->inChannelCount(mEffects[0]->id());

    memset(mInBuffer->audioBuffer()->raw, 0, mEffectCallback->frameCount() * frameSize);
    mInBuffer->commit();
}

// Must be called with EffectChain::mutex() locked
void EffectChain::process_l()
{
    // never process effects when:
    // - on an OFFLOAD thread
    // - no more tracks are on the session and the effect tail has been rendered
    bool doProcess = !mEffectCallback->isOffloadOrMmap();
    if (!audio_is_global_session(mSessionId)) {
        bool tracksOnSession = (trackCnt() != 0);

        if (!tracksOnSession && mTailBufferCount == 0) {
            doProcess = false;
        }

        if (activeTrackCnt() == 0) {
            // if no track is active and the effect tail has not been rendered,
            // the input buffer must be cleared here as the mixer process will not do it
            if (tracksOnSession || mTailBufferCount > 0) {
                clearInputBuffer_l();
                if (mTailBufferCount > 0) {
                    mTailBufferCount--;
                }
            }
        }
    }

    size_t size = mEffects.size();
    if (doProcess) {
        // Only the input and output buffers of the chain can be external,
        // and 'update' / 'commit' do nothing for allocated buffers, thus
        // it's not needed to consider any other buffers here.
        mInBuffer->update();
        if (mInBuffer->audioBuffer()->raw != mOutBuffer->audioBuffer()->raw) {
            mOutBuffer->update();
        }
        for (size_t i = 0; i < size; i++) {
            mEffects[i]->process();
        }
        mInBuffer->commit();
        if (mInBuffer->audioBuffer()->raw != mOutBuffer->audioBuffer()->raw) {
            mOutBuffer->commit();
        }
    }
    bool doResetVolume = false;
    for (size_t i = 0; i < size; i++) {
        doResetVolume = mEffects[i]->updateState() || doResetVolume;
    }
    if (doResetVolume) {
        resetVolume_l();
    }
}

// createEffect_l() must be called with IAfThreadBase::mutex() held
status_t EffectChain::createEffect_l(sp<IAfEffectModule>& effect,
                                                   effect_descriptor_t *desc,
                                                   int id,
                                                   audio_session_t sessionId,
                                                   bool pinned)
{
    audio_utils::lock_guard _l(mutex());
    effect = new EffectModule(mEffectCallback, desc, id, sessionId, pinned, AUDIO_PORT_HANDLE_NONE);
    status_t lStatus = effect->status();
    if (lStatus == NO_ERROR) {
        lStatus = addEffect_ll(effect);
    }
    if (lStatus != NO_ERROR) {
        effect.clear();
    }
    return lStatus;
}

// addEffect_l() must be called with IAfThreadBase::mutex() held
status_t EffectChain::addEffect_l(const sp<IAfEffectModule>& effect)
{
    audio_utils::lock_guard _l(mutex());
    return addEffect_ll(effect);
}
// addEffect_l() must be called with IAfThreadBase::mutex() and EffectChain::mutex() held
status_t EffectChain::addEffect_ll(const sp<IAfEffectModule>& effect)
{
    effect->setCallback(mEffectCallback);

    effect_descriptor_t desc = effect->desc();
    if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
        // Auxiliary effects are inserted at the beginning of mEffects vector as
        // they are processed first and accumulated in chain input buffer
        mEffects.insertAt(effect, 0);

        // the input buffer for auxiliary effect contains mono samples in
        // 32 bit format. This is to avoid saturation in AudoMixer
        // accumulation stage. Saturation is done in EffectModule::process() before
        // calling the process in effect engine
        size_t numSamples = mEffectCallback->frameCount();
        sp<EffectBufferHalInterface> halBuffer;

        status_t result = mEffectCallback->allocateHalBuffer(
                numSamples * sizeof(float), &halBuffer);
        if (result != OK) return result;

        effect->configure();

        effect->setInBuffer(halBuffer);
        // auxiliary effects output samples to chain input buffer for further processing
        // by insert effects
        effect->setOutBuffer(mInBuffer);
    } else {
        ssize_t idx_insert = getInsertIndex(desc);
        if (idx_insert < 0) {
            return INVALID_OPERATION;
        }

        size_t previousSize = mEffects.size();
        mEffects.insertAt(effect, idx_insert);

        effect->configure();

        // - By default:
        //   All effects read samples from chain input buffer.
        //   The last effect in the chain, writes samples to chain output buffer,
        //   otherwise to chain input buffer
        // - In the OUTPUT_STAGE chain of a spatializer mixer thread:
        //   The spatializer effect (first effect) reads samples from the input buffer
        //   and writes samples to the output buffer.
        //   All other effects read and writes samples to the output buffer
        if (mEffectCallback->isSpatializer()
                && mSessionId == AUDIO_SESSION_OUTPUT_STAGE) {
            effect->setOutBuffer(mOutBuffer);
            if (idx_insert == 0) {
                if (previousSize != 0) {
                    mEffects[1]->configure();
                    mEffects[1]->setInBuffer(mOutBuffer);
                    mEffects[1]->updateAccessMode();      // reconfig if neeeded.
                }
                effect->setInBuffer(mInBuffer);
            } else {
                effect->setInBuffer(mOutBuffer);
            }
        } else {
            effect->setInBuffer(mInBuffer);
            if (idx_insert == static_cast<ssize_t>(previousSize)) {
                if (idx_insert != 0) {
                    mEffects[idx_insert-1]->configure();
                    mEffects[idx_insert-1]->setOutBuffer(mInBuffer);
                    mEffects[idx_insert - 1]->updateAccessMode();      // reconfig if neeeded.
                }
                effect->setOutBuffer(mOutBuffer);
            } else {
                effect->setOutBuffer(mInBuffer);
            }
        }
        ALOGV("%s effect %p, added in chain %p at rank %zu",
                __func__, effect.get(), this, idx_insert);
    }
    effect->configure();

    return NO_ERROR;
}

std::optional<size_t> EffectChain::findVolumeControl_l(size_t from, size_t to) const {
    for (size_t i = std::min(to, mEffects.size()); i > from; i--) {
        if (mEffects[i - 1]->isVolumeControlEnabled()) {
            return i - 1;
        }
    }
    return std::nullopt;
}

ssize_t EffectChain::getInsertIndex(const effect_descriptor_t& desc) {
    // Insert effects are inserted at the end of mEffects vector as they are processed
    //  after track and auxiliary effects.
    // Insert effect order as a function of indicated preference:
    //  if EFFECT_FLAG_INSERT_EXCLUSIVE, insert in first position or reject if
    //  another effect is present
    //  else if EFFECT_FLAG_INSERT_FIRST, insert in first position or after the
    //  last effect claiming first position
    //  else if EFFECT_FLAG_INSERT_LAST, insert in last position or before the
    //  first effect claiming last position
    //  else if EFFECT_FLAG_INSERT_ANY insert after first or before last
    // Reject insertion if an effect with EFFECT_FLAG_INSERT_EXCLUSIVE is
    // already present
    // Spatializer or Downmixer effects are inserted in first position because
    // they adapt the channel count for all other effects in the chain
    if ((memcmp(&desc.type, FX_IID_SPATIALIZER, sizeof(effect_uuid_t)) == 0)
            || (memcmp(&desc.type, EFFECT_UIID_DOWNMIX, sizeof(effect_uuid_t)) == 0)) {
        return 0;
    }

    size_t size = mEffects.size();
    uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;
    ssize_t idx_insert;
    ssize_t idx_insert_first = -1;
    ssize_t idx_insert_last = -1;

    idx_insert = size;
    for (size_t i = 0; i < size; i++) {
        effect_descriptor_t d = mEffects[i]->desc();
        uint32_t iMode = d.flags & EFFECT_FLAG_TYPE_MASK;
        uint32_t iPref = d.flags & EFFECT_FLAG_INSERT_MASK;
        if (iMode == EFFECT_FLAG_TYPE_INSERT) {
            // check invalid effect chaining combinations
            if (insertPref == EFFECT_FLAG_INSERT_EXCLUSIVE ||
                iPref == EFFECT_FLAG_INSERT_EXCLUSIVE) {
                ALOGW("%s could not insert effect %s: exclusive conflict with %s",
                        __func__, desc.name, d.name);
                return -1;
            }
            // remember position of first insert effect and by default
            // select this as insert position for new effect
            if (idx_insert == static_cast<ssize_t>(size)) {
                idx_insert = i;
            }
            // remember position of last insert effect claiming
            // first position
            if (iPref == EFFECT_FLAG_INSERT_FIRST) {
                idx_insert_first = i;
            }
            // remember position of first insert effect claiming
            // last position
            if (iPref == EFFECT_FLAG_INSERT_LAST &&
                idx_insert_last == -1) {
                idx_insert_last = i;
            }
        }
    }

    // modify idx_insert from first position if needed
    if (insertPref == EFFECT_FLAG_INSERT_LAST) {
        if (idx_insert_last != -1) {
            idx_insert = idx_insert_last;
        } else {
            idx_insert = size;
        }
    } else {
        if (idx_insert_first != -1) {
            idx_insert = idx_insert_first + 1;
        }
    }
    return idx_insert;
}

// removeEffect_l() must be called with IAfThreadBase::mutex() held
size_t EffectChain::removeEffect_l(const sp<IAfEffectModule>& effect,
                                                 bool release)
{
    audio_utils::lock_guard _l(mutex());
    size_t size = mEffects.size();
    uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK;

    for (size_t i = 0; i < size; i++) {
        if (effect == mEffects[i]) {
            // calling stop here will remove pre-processing effect from the audio HAL.
            // This is safe as we hold the EffectChain mutex which guarantees that we are not in
            // the middle of a read from audio HAL
            if (mEffects[i]->state() == EffectModule::ACTIVE ||
                    mEffects[i]->state() == EffectModule::STOPPING) {
                mEffects[i]->stop();
            }
            if (release) {
                mEffects[i]->release_l();
            }

            if (type != EFFECT_FLAG_TYPE_AUXILIARY) {
                if (i == size - 1 && i != 0) {
                    mEffects[i - 1]->configure();
                    mEffects[i - 1]->setOutBuffer(mOutBuffer);
                    mEffects[i - 1]->updateAccessMode();      // reconfig if neeeded.
                }
            }
            mEffects.removeAt(i);

            // make sure the input buffer configuration for the new first effect in the chain
            // is updated if needed (can switch from HAL channel mask to mixer channel mask)
            if (type != EFFECT_FLAG_TYPE_AUXILIARY // TODO(b/284522658) breaks for aux FX, why?
                    && i == 0 && size > 1) {
                mEffects[0]->configure();
                mEffects[0]->setInBuffer(mInBuffer);
                mEffects[0]->updateAccessMode();      // reconfig if neeeded.
            }

            ALOGV("removeEffect_l() effect %p, removed from chain %p at rank %zu", effect.get(),
                    this, i);
            break;
        }
    }

    return mEffects.size();
}

// setDevices_l() must be called with IAfThreadBase::mutex() held
void EffectChain::setDevices_l(const AudioDeviceTypeAddrVector &devices)
{
    size_t size = mEffects.size();
    for (size_t i = 0; i < size; i++) {
        mEffects[i]->setDevices(devices);
    }
}

// setInputDevice_l() must be called with IAfThreadBase::mutex() held
void EffectChain::setInputDevice_l(const AudioDeviceTypeAddr &device)
{
    size_t size = mEffects.size();
    for (size_t i = 0; i < size; i++) {
        mEffects[i]->setInputDevice(device);
    }
}

// setMode_l() must be called with IAfThreadBase::mutex() held
void EffectChain::setMode_l(audio_mode_t mode)
{
    size_t size = mEffects.size();
    for (size_t i = 0; i < size; i++) {
        mEffects[i]->setMode(mode);
    }
}

// setAudioSource_l() must be called with IAfThreadBase::mutex() held
void EffectChain::setAudioSource_l(audio_source_t source)
{
    size_t size = mEffects.size();
    for (size_t i = 0; i < size; i++) {
        mEffects[i]->setAudioSource(source);
    }
}

bool EffectChain::hasVolumeControlEnabled_l() const {
    for (const auto &effect : mEffects) {
        if (effect->isVolumeControlEnabled()) return true;
    }
    return false;
}

// setVolume_l() must be called with IAfThreadBase::mutex() or EffectChain::mutex() held
bool EffectChain::setVolume_l(uint32_t *left, uint32_t *right, bool force)
{
    uint32_t newLeft = *left;
    uint32_t newRight = *right;
    const size_t size = mEffects.size();

    // first update volume controller
    const auto volumeControlIndex = findVolumeControl_l(0, size);
    const int ctrlIdx = volumeControlIndex.value_or(-1);
    const sp<IAfEffectModule> volumeControlEffect =
            volumeControlIndex.has_value() ? mEffects[ctrlIdx] : nullptr;
    const sp<IAfEffectModule> cachedVolumeControlEffect = mVolumeControlEffect.promote();

    if (!force && volumeControlEffect == cachedVolumeControlEffect &&
            *left == mLeftVolume && *right == mRightVolume) {
        if (volumeControlIndex.has_value()) {
            *left = mNewLeftVolume;
            *right = mNewRightVolume;
        }
        return volumeControlIndex.has_value();
    }

    if (volumeControlEffect != cachedVolumeControlEffect) {
        // The volume control effect is a new one. Set the old one as full volume. Set the new onw
        // as zero for safe ramping.
        if (cachedVolumeControlEffect != nullptr) {
            uint32_t leftMax = 1 << 24;
            uint32_t rightMax = 1 << 24;
            cachedVolumeControlEffect->setVolume(&leftMax, &rightMax, true /*controller*/);
        }
        if (volumeControlEffect != nullptr) {
            uint32_t leftZero = 0;
            uint32_t rightZero = 0;
            volumeControlEffect->setVolume(&leftZero, &rightZero, true /*controller*/);
        }
    }
    mLeftVolume = newLeft;
    mRightVolume = newRight;

    // second get volume update from volume controller
    if (ctrlIdx >= 0) {
        mEffects[ctrlIdx]->setVolume(&newLeft, &newRight, true);
        mNewLeftVolume = newLeft;
        mNewRightVolume = newRight;
    }
    // then indicate volume to all other effects in chain.
    // Pass altered volume to effects before volume controller
    // and requested volume to effects after controller or with volume monitor flag
    uint32_t lVol = newLeft;
    uint32_t rVol = newRight;

    for (size_t i = 0; i < size; i++) {
        if ((int)i == ctrlIdx) {
            continue;
        }
        // this also works for ctrlIdx == -1 when there is no volume controller
        if ((int)i > ctrlIdx) {
            lVol = *left;
            rVol = *right;
        }
        // Pass requested volume directly if this is volume monitor module
        if (mEffects[i]->isVolumeMonitor()) {
            mEffects[i]->setVolume(left, right, false);
        } else {
            mEffects[i]->setVolume(&lVol, &rVol, false);
        }
    }
    *left = newLeft;
    *right = newRight;

    setVolumeForOutput_l(*left, *right);

    return volumeControlIndex.has_value();
}

// resetVolume_l() must be called with IAfThreadBase::mutex() or EffectChain::mutex() held
void EffectChain::resetVolume_l()
{
    if ((mLeftVolume != UINT_MAX) && (mRightVolume != UINT_MAX)) {
        uint32_t left = mLeftVolume;
        uint32_t right = mRightVolume;
        (void)setVolume_l(&left, &right, true);
    }
}

// containsHapticGeneratingEffect_l must be called with
// IAfThreadBase::mutex() or EffectChain::mutex() held
bool EffectChain::containsHapticGeneratingEffect_l()
{
    for (size_t i = 0; i < mEffects.size(); ++i) {
        if (mEffects[i]->isHapticGenerator()) {
            return true;
        }
    }
    return false;
}

void EffectChain::setHapticIntensity_l(int id, os::HapticScale intensity)
{
    audio_utils::lock_guard _l(mutex());
    for (size_t i = 0; i < mEffects.size(); ++i) {
        mEffects[i]->setHapticIntensity(id, intensity);
    }
}

void EffectChain::syncHalEffectsState()
{
    audio_utils::lock_guard _l(mutex());
    for (size_t i = 0; i < mEffects.size(); i++) {
        if (mEffects[i]->state() == EffectModule::ACTIVE ||
                mEffects[i]->state() == EffectModule::STOPPING) {
            mEffects[i]->addEffectToHal_l();
        }
    }
}

void EffectChain::dump(int fd, const Vector<String16>& args) const
NO_THREAD_SAFETY_ANALYSIS  // conditional try lock
{
    String8 result;

    const size_t numEffects = mEffects.size();
    result.appendFormat("    %zu effects for session %d\n", numEffects, mSessionId);

    if (numEffects) {
        const bool locked = afutils::dumpTryLock(mutex());
        // failed to lock - AudioFlinger is probably deadlocked
        if (!locked) {
            result.append("\tCould not lock mutex:\n");
        }

        const std::string inBufferStr = dumpInOutBuffer(true /* isInput */, mInBuffer);
        const std::string outBufferStr = dumpInOutBuffer(false /* isInput */, mOutBuffer);
        result.appendFormat("\t%-*s%-*s   Active tracks:\n",
                (int)inBufferStr.size(), "In buffer    ",
                (int)outBufferStr.size(), "Out buffer      ");
        result.appendFormat("\t%s   %s   %d\n",
                inBufferStr.c_str(), outBufferStr.c_str(), mActiveTrackCnt);
        write(fd, result.c_str(), result.size());

        for (size_t i = 0; i < numEffects; ++i) {
            sp<IAfEffectModule> effect = mEffects[i];
            if (effect != 0) {
                effect->dump(fd, args);
            }
        }

        if (locked) {
            mutex().unlock();
        }
    } else {
        write(fd, result.c_str(), result.size());
    }
}

// must be called with IAfThreadBase::mutex() held
void EffectChain::setEffectSuspended_l(
        const effect_uuid_t *type, bool suspend)
{
    sp<SuspendedEffectDesc> desc;
    // use effect type UUID timelow as key as there is no real risk of identical
    // timeLow fields among effect type UUIDs.
    ssize_t index = mSuspendedEffects.indexOfKey(type->timeLow);
    if (suspend) {
        if (index >= 0) {
            desc = mSuspendedEffects.valueAt(index);
        } else {
            desc = new SuspendedEffectDesc();
            desc->mType = *type;
            mSuspendedEffects.add(type->timeLow, desc);
            ALOGV("setEffectSuspended_l() add entry for %08x", type->timeLow);
        }

        if (desc->mRefCount++ == 0) {
            sp<IAfEffectModule> effect = getEffectIfEnabled(type);
            if (effect != 0) {
                desc->mEffect = effect;
                effect->setSuspended(true);
                effect->setEnabled(false, false /*fromHandle*/);
            }
        }
    } else {
        if (index < 0) {
            return;
        }
        desc = mSuspendedEffects.valueAt(index);
        if (desc->mRefCount <= 0) {
            ALOGW("setEffectSuspended_l() restore refcount should not be 0 %d", desc->mRefCount);
            desc->mRefCount = 0;
            return;
        }
        if (--desc->mRefCount == 0) {
            ALOGV("setEffectSuspended_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
            if (desc->mEffect != 0) {
                sp<IAfEffectModule> effect = desc->mEffect.promote();
                if (effect != 0) {
                    effect->setSuspended(false);
                    effect->mutex().lock();
                    IAfEffectHandle *handle = effect->controlHandle_l();
                    if (handle != NULL && !handle->disconnected()) {
                        effect->setEnabled_l(handle->enabled());
                    }
                    effect->mutex().unlock();
                }
                desc->mEffect.clear();
            }
            mSuspendedEffects.removeItemsAt(index);
        }
    }
}

// must be called with IAfThreadBase::mutex() held
void EffectChain::setEffectSuspendedAll_l(bool suspend)
{
    sp<SuspendedEffectDesc> desc;

    ssize_t index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
    if (suspend) {
        if (index >= 0) {
            desc = mSuspendedEffects.valueAt(index);
        } else {
            desc = new SuspendedEffectDesc();
            mSuspendedEffects.add((int)kKeyForSuspendAll, desc);
            ALOGV("setEffectSuspendedAll_l() add entry for 0");
        }
        if (desc->mRefCount++ == 0) {
            Vector< sp<IAfEffectModule> > effects;
            getSuspendEligibleEffects(effects);
            for (size_t i = 0; i < effects.size(); i++) {
                setEffectSuspended_l(&effects[i]->desc().type, true);
            }
        }
    } else {
        if (index < 0) {
            return;
        }
        desc = mSuspendedEffects.valueAt(index);
        if (desc->mRefCount <= 0) {
            ALOGW("setEffectSuspendedAll_l() restore refcount should not be 0 %d", desc->mRefCount);
            desc->mRefCount = 1;
        }
        if (--desc->mRefCount == 0) {
            Vector<const effect_uuid_t *> types;
            for (size_t i = 0; i < mSuspendedEffects.size(); i++) {
                if (mSuspendedEffects.keyAt(i) == (int)kKeyForSuspendAll) {
                    continue;
                }
                types.add(&mSuspendedEffects.valueAt(i)->mType);
            }
            for (size_t i = 0; i < types.size(); i++) {
                setEffectSuspended_l(types[i], false);
            }
            ALOGV("setEffectSuspendedAll_l() remove entry for %08x",
                    mSuspendedEffects.keyAt(index));
            mSuspendedEffects.removeItem((int)kKeyForSuspendAll);
        }
    }
}


// The volume effect is used for automated tests only
#ifndef OPENSL_ES_H_
static const effect_uuid_t SL_IID_VOLUME_ = { 0x09e8ede0, 0xddde, 0x11db, 0xb4f6,
                                            { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
const effect_uuid_t * const SL_IID_VOLUME = &SL_IID_VOLUME_;
#endif //OPENSL_ES_H_

/* static */
bool EffectChain::isEffectEligibleForBtNrecSuspend(const effect_uuid_t *type)
{
    // Only NS and AEC are suspended when BtNRec is off
    if ((memcmp(type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) ||
        (memcmp(type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
        return true;
    }
    return false;
}

bool EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc)
{
    // auxiliary effects and visualizer are never suspended on output mix
    if ((mSessionId == AUDIO_SESSION_OUTPUT_MIX) &&
        (((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) ||
         (memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) ||
         (memcmp(&desc.type, SL_IID_VOLUME, sizeof(effect_uuid_t)) == 0) ||
         (memcmp(&desc.type, SL_IID_DYNAMICSPROCESSING, sizeof(effect_uuid_t)) == 0))) {
        return false;
    }
    return true;
}

void EffectChain::getSuspendEligibleEffects(
        Vector< sp<IAfEffectModule> > &effects)
{
    effects.clear();
    for (size_t i = 0; i < mEffects.size(); i++) {
        if (isEffectEligibleForSuspend(mEffects[i]->desc())) {
            effects.add(mEffects[i]);
        }
    }
}

sp<IAfEffectModule> EffectChain::getEffectIfEnabled(const effect_uuid_t *type)
{
    sp<IAfEffectModule> effect = getEffectFromType_l(type);
    return effect != 0 && effect->isEnabled() ? effect : 0;
}

void EffectChain::checkSuspendOnEffectEnabled(const sp<IAfEffectModule>& effect,
                                                            bool enabled)
{
    ssize_t index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
    if (enabled) {
        if (index < 0) {
            // if the effect is not suspend check if all effects are suspended
            index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
            if (index < 0) {
                return;
            }
            if (!isEffectEligibleForSuspend(effect->desc())) {
                return;
            }
            setEffectSuspended_l(&effect->desc().type, enabled);
            index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
            if (index < 0) {
                ALOGW("checkSuspendOnEffectEnabled() Fx should be suspended here!");
                return;
            }
        }
        ALOGV("checkSuspendOnEffectEnabled() enable suspending fx %08x",
            effect->desc().type.timeLow);
        sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
        // if effect is requested to suspended but was not yet enabled, suspend it now.
        if (desc->mEffect == 0) {
            desc->mEffect = effect;
            effect->setEnabled(false, false /*fromHandle*/);
            effect->setSuspended(true);
        }
    } else {
        if (index < 0) {
            return;
        }
        ALOGV("checkSuspendOnEffectEnabled() disable restoring fx %08x",
            effect->desc().type.timeLow);
        sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
        desc->mEffect.clear();
        effect->setSuspended(false);
    }
}

bool EffectChain::isNonOffloadableEnabled() const
{
    audio_utils::lock_guard _l(mutex());
    return isNonOffloadableEnabled_l();
}

bool EffectChain::isNonOffloadableEnabled_l() const
{
    size_t size = mEffects.size();
    for (size_t i = 0; i < size; i++) {
        if (mEffects[i]->isEnabled() && !mEffects[i]->isOffloadable()) {
            return true;
        }
    }
    return false;
}

void EffectChain::setThread(const sp<IAfThreadBase>& thread)
{
    audio_utils::lock_guard _l(mutex());
    mEffectCallback->setThread(thread);
}

void EffectChain::checkOutputFlagCompatibility(audio_output_flags_t *flags) const
{
    if ((*flags & AUDIO_OUTPUT_FLAG_RAW) != 0 && !isRawCompatible()) {
        *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_RAW);
    }
    if ((*flags & AUDIO_OUTPUT_FLAG_FAST) != 0 && !isFastCompatible()) {
        *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_FAST);
    }
    if ((*flags & AUDIO_OUTPUT_FLAG_BIT_PERFECT) != 0 && !isBitPerfectCompatible()) {
        *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_BIT_PERFECT);
    }
}

void EffectChain::checkInputFlagCompatibility(audio_input_flags_t *flags) const
{
    if ((*flags & AUDIO_INPUT_FLAG_RAW) != 0 && !isRawCompatible()) {
        *flags = (audio_input_flags_t)(*flags & ~AUDIO_INPUT_FLAG_RAW);
    }
    if ((*flags & AUDIO_INPUT_FLAG_FAST) != 0 && !isFastCompatible()) {
        *flags = (audio_input_flags_t)(*flags & ~AUDIO_INPUT_FLAG_FAST);
    }
}

bool EffectChain::isRawCompatible() const
{
    audio_utils::lock_guard _l(mutex());
    for (const auto &effect : mEffects) {
        if (effect->isProcessImplemented()) {
            return false;
        }
    }
    // Allow effects without processing.
    return true;
}

bool EffectChain::isFastCompatible() const
{
    audio_utils::lock_guard _l(mutex());
    for (const auto &effect : mEffects) {
        if (effect->isProcessImplemented()
                && effect->isImplementationSoftware()) {
            return false;
        }
    }
    // Allow effects without processing or hw accelerated effects.
    return true;
}

bool EffectChain::isBitPerfectCompatible() const {
    audio_utils::lock_guard _l(mutex());
    for (const auto &effect : mEffects) {
        if (effect->isProcessImplemented()
                && effect->isImplementationSoftware()) {
            return false;
        }
    }
    // Allow effects without processing or hw accelerated effects.
    return true;
}

// isCompatibleWithThread_l() must be called with thread->mutex() held
bool EffectChain::isCompatibleWithThread_l(const sp<IAfThreadBase>& thread) const
{
    audio_utils::lock_guard _l(mutex());
    for (size_t i = 0; i < mEffects.size(); i++) {
        if (thread->checkEffectCompatibility_l(&(mEffects[i]->desc()), mSessionId) != NO_ERROR) {
            return false;
        }
    }
    return true;
}

// EffectCallbackInterface implementation
status_t EffectChain::EffectCallback::createEffectHal(
        const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
        sp<EffectHalInterface> *effect) {
    status_t status = NO_INIT;
    const sp<EffectsFactoryHalInterface> effectsFactory =
            EffectConfiguration::getEffectsFactoryHal();
    if (effectsFactory != 0) {
        status = effectsFactory->createEffect(pEffectUuid, sessionId, io(), deviceId, effect);
    }
    return status;
}

bool EffectChain::EffectCallback::updateOrphanEffectChains(
        const sp<IAfEffectBase>& effect) {
    // in EffectChain context, an EffectBase is always from an EffectModule so static cast is safe
    return mAfThreadCallback->updateOrphanEffectChains(effect->asEffectModule());
}

status_t EffectChain::EffectCallback::allocateHalBuffer(
        size_t size, sp<EffectBufferHalInterface>* buffer) {
    return mAfThreadCallback->getEffectsFactoryHal()->allocateBuffer(size, buffer);
}

status_t EffectChain::EffectCallback::addEffectToHal(
        const sp<EffectHalInterface>& effect) {
    status_t result = NO_INIT;
    const sp<IAfThreadBase> t = thread().promote();
    if (t == nullptr) {
        return result;
    }
    sp <StreamHalInterface> st = t->stream();
    if (st == nullptr) {
        return result;
    }
    result = st->addEffect(effect);
    ALOGE_IF(result != OK, "Error when adding effect: %d", result);
    return result;
}

status_t EffectChain::EffectCallback::removeEffectFromHal(
        const sp<EffectHalInterface>& effect) {
    status_t result = NO_INIT;
    const sp<IAfThreadBase> t = thread().promote();
    if (t == nullptr) {
        return result;
    }
    sp <StreamHalInterface> st = t->stream();
    if (st == nullptr) {
        return result;
    }
    result = st->removeEffect(effect);
    ALOGE_IF(result != OK, "Error when removing effect: %d", result);
    return result;
}

audio_io_handle_t EffectChain::EffectCallback::io() const {
    const sp<IAfThreadBase> t = thread().promote();
    if (t == nullptr) {
        return AUDIO_IO_HANDLE_NONE;
    }
    return t->id();
}

bool EffectChain::EffectCallback::isOutput() const {
    const sp<IAfThreadBase> t = thread().promote();
    if (t == nullptr) {
        return true;
    }
    return t->isOutput();
}

bool EffectChain::EffectCallback::isOffload() const {
    return mThreadType == IAfThreadBase::OFFLOAD;
}

bool EffectChain::EffectCallback::isOffloadOrDirect() const {
    return mThreadType == IAfThreadBase::OFFLOAD
            || mThreadType == IAfThreadBase::DIRECT;
}

bool EffectChain::EffectCallback::isOffloadOrMmap() const {
    switch (mThreadType) {
    case IAfThreadBase::OFFLOAD:
    case IAfThreadBase::MMAP_PLAYBACK:
    case IAfThreadBase::MMAP_CAPTURE:
        return true;
    default:
        return false;
    }
}

bool EffectChain::EffectCallback::isSpatializer() const {
    return mThreadType == IAfThreadBase::SPATIALIZER;
}

uint32_t EffectChain::EffectCallback::sampleRate() const {
    const sp<IAfThreadBase> t = thread().promote();
    if (t == nullptr) {
        return 0;
    }
    return t->sampleRate();
}

audio_channel_mask_t EffectChain::EffectCallback::inChannelMask(int id) const {
    const sp<IAfThreadBase> t = thread().promote();
    if (t == nullptr) {
        return AUDIO_CHANNEL_NONE;
    }
    sp<IAfEffectChain> c = chain().promote();
    if (c == nullptr) {
        return AUDIO_CHANNEL_NONE;
    }

    if (mThreadType == IAfThreadBase::SPATIALIZER) {
        if (c->sessionId() == AUDIO_SESSION_OUTPUT_STAGE) {
            if (c->isFirstEffect(id)) {
                return t->mixerChannelMask();
            } else {
                return t->channelMask();
            }
        } else if (!audio_is_global_session(c->sessionId())) {
            if ((t->hasAudioSession_l(c->sessionId())
                    & IAfThreadBase::SPATIALIZED_SESSION) != 0) {
                return t->mixerChannelMask();
            } else {
                return t->channelMask();
            }
        } else {
            return t->channelMask();
        }
    } else {
        return t->channelMask();
    }
}

uint32_t EffectChain::EffectCallback::inChannelCount(int id) const {
    return audio_channel_count_from_out_mask(inChannelMask(id));
}

audio_channel_mask_t EffectChain::EffectCallback::outChannelMask() const {
    const sp<IAfThreadBase> t = thread().promote();
    if (t == nullptr) {
        return AUDIO_CHANNEL_NONE;
    }
    sp<IAfEffectChain> c = chain().promote();
    if (c == nullptr) {
        return AUDIO_CHANNEL_NONE;
    }

    if (mThreadType == IAfThreadBase::SPATIALIZER) {
        if (!audio_is_global_session(c->sessionId())) {
            if ((t->hasAudioSession_l(c->sessionId())
                    & IAfThreadBase::SPATIALIZED_SESSION) != 0) {
                return t->mixerChannelMask();
            } else {
                return t->channelMask();
            }
        } else {
            return t->channelMask();
        }
    } else {
        return t->channelMask();
    }
}

uint32_t EffectChain::EffectCallback::outChannelCount() const {
    return audio_channel_count_from_out_mask(outChannelMask());
}

audio_channel_mask_t EffectChain::EffectCallback::hapticChannelMask() const {
    const sp<IAfThreadBase> t = thread().promote();
    if (t == nullptr) {
        return AUDIO_CHANNEL_NONE;
    }
    return t->hapticChannelMask();
}

size_t EffectChain::EffectCallback::frameCount() const {
    const sp<IAfThreadBase> t = thread().promote();
    if (t == nullptr) {
        return 0;
    }
    return t->frameCount();
}

uint32_t EffectChain::EffectCallback::latency() const
NO_THREAD_SAFETY_ANALYSIS  // latency_l() access
{
    const sp<IAfThreadBase> t = thread().promote();
    if (t == nullptr) {
        return 0;
    }
    // TODO(b/275956781) - this requires the thread lock.
    return t->latency_l();
}

void EffectChain::EffectCallback::setVolumeForOutput(float left, float right) const
NO_THREAD_SAFETY_ANALYSIS  // setVolumeForOutput_l() access
{
    const sp<IAfThreadBase> t = thread().promote();
    if (t == nullptr) {
        return;
    }
    t->setVolumeForOutput_l(left, right);
}

void EffectChain::EffectCallback::checkSuspendOnEffectEnabled(
        const sp<IAfEffectBase>& effect, bool enabled, bool threadLocked) {
    const sp<IAfThreadBase> t = thread().promote();
    if (t == nullptr) {
        return;
    }
    t->checkSuspendOnEffectEnabled(enabled, effect->sessionId(), threadLocked);

    sp<IAfEffectChain> c = chain().promote();
    if (c == nullptr) {
        return;
    }
    // in EffectChain context, an EffectBase is always from an EffectModule so static cast is safe
    c->checkSuspendOnEffectEnabled(effect->asEffectModule(), enabled);
}

void EffectChain::EffectCallback::onEffectEnable(const sp<IAfEffectBase>& effect) {
    const sp<IAfThreadBase> t = thread().promote();
    if (t == nullptr) {
        return;
    }
    // in EffectChain context, an EffectBase is always from an EffectModule so static cast is safe
    t->onEffectEnable(effect->asEffectModule());
}

void EffectChain::EffectCallback::onEffectDisable(const sp<IAfEffectBase>& effect) {
    checkSuspendOnEffectEnabled(effect, false, false /*threadLocked*/);

    const sp<IAfThreadBase> t = thread().promote();
    if (t == nullptr) {
        return;
    }
    t->onEffectDisable();
}

bool EffectChain::EffectCallback::disconnectEffectHandle(IAfEffectHandle *handle,
                                                      bool unpinIfLast) {
    const sp<IAfThreadBase> t = thread().promote();
    if (t == nullptr) {
        return false;
    }
    t->disconnectEffectHandle(handle, unpinIfLast);
    return true;
}

void EffectChain::EffectCallback::resetVolume() {
    sp<IAfEffectChain> c = chain().promote();
    if (c == nullptr) {
        return;
    }
    c->resetVolume_l();

}

product_strategy_t EffectChain::EffectCallback::strategy() const {
    sp<IAfEffectChain> c = chain().promote();
    if (c == nullptr) {
        return PRODUCT_STRATEGY_NONE;
    }
    return c->strategy();
}

int32_t EffectChain::EffectCallback::activeTrackCnt() const {
    sp<IAfEffectChain> c = chain().promote();
    if (c == nullptr) {
        return 0;
    }
    return c->activeTrackCnt();
}


#undef LOG_TAG
#define LOG_TAG "DeviceEffectProxy"

/* static */
sp<IAfDeviceEffectProxy> IAfDeviceEffectProxy::create(
        const AudioDeviceTypeAddr& device,
        const sp<DeviceEffectManagerCallback>& callback,
        effect_descriptor_t *desc, int id, bool notifyFramesProcessed)
{
    return sp<DeviceEffectProxy>::make(device,
            callback,
            desc, id, notifyFramesProcessed);
}

status_t DeviceEffectProxy::setEnabled(bool enabled, bool fromHandle)
{
    status_t status = EffectBase::setEnabled(enabled, fromHandle);
    audio_utils::lock_guard _l(proxyMutex());
    if (status == NO_ERROR) {
        for (auto& handle : mEffectHandles) {
            Status bs;
            if (enabled) {
                bs = handle.second->asIEffect()->enable(&status);
            } else {
                bs = handle.second->asIEffect()->disable(&status);
            }
            if (!bs.isOk()) {
              status = statusTFromBinderStatus(bs);
            }
        }
    }
    ALOGV("%s enable %d status %d", __func__, enabled, status);
    return status;
}

status_t DeviceEffectProxy::init(
        const std::map <audio_patch_handle_t, IAfPatchPanel::Patch>& patches) {
//For all audio patches
//If src or sink device match
//If the effect is HW accelerated
//	if no corresponding effect module
//		Create EffectModule: mHalEffect
//Create and attach EffectHandle
//If the effect is not HW accelerated and the patch sink or src is a mixer port
//	Create Effect on patch input or output thread on session -1
//Add EffectHandle to EffectHandle map of Effect Proxy:
    ALOGV("%s device type %d address %s", __func__,  mDevice.mType, mDevice.getAddress());
    status_t status = NO_ERROR;
    for (auto &patch : patches) {
        status = onCreatePatch(patch.first, patch.second);
        ALOGV("%s onCreatePatch status %d", __func__, status);
        if (status == BAD_VALUE) {
            return status;
        }
    }
    return status;
}

status_t DeviceEffectProxy::onCreatePatch(
        audio_patch_handle_t patchHandle, const IAfPatchPanel::Patch& patch) {
    status_t status = NAME_NOT_FOUND;
    sp<IAfEffectHandle> handle;
    // only consider source[0] as this is the only "true" source of a patch
    status = checkPort(patch, &patch.mAudioPatch.sources[0], &handle);
    ALOGV("%s source checkPort status %d", __func__, status);
    for (uint32_t i = 0; i < patch.mAudioPatch.num_sinks && status == NAME_NOT_FOUND; i++) {
        status = checkPort(patch, &patch.mAudioPatch.sinks[i], &handle);
        ALOGV("%s sink %d checkPort status %d", __func__, i, status);
    }
    if (status == NO_ERROR || status == ALREADY_EXISTS) {
        audio_utils::lock_guard _l(proxyMutex());
        mEffectHandles.emplace(patchHandle, handle);
    }
    ALOGW_IF(status == BAD_VALUE,
            "%s cannot attach effect %s on patch %d", __func__, mDescriptor.name, patchHandle);

    return status;
}

status_t DeviceEffectProxy::checkPort(const IAfPatchPanel::Patch& patch,
        const struct audio_port_config *port, sp<IAfEffectHandle> *handle)
NO_THREAD_SAFETY_ANALYSIS
// calling function 'createEffect_l' requires holding mutex 'AudioFlinger_Mutex' exclusively
{

    ALOGV("%s type %d device type %d address %s device ID %d patch.isSoftware() %d",
            __func__, port->type, port->ext.device.type,
            port->ext.device.address, port->id, patch.isSoftware());
    if (port->type != AUDIO_PORT_TYPE_DEVICE || port->ext.device.type != mDevice.mType ||
        port->ext.device.address != mDevice.address()) {
        return NAME_NOT_FOUND;
    }
    if (((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) &&
        (audio_port_config_has_input_direction(port))) {
        ALOGI("%s don't create postprocessing effect on record port", __func__);
        return NAME_NOT_FOUND;
    }
    if (((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC) &&
        (!audio_port_config_has_input_direction(port))) {
        ALOGI("%s don't create preprocessing effect on playback port", __func__);
        return NAME_NOT_FOUND;
    }
    status_t status = NAME_NOT_FOUND;

    if (mDescriptor.flags & EFFECT_FLAG_HW_ACC_TUNNEL) {
        audio_utils::lock_guard _l(proxyMutex());
        mDevicePort = *port;
        mHalEffect = new EffectModule(mMyCallback,
                                      const_cast<effect_descriptor_t *>(&mDescriptor),
                                      mMyCallback->newEffectId(), AUDIO_SESSION_DEVICE,
                                      false /* pinned */, port->id);
        if (audio_is_input_device(mDevice.mType)) {
            mHalEffect->setInputDevice(mDevice);
        } else {
            mHalEffect->setDevices({mDevice});
        }
        mHalEffect->configure();

        *handle = new EffectHandle(mHalEffect, nullptr, nullptr, 0 /*priority*/,
                                   mNotifyFramesProcessed);
        status = (*handle)->initCheck();
        if (status == OK) {
            status = mHalEffect->addHandle((*handle).get());
        } else {
            mHalEffect.clear();
            mDevicePort.id = AUDIO_PORT_HANDLE_NONE;
        }
    } else if (patch.isSoftware() || patch.thread().promote() != nullptr) {
        sp<IAfThreadBase> thread;
        if (audio_port_config_has_input_direction(port)) {
            if (patch.isSoftware()) {
                thread = patch.mRecord.thread();
            } else {
                thread = patch.thread().promote();
            }
        } else {
            if (patch.isSoftware()) {
                thread = patch.mPlayback.thread();
            } else {
                thread = patch.thread().promote();
            }
        }
        int enabled;
        *handle = thread->createEffect_l(nullptr, nullptr, 0, AUDIO_SESSION_DEVICE,
                                         const_cast<effect_descriptor_t *>(&mDescriptor),
                                         &enabled, &status, false, false /*probe*/,
                                         mNotifyFramesProcessed);
        ALOGV("%s thread->createEffect_l status %d", __func__, status);
    } else {
        status = BAD_VALUE;
    }

    if (status == NO_ERROR || status == ALREADY_EXISTS) {
        Status bs;
        if (isEnabled()) {
            bs = (*handle)->asIEffect()->enable(&status);
        } else {
            bs = (*handle)->asIEffect()->disable(&status);
        }
        if (!bs.isOk()) {
            status = statusTFromBinderStatus(bs);
        }
    }
    return status;
}

void DeviceEffectProxy::onReleasePatch(audio_patch_handle_t patchHandle) {
    sp<IAfEffectHandle> effect;
    {
        audio_utils::lock_guard _l(proxyMutex());
        if (mEffectHandles.find(patchHandle) != mEffectHandles.end()) {
            effect = mEffectHandles.at(patchHandle);
            mEffectHandles.erase(patchHandle);
        }
    }
}


size_t DeviceEffectProxy::removeEffect(const sp<IAfEffectModule>& effect)
{
    audio_utils::lock_guard _l(proxyMutex());
    if (effect == mHalEffect) {
        mHalEffect->release_l();
        mHalEffect.clear();
        mDevicePort.id = AUDIO_PORT_HANDLE_NONE;
    }
    return mHalEffect == nullptr ? 0 : 1;
}

status_t DeviceEffectProxy::addEffectToHal(
        const sp<EffectHalInterface>& effect) {
    if (mHalEffect == nullptr) {
        return NO_INIT;
    }
    return mManagerCallback->addEffectToHal(&mDevicePort, effect);
}

status_t DeviceEffectProxy::removeEffectFromHal(
        const sp<EffectHalInterface>& effect) {
    if (mHalEffect == nullptr) {
        return NO_INIT;
    }
    return mManagerCallback->removeEffectFromHal(&mDevicePort, effect);
}

bool DeviceEffectProxy::isOutput() const {
    if (mDevicePort.id != AUDIO_PORT_HANDLE_NONE) {
        return mDevicePort.role == AUDIO_PORT_ROLE_SINK;
    }
    return true;
}

uint32_t DeviceEffectProxy::sampleRate() const {
    if (mDevicePort.id != AUDIO_PORT_HANDLE_NONE &&
            (mDevicePort.config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) != 0) {
        return mDevicePort.sample_rate;
    }
    return DEFAULT_OUTPUT_SAMPLE_RATE;
}

audio_channel_mask_t DeviceEffectProxy::channelMask() const {
    if (mDevicePort.id != AUDIO_PORT_HANDLE_NONE &&
            (mDevicePort.config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) != 0) {
        return mDevicePort.channel_mask;
    }
    return AUDIO_CHANNEL_OUT_STEREO;
}

uint32_t DeviceEffectProxy::channelCount() const {
    if (isOutput()) {
        return audio_channel_count_from_out_mask(channelMask());
    }
    return audio_channel_count_from_in_mask(channelMask());
}

void DeviceEffectProxy::dump2(int fd, int spaces) const
NO_THREAD_SAFETY_ANALYSIS  // conditional try lock
{
    const Vector<String16> args;
    EffectBase::dump(fd, args);

    const bool locked = afutils::dumpTryLock(proxyMutex());
    if (!locked) {
        String8 result("DeviceEffectProxy may be deadlocked\n");
        write(fd, result.c_str(), result.size());
    }

    String8 outStr;
    if (mHalEffect != nullptr) {
        outStr.appendFormat("%*sHAL Effect Id: %d\n", spaces, "", mHalEffect->id());
    } else {
        outStr.appendFormat("%*sNO HAL Effect\n", spaces, "");
    }
    write(fd, outStr.c_str(), outStr.size());
    outStr.clear();

    outStr.appendFormat("%*sSub Effects:\n", spaces, "");
    write(fd, outStr.c_str(), outStr.size());
    outStr.clear();

    for (const auto& iter : mEffectHandles) {
        outStr.appendFormat("%*sEffect for patch handle %d:\n", spaces + 2, "", iter.first);
        write(fd, outStr.c_str(), outStr.size());
        outStr.clear();
        sp<IAfEffectBase> effect = iter.second->effect().promote();
        if (effect != nullptr) {
            effect->dump(fd, args);
        }
    }

    if (locked) {
        proxyMutex().unlock();
    }
}

#undef LOG_TAG
#define LOG_TAG "DeviceEffectProxy::ProxyCallback"

int DeviceEffectProxy::ProxyCallback::newEffectId() {
    return mManagerCallback->newEffectId();
}


bool DeviceEffectProxy::ProxyCallback::disconnectEffectHandle(
        IAfEffectHandle *handle, bool unpinIfLast) {
    sp<IAfEffectBase> effectBase = handle->effect().promote();
    if (effectBase == nullptr) {
        return false;
    }

    sp<IAfEffectModule> effect = effectBase->asEffectModule();
    if (effect == nullptr) {
        return false;
    }

    // restore suspended effects if the disconnected handle was enabled and the last one.
    bool remove = (effect->removeHandle(handle) == 0) && (!effect->isPinned() || unpinIfLast);
    if (remove) {
        sp<DeviceEffectProxy> proxy = mProxy.promote();
        if (proxy != nullptr) {
            proxy->removeEffect(effect);
        }
        if (handle->enabled()) {
            effectBase->checkSuspendOnEffectEnabled(false, false /*threadLocked*/);
        }
    }
    return true;
}

status_t DeviceEffectProxy::ProxyCallback::createEffectHal(
        const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
        sp<EffectHalInterface> *effect) {
    return mManagerCallback->createEffectHal(pEffectUuid, sessionId, deviceId, effect);
}

status_t DeviceEffectProxy::ProxyCallback::addEffectToHal(
        const sp<EffectHalInterface>& effect) {
    sp<DeviceEffectProxy> proxy = mProxy.promote();
    if (proxy == nullptr) {
        return NO_INIT;
    }
    return proxy->addEffectToHal(effect);
}

status_t DeviceEffectProxy::ProxyCallback::removeEffectFromHal(
        const sp<EffectHalInterface>& effect) {
    sp<DeviceEffectProxy> proxy = mProxy.promote();
    if (proxy == nullptr) {
        return NO_INIT;
    }
    return proxy->removeEffectFromHal(effect);
}

bool DeviceEffectProxy::ProxyCallback::isOutput() const {
    sp<DeviceEffectProxy> proxy = mProxy.promote();
    if (proxy == nullptr) {
        return true;
    }
    return proxy->isOutput();
}

uint32_t DeviceEffectProxy::ProxyCallback::sampleRate() const {
    sp<DeviceEffectProxy> proxy = mProxy.promote();
    if (proxy == nullptr) {
        return DEFAULT_OUTPUT_SAMPLE_RATE;
    }
    return proxy->sampleRate();
}

audio_channel_mask_t DeviceEffectProxy::ProxyCallback::inChannelMask(
        int id __unused) const {
    sp<DeviceEffectProxy> proxy = mProxy.promote();
    if (proxy == nullptr) {
        return AUDIO_CHANNEL_OUT_STEREO;
    }
    return proxy->channelMask();
}

uint32_t DeviceEffectProxy::ProxyCallback::inChannelCount(int id __unused) const {
    sp<DeviceEffectProxy> proxy = mProxy.promote();
    if (proxy == nullptr) {
        return 2;
    }
    return proxy->channelCount();
}

audio_channel_mask_t DeviceEffectProxy::ProxyCallback::outChannelMask() const {
    sp<DeviceEffectProxy> proxy = mProxy.promote();
    if (proxy == nullptr) {
        return AUDIO_CHANNEL_OUT_STEREO;
    }
    return proxy->channelMask();
}

uint32_t DeviceEffectProxy::ProxyCallback::outChannelCount() const {
    sp<DeviceEffectProxy> proxy = mProxy.promote();
    if (proxy == nullptr) {
        return 2;
    }
    return proxy->channelCount();
}

void DeviceEffectProxy::ProxyCallback::onEffectEnable(
        const sp<IAfEffectBase>& effectBase) {
    sp<IAfEffectModule> effect = effectBase->asEffectModule();
    if (effect == nullptr) {
        return;
    }
    effect->start();
}

void DeviceEffectProxy::ProxyCallback::onEffectDisable(
        const sp<IAfEffectBase>& effectBase) {
    sp<IAfEffectModule> effect = effectBase->asEffectModule();
    if (effect == nullptr) {
        return;
    }
    effect->stop();
}

} // namespace android
