/*
 * Copyright (C) 2017-2020 Intel Corporation.
 *
 * 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 "PSysDAG"

#include <algorithm>
#include "iutils/Utils.h"
#include "iutils/CameraLog.h"
#include "PSysDAG.h"
#ifdef TNR7_CM
#include "GPUExecutor.h"
#endif

namespace icamera {
PSysDAG::PSysDAG(int cameraId, PSysDagCallback* psysDagCB) :
    mCameraId(cameraId),
    mPSysDagCB(psysDagCB),
    mConfigMode(CAMERA_STREAM_CONFIGURATION_MODE_AUTO),
    mTuningMode(TUNING_MODE_MAX),
#ifdef USE_PG_LITE_PIPE
    mShareReferPool(nullptr),
#endif
    mDefaultMainInputPort(MAIN_PORT),
    mVideoTnrExecutor(nullptr),
    mStillTnrExecutor(nullptr),
    mRunAicAfterQbuf(false)
{
    LOG1("@%s, mCameraId:%d", __func__, mCameraId);

    mPolicyManager = new PolicyManager(mCameraId);
    mIspParamAdaptor = new IspParamAdaptor(mCameraId, PG_PARAM_PSYS_ISA);
}

PSysDAG::~PSysDAG()
{
    LOG1("@%s, mCameraId:%d", __func__, mCameraId);

    releasePipeExecutors();

    mIspParamAdaptor->deinit();
    delete mIspParamAdaptor;
    delete mPolicyManager;
}

void PSysDAG::setFrameInfo(const std::map<Port, stream_t>& inputInfo,
                           const std::map<Port, stream_t>& outputInfo) {
    mInputFrameInfo = inputInfo;
    mOutputFrameInfo = outputInfo;

    mDefaultMainInputPort = inputInfo.begin()->first;
    // Select default main input port in priority
    Port availablePorts[] = {MAIN_PORT, SECOND_PORT, THIRD_PORT, FORTH_PORT, INVALID_PORT};
    for (unsigned int i = 0; i < ARRAY_SIZE(availablePorts); i++) {
        if (mInputFrameInfo.find(availablePorts[i]) != mInputFrameInfo.end()) {
            mDefaultMainInputPort = availablePorts[i];
            break;
        }
    }
}

void PSysDAG::releasePipeExecutors()
{
    for (auto &executor : mExecutorsPool) {
        delete executor;
    }
    mExecutorsPool.clear();
    mExecutorStreamId.clear();
}

/*
 * According to the policy config to create the executors,
 * and use the graph config data to configure the executors.
 */
int PSysDAG::createPipeExecutors(bool useTnrOutBuffer)
{
    LOG1("@%s, mCameraId:%d", __func__, mCameraId);

    releasePipeExecutors();

    mOngoingPalMap.clear();

    IGraphConfigManager *GCM = IGraphConfigManager::getInstance(mCameraId);
    CheckError(!GCM, UNKNOWN_ERROR, "Failed to get GC manager in PSysDAG!");

    std::shared_ptr<IGraphConfig> gc = GCM->getGraphConfig(mConfigMode);
    CheckError(!gc, UNKNOWN_ERROR, "Failed to get GraphConfig in PSysDAG!");

    int graphId = gc->getGraphId();
    PolicyConfig* cfg = PlatformData::getExecutorPolicyConfig(graphId);
    CheckError(!cfg, UNKNOWN_ERROR, "Failed to get PolicyConfig in PSysDAG!");

#ifdef USE_PG_LITE_PIPE
    configShareReferPool(gc);
#endif

    std::vector<std::string> pgNames;
    gc->getPgNames(&pgNames);
    bool hasVideoPipe = false, hasStillPipe = false;

    for (auto &item : cfg->pipeExecutorVec) {
        int streamId = -1;
        bool pgFound = true;

        // Not support multiple streamId in one executor,
        // so need to the check the streamId of pgList.
        for (auto &pgName : item.pgList) {
            if (std::find(pgNames.begin(), pgNames.end(), pgName) == pgNames.end()) {
                pgFound = false;
                break;
            }
            int tmpId = gc->getStreamIdByPgName(pgName);
            CheckError(tmpId == -1, BAD_VALUE, "Cannot get streamId for %s", pgName.c_str());
            CheckError(((streamId != -1) && (tmpId != streamId)), BAD_VALUE,
                    "the streamId: %d for pgName(%s) is different with previous: %d",
                    tmpId, pgName.c_str(), streamId);
            streamId = tmpId;
            LOG1("%s executor:%s pg name:%s streamId: %d",
                  __func__, item.exeName.c_str(), pgName.c_str(), streamId);
        }
        if (!pgFound)
            continue;

        if (!hasVideoPipe)
            hasVideoPipe = (streamId == VIDEO_STREAM_ID);
        if (!hasStillPipe)
            hasStillPipe = (streamId == STILL_STREAM_ID);
#ifdef TNR7_CM
        PipeExecutor *executor;
        if (strstr(item.exeName.c_str(), "gputnr") != nullptr) {
            executor = new GPUExecutor(mCameraId, item, cfg->exclusivePgs, this, gc,
                                       useTnrOutBuffer);
            if (streamId == VIDEO_STREAM_ID) mVideoTnrExecutor = executor;
            else if (streamId == STILL_STREAM_ID) mStillTnrExecutor = executor;
        } else {
            executor = new PipeExecutor(mCameraId, item, cfg->exclusivePgs, this, gc);
        }
#else
        PipeExecutor *executor = new PipeExecutor(mCameraId, item, cfg->exclusivePgs, this, gc);
#endif
        executor->setIspParamAdaptor(mIspParamAdaptor);
        executor->setStreamId(streamId);
        executor->setPolicyManager(mPolicyManager);
        executor->setNotifyPolicy(item.notifyPolicy);
#ifdef USE_PG_LITE_PIPE
        executor->setShareReferPool(mShareReferPool);
#endif
        int ret = executor->initPipe();
        if (ret != OK) {
            LOGE("Failed to create pipe for executor:%s", executor->getName());
            delete executor;
            return ret;
        }

        mExecutorsPool.push_back(executor);
        mExecutorStreamId[executor] = streamId;
    }
    LOG2("%s, hasVideoPipe: %d, hasStillPipe: %d, enableBundleInSdv: %d",
         __func__, hasVideoPipe, hasStillPipe, cfg->enableBundleInSdv);

    // Only enable psys bundle with aic when has video pipe only
    if (!hasStillPipe && PlatformData::psysBundleWithAic(mCameraId)) {
        mRunAicAfterQbuf = true;
    }

    if (hasStillPipe && hasVideoPipe && !cfg->enableBundleInSdv) return OK;

    for (auto &bundle : cfg->bundledExecutorDepths) {
        bool foundExecutor = true;
        for (auto &executor : bundle.bundledExecutors) {
            std::vector<PipeExecutor*>::iterator it = std::find_if(mExecutorsPool.begin(),
                    mExecutorsPool.end(), [executor](PipeExecutor* exec) {
                        return exec->getName() == executor;
                    });
            if (it == mExecutorsPool.end()) {
                foundExecutor = false;
                break;
            }
        }

        if (foundExecutor)
            mPolicyManager->addExecutorBundle(bundle.bundledExecutors, bundle.depths);
    }

    return OK;
}

bool PSysDAG::fetchTnrOutBuffer(int64_t seq, std::shared_ptr<CameraBuffer> buf)
{
    return mVideoTnrExecutor != nullptr ? mVideoTnrExecutor->fetchTnrOutBuffer(seq, buf) : false;
}

bool PSysDAG::isBypassStillTnr(int64_t seq)
{
    return mStillTnrExecutor != nullptr ? mStillTnrExecutor->isBypassStillTnr(seq) : true;
}

int PSysDAG::linkAndConfigExecutors()
{
    for (auto& consumer : mExecutorsPool) {
        std::map<ia_uid, Port> input;

        if (consumer->isInputEdge()) {
            // Use its own input info due to no executor as producer
            consumer->getInputTerminalPorts(input);
        } else {
            PipeExecutor* producer = findExecutorProducer(consumer);
            CheckError(producer == nullptr, BAD_VALUE, "no producer for executor %s!", consumer->getName());
            producer->getOutputTerminalPorts(input);

            consumer->setBufferProducer(producer);
            LOG1("%s: link consumer %s to %s", __func__, consumer->getName(), producer->getName());
        }

        // Link producer (output) to consumer (input) by terminal
        consumer->setInputTerminals(input);

        std::vector<ConfigMode> configModes;
        configModes.push_back(mConfigMode);
        consumer->configure(configModes);
    }

    return OK;
}

PipeExecutor* PSysDAG::findExecutorProducer(PipeExecutor* consumer)
{
    std::map<ia_uid, Port> inputTerminals;
    consumer->getInputTerminalPorts(inputTerminals);

    for (auto& executor : mExecutorsPool) {
        if (executor == consumer) {
            continue;
        }

        for (auto& inputTerminal : inputTerminals) {
            // Return if one is matched, because only one producer is supported now.
            if (executor->hasOutputTerminal(inputTerminal.first)) {
                return executor;
            }
        }
    }

    return nullptr;
}

/*
 * Search all the stream Ids in one pipe which provides frame buffer to the output port
 * mOutputPortToStreamIds: store all the different stream Ids to output port mapping table
 */
status_t PSysDAG::searchStreamIdsForOutputPort(PipeExecutor *executor, Port port) {
    LOG2("@%s, mCameraId:%d", __func__, mCameraId);

    CheckError(!executor || !executor->isOutputEdge(), BAD_VALUE,
               "%s, the executor is nullptr or is not output edge", __func__);

    if (mOutputPortToStreamIds.find(port) != mOutputPortToStreamIds.end()) {
        return OK;
    }

    std::vector<int32_t> streamIds;
    PipeExecutor *tmpExecutor = executor;
    // Loop to find the producer executor's stream id
    do {
        int32_t streamId = mExecutorStreamId[tmpExecutor];
        if (std::find(streamIds.begin(), streamIds.end(), streamId) == streamIds.end()) {
            streamIds.push_back(streamId);
            LOG2("%s, store the streamId: %d for output port: %d", __func__, streamId, port);
        }

        tmpExecutor = findExecutorProducer(tmpExecutor);
    } while (tmpExecutor);

    mOutputPortToStreamIds[port] = streamIds;

    return OK;
}

/**
 * Bind the port between DAG and its edge executors.
 * After the binding we'll know where the task buffer should be queued to.
 */
int PSysDAG::bindExternalPortsToExecutor()
{
    LOG1("@%s, mCameraId:%d", __func__, mCameraId);

    mInputMaps.clear();
    mOutputMaps.clear();
    mOutputPortToStreamIds.clear();

    std::map<Port, stream_t> outputInfo;
    std::map<Port, stream_t> inputInfo;

    // Bind the input ports first.
    LOG2("%s, start to bind the input port", __func__);
    for (auto& executor : mExecutorsPool) {
        if (!executor->isInputEdge()) {
            continue;
        }
        executor->getFrameInfo(inputInfo, outputInfo);

        for (auto& frameInfo : mInputFrameInfo) {
            for (auto& portInfo : inputInfo) {
                // Check if it has been cleared (bound already).
                if (!portInfo.second.format) {
                    continue;
                }
                if (executor->isSameStreamConfig(portInfo.second, frameInfo.second, mConfigMode, false)) {
                    PortMapping portMap;
                    portMap.mExecutor = executor;
                    portMap.mDagPort = frameInfo.first;
                    portMap.mExecutorPort = portInfo.first;
                    mInputMaps.push_back(portMap);
                    // Clear the stream of executor to avoid binding it again.
                    CLEAR(portInfo.second);
                    LOG2("%s, inputMap executor %p, dagPort %d, execPort %d", __func__,
                        executor, frameInfo.first, portInfo.first);
                    break;
                }
            }
        }
    }

    // Then bind the output ports.
    LOG2("%s, start to bind the output port", __func__);
    for (auto& executor : mExecutorsPool) {
        if (!executor->isOutputEdge()) {
            continue;
        }

        executor->getFrameInfo(inputInfo, outputInfo);
        for (auto& frameInfo : mOutputFrameInfo) {
            for (auto& portInfo : outputInfo) {
                // Check if it has been cleared (bound already).
                if (!portInfo.second.format) {
                    continue;
                }
                if (executor->isSameStreamConfig(portInfo.second, frameInfo.second, mConfigMode, true)) {
                    PortMapping portMap;
                    portMap.mExecutor = executor;
                    portMap.mDagPort = frameInfo.first;
                    portMap.mExecutorPort = portInfo.first;
                    mOutputMaps.push_back(portMap);
                    searchStreamIdsForOutputPort(executor, frameInfo.first);
                    // Clear the stream of executor to avoid binding it again.
                    CLEAR(portInfo.second);
                    break;
                }
            }
        }
    }

    // Each required port must be mapped to one of (edge) executor's port.
    // One input port may be mapped to more of (edge) executor's ports.
    CheckError(mInputMaps.size() < mInputFrameInfo.size(), BAD_VALUE, "Failed to bind input ports");
    CheckError(mOutputMaps.size() != mOutputFrameInfo.size(), BAD_VALUE, "Failed to bind output ports");

    return OK;
}

int PSysDAG::registerUserOutputBufs(Port port, const std::shared_ptr<CameraBuffer> &camBuffer)
{
    for (auto& outputMap : mOutputMaps) {
        if (port == outputMap.mDagPort) {
            outputMap.mExecutor->registerOutBuffers(outputMap.mExecutorPort, camBuffer);
            break;
        }
    }

    return OK;
}

int PSysDAG::registerInternalBufs(std::map<Port, CameraBufVector> &internalBufs)
{
    for (auto& portToBuffers : internalBufs) {
        for (auto& inputMap : mInputMaps) {
            if (inputMap.mDagPort == portToBuffers.first) {
                for (auto& inputBuf : portToBuffers.second) {
                    inputMap.mExecutor->registerInBuffers(inputMap.mExecutorPort, inputBuf);
                }
                break;
            }
        }
    }

    return OK;
}

/**
 * Queue the buffers in PSysTaskData to the cooresponding executors.
 */
int PSysDAG::queueBuffers(const PSysTaskData& task)
{
    LOG2("@%s, mCameraId:%d", __func__, mCameraId);

    // Provide the input buffers for the input edge executor.
    for (auto& inputFrame : task.mInputBuffers) {
        for (auto& inputMap : mInputMaps) {
            if (inputMap.mDagPort == inputFrame.first) {
                inputMap.mExecutor->onFrameAvailable(inputMap.mExecutorPort, inputFrame.second);
                LOG2("%s, queue input buffer: dagPort: %d, executorPort: %d, name: %s", __func__,
                     inputMap.mDagPort, inputMap.mExecutorPort, inputMap.mExecutor->getName());
            }
        }
    }

    // Provide the output buffers for the output edge executor.
    for (auto& outputFrame : task.mOutputBuffers) {
        for (auto& outputMap : mOutputMaps) {
            if (outputMap.mDagPort == outputFrame.first) {
                outputMap.mExecutor->qbuf(outputMap.mExecutorPort, outputFrame.second);
                LOG2("%s, queue output buffer, dagPort: %d, executorPort: %d, name: %s", __func__,
                     outputMap.mDagPort, outputMap.mExecutorPort, outputMap.mExecutor->getName());
                if (outputFrame.second) {
                    LOG2("outputFrame.second %p, outputFrame.first %d", outputFrame.second.get(),
                          outputFrame.first);
                }
                break;
            }
        }
    }

    return OK;
}

#ifdef USE_PG_LITE_PIPE
void PSysDAG::configShareReferPool(std::shared_ptr<IGraphConfig> gc) {
    PolicyConfig* cfg = PlatformData::getExecutorPolicyConfig(gc->getGraphId());
    if (!cfg || cfg->shareReferPairList.empty()) {
        return;
    }

    CheckWarning(cfg->shareReferPairList.size() % 2 != 0, VOID_VALUE,
                 "bad share refer pair count");

    if (!mShareReferPool.get())
        mShareReferPool = std::make_shared<ShareReferBufferPool>(mCameraId);

    for (size_t i = 0; i < cfg->shareReferPairList.size(); i += 2) {
        ShareReferIdDesc& pDesc = cfg->shareReferPairList[i];
        int32_t pStream = gc->getStreamIdByPgName(pDesc.first);
        int32_t pPgId = gc->getPgIdByPgName(pDesc.first);
        int32_t pPort = pDesc.second;
        ShareReferIdDesc& cDesc = cfg->shareReferPairList[i + 1];
        int32_t cStream = gc->getStreamIdByPgName(cDesc.first);
        int32_t cPgId = gc->getPgIdByPgName(cDesc.first);
        int32_t cPort = cDesc.second;
        // Check producer only because sometimes there is no consumer (such as still pipe)
        if (pPgId > 0) {
           int64_t pReferId = ShareReferBufferPool::constructReferId(pStream, pPgId, pPort);
           int64_t cReferId = ShareReferBufferPool::constructReferId(cStream, cPgId, cPort);
           mShareReferPool->setReferPair(pDesc.first, pReferId, cDesc.first, cReferId);
        }
    }
}
#endif

int PSysDAG::configure(ConfigMode configMode, TuningMode tuningMode, bool useTnrOutBuffer)
{
    LOG1("@%s, mCameraId:%d", __func__, mCameraId);

    mConfigMode = configMode;
    mTuningMode = tuningMode;
    mRunAicAfterQbuf = false;

    // Configure IspParamAdaptor
    int ret = mIspParamAdaptor->init();
    CheckError(ret != OK, ret, "Init isp Adaptor failed, tuningMode %d", mTuningMode);

    ret = mIspParamAdaptor->configure(mInputFrameInfo[mDefaultMainInputPort], mConfigMode, mTuningMode);
    CheckError(ret != OK, ret, "Configure isp Adaptor failed, tuningMode %d", mTuningMode);

    ret = createPipeExecutors(useTnrOutBuffer);
    CheckError(ret != OK, ret, "@%s, create psys executors failed", __func__);

    ret = linkAndConfigExecutors();
    CheckError(ret != OK, ret, "Link executors failed");

    ret = bindExternalPortsToExecutor();
    CheckError(ret != OK, ret, "Bind ports failed");

    return OK;
}

int PSysDAG::start()
{
    LOG1("@%s, mCameraId:%d", __func__, mCameraId);

    mPolicyManager->setActive(true);

    for (auto& executors : mExecutorsPool) {
        executors->start();
    }
    return OK;
}

int PSysDAG::stop()
{
    LOG1("@%s, mCameraId:%d", __func__, mCameraId);

    mPolicyManager->setActive(false);

    for (auto& executors : mExecutorsPool) {
        executors->notifyStop();
    }

    for (auto& executors : mExecutorsPool) {
        executors->stop();
    }
    return OK;
}

int PSysDAG::resume()
{
    mPolicyManager->setActive(true);
    return OK;
}

int PSysDAG::pause()
{
    mPolicyManager->setActive(false);
    return OK;
}

void PSysDAG::addTask(PSysTaskData taskParam)
{
    LOG2("@%s, mCameraId:%d", __func__, mCameraId);

    if (taskParam.mTuningMode != mTuningMode) {
        tuningReconfig(taskParam.mTuningMode);
    }

    TaskInfo task = {};
    {
        // Save the task data into mOngoingTasks
        task.mTaskData = taskParam;
        // Count how many valid output buffers need to be returned.
        for (auto& outBuf : taskParam.mOutputBuffers) {
            if (outBuf.second) {
                task.mNumOfValidBuffers++;
            }
        }
        LOG2("%s:Id:%d push task with %d output buffers, sequence: %ld",
                __func__, mCameraId, task.mNumOfValidBuffers,
                taskParam.mInputBuffers.at(mDefaultMainInputPort)->getSequence());
        AutoMutex taskLock(mTaskLock);
        mOngoingTasks.push_back(task);
    }

    // It's too early to runIspAdapt here, and the ipu parameters
    // may be incorrect when runPipe.
    bool runIspAdaptor = true;

    long sequence = taskParam.mInputBuffers.at(mDefaultMainInputPort)->getSequence();
    if (runIspAdaptor) {
        LOG2("%s, run AIC before execute psys for sequence: %ld", __func__, sequence);
        prepareIpuParams(sequence, false, &task);
    }

    queueBuffers(taskParam);

    if (runIspAdaptor && mRunAicAfterQbuf) {
        LOG2("%s, run AIC bundle with execute psys for sequence: %ld", __func__, sequence + 1);
        // if running psys bundle with aic, current aic result is for next sequence
        prepareIpuParams((sequence + 1), false, &task);
    }
}

int PSysDAG::getParameters(Parameters& param)
{
    return mIspParamAdaptor->getParameters(param);
}

TuningMode PSysDAG::getTuningMode(long sequence)
{
    AutoMutex taskLock(mTaskLock);

    TuningMode taskTuningMode = mTuningMode;
    bool taskTuningModeFound = false;

    for (auto const& task : mOngoingTasks) {
        if (sequence == task.mTaskData.mInputBuffers.at(mDefaultMainInputPort)->getSequence()) {
            taskTuningMode = task.mTaskData.mTuningMode;
            taskTuningModeFound = true;
            break;
        }
    }

    if (!taskTuningModeFound) {
        LOGW("No task tuning mode found for sequence:%ld, use current DAG tuning mode.", sequence);
    }

    return taskTuningMode;
}

/**
 * Use to handle the frame done event from the executors.
 *
 * This is for returning output buffers to PSysDAG. And it'll check if all the valid
 * output buffer returned, if so, then it'll return the whole corresponding task data to
 * PSysProcessor.
 */
int PSysDAG::onFrameDone(Port port, const std::shared_ptr<CameraBuffer>& buffer)
{
    LOG2("@%s, mCameraId:%d buffer=%p", __func__, mCameraId, buffer.get());

    if (!buffer) return OK; // No need to handle if the buffer is nullptr.

    long sequence = buffer->getSequence();
    bool needReturn = false;
    Port outputPort = INVALID_PORT;
    bool fakeTask = false;
    PSysTaskData result;
    {
        AutoMutex taskLock(mTaskLock);
        for (auto it = mOngoingTasks.begin(); it != mOngoingTasks.end(); it++) {
            // Check if the returned buffer belong to the task.
            if (sequence != it->mTaskData.mInputBuffers.at(mDefaultMainInputPort)->getSequence()) {
                continue;
            }

            // Check if buffer belongs to the task because input buffer maybe reused
            for (auto& buf : it->mTaskData.mOutputBuffers) {
                if (buf.second && (buffer->getUserBuffer() == buf.second->getUserBuffer())) {
                    outputPort = buf.first;
                }
            }
            if (outputPort == INVALID_PORT) continue;

            fakeTask = it->mTaskData.mFakeTask;
            it->mNumOfReturnedBuffers++;
            if (it->mNumOfReturnedBuffers >= it->mNumOfValidBuffers) {
                result = it->mTaskData;
                needReturn = true;
                LOG2("%s:Id:%d finish task with %d returned output buffers, sequence: %ld",
                     __func__, mCameraId, it->mNumOfReturnedBuffers, sequence);
                // Remove the task data from mOngoingTasks since it's already processed.
                mOngoingTasks.erase(it);

                // Remove the sequence when finish to process the task
                AutoMutex l(mOngoingPalMapLock);
                mOngoingPalMap.erase(sequence);
            }
            // No need check other if other tasks are matched with the returned buffer since
            // we already found one.
            break;
        }
    }

    // Don't handle buffer done if it is a fake task
    if (!fakeTask) {
        CheckError(outputPort == INVALID_PORT, INVALID_OPERATION, "outputPort is invalid");
        // Return buffer
        mPSysDagCB->onBufferDone(sequence, outputPort, buffer);
    }

    if (needReturn) {
        returnBuffers(result);
    }

    return OK;
}

int PSysDAG::prepareIpuParams(long sequence, bool forceUpdate, TaskInfo *task)
{
    TRACE_LOG_PROCESS("PSysDAG", __func__, MAKE_COLOR(sequence), sequence);
    if (task == nullptr) {
        AutoMutex taskLock(mTaskLock);
        for (size_t i = 0; i < mOngoingTasks.size(); i++) {
            if (sequence ==
                mOngoingTasks[i].mTaskData.mInputBuffers.at(mDefaultMainInputPort)->getSequence()) {
                task = &mOngoingTasks[i];
                break;
            }
        }
    }
    CheckError(!task, UNKNOWN_ERROR,
               "%s, Failed to find the task for sequence: %ld", __func__, sequence);

    // According to the output port to filter the valid executor stream Ids, and then run AIC
    std::vector<int32_t> activeStreamIds;
    for (auto& outputFrame : task->mTaskData.mOutputBuffers) {
        if (outputFrame.second.get() == nullptr)
            continue;

        std::map<Port, std::vector<int32_t> >::iterator
            it = mOutputPortToStreamIds.find(outputFrame.first);
        CheckError(it == mOutputPortToStreamIds.end(), UNKNOWN_ERROR,
                   "%s, failed to find streamIds for output port: %d",
                   __func__, outputFrame.first);

        for (auto& streamId : it->second) {
            if (std::find(activeStreamIds.begin(), activeStreamIds.end(), streamId)
                    == activeStreamIds.end()) {
                activeStreamIds.push_back(streamId);
            }
        }
    }
    LOG2("%s, the active streamId size for aic(sequence: %ld) is %zu",
         __func__, sequence, activeStreamIds.size());

    int ret = OK;
    for (auto& id : activeStreamIds) {
        // Make sure the AIC is executed once.
        if (!forceUpdate) {
            AutoMutex l(mOngoingPalMapLock);

            if (mOngoingPalMap.find(sequence) != mOngoingPalMap.end()) {
                // Check if stream id is available.
                if (mOngoingPalMap[sequence].find(id) != mOngoingPalMap[sequence].end()) {
                    // This means aic for the sequence has been executed.
                    continue;
                }
            }
        }

        ret = mIspParamAdaptor->runIspAdapt(&task->mTaskData.mIspSettings, sequence, id);
        CheckError(ret != OK, UNKNOWN_ERROR,
                   "%s, Failed to run AIC: sequence: %ld streamId: %d", __func__, sequence, id);

        // Store the new sequence.
        AutoMutex l(mOngoingPalMapLock);
        mOngoingPalMap[sequence].insert(id);
    }

    return OK;
}

int PSysDAG::returnBuffers(PSysTaskData& result)
{
    LOG2("@%s, mCameraId:%d", __func__, mCameraId);

    CheckError(!mPSysDagCB, INVALID_OPERATION, "Invalid PSysProcessor");

    mPSysDagCB->onFrameDone(result);
    return OK;
}

void PSysDAG::registerListener(EventType eventType, EventListener* eventListener)
{
    //Pass through event registration to PipeExecutor
    for (auto const& executor : mExecutorsPool) {
        executor->registerListener(eventType, eventListener);
    }
}

void PSysDAG::removeListener(EventType eventType, EventListener* eventListener)
{
    //Pass through event unregistration to PipeExecutor
    for (auto const& executor : mExecutorsPool) {
        executor->removeListener(eventType, eventListener);
    }
}

void PSysDAG::tuningReconfig(TuningMode newTuningMode)
{
    LOG1("@%s ", __func__);

    if (mIspParamAdaptor) {
        mIspParamAdaptor->deinit();
    } else {
        mIspParamAdaptor = new IspParamAdaptor(mCameraId, PG_PARAM_PSYS_ISA);
    }

    int ret = mIspParamAdaptor->init();
    CheckError(ret != OK, VOID_VALUE, "Init isp Adaptor failed, tuningMode %d", newTuningMode);

    ret = mIspParamAdaptor->configure(mInputFrameInfo[mDefaultMainInputPort], mConfigMode, newTuningMode);
    CheckError(ret != OK, VOID_VALUE, "Failed to reconfig isp Adaptor.");

    mTuningMode = newTuningMode;
}

void PSysDAG::dumpExternalPortMap()
{
    for (auto& inputMap : mInputMaps) {
        if (inputMap.mExecutor) {
            LOG2("@%s: Input port %d, executor: %s:%d", __func__, inputMap.mDagPort,
                 inputMap.mExecutor->getName(), inputMap.mExecutorPort);
        } else {
            LOGE("%s: no executro for input port %d!", __func__, inputMap.mDagPort);
        }
    }
    for (auto& outputMap : mOutputMaps) {
        if (outputMap.mExecutor) {
            LOG2("@%s: Output port %d, executor: %s:%d", __func__, outputMap.mDagPort,
                 outputMap.mExecutor->getName(), outputMap.mExecutorPort);
        } else {
            LOGE("%s: no executro for output port %d!", __func__, outputMap.mDagPort);
        }
    }
}

}
