blob: ed57ae40b3f636864899a2462c40f0d11f14bc31 [file] [log] [blame]
/*
* 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 "Camera_PolicyManager"
#include "PolicyManager.h"
#include "iutils/Errors.h"
#include "iutils/CameraLog.h"
namespace icamera {
PolicyManager::PolicyManager(int cameraId) : mCameraId(cameraId), mIsActive(false)
{
LOG1("@%s: camera id:%d", __func__, mCameraId);
}
PolicyManager::~PolicyManager()
{
LOG1("@%s: camera id:%d", __func__, mCameraId);
releaseBundles();
}
void PolicyManager::releaseBundles()
{
LOG1("@%s: camera id:%d", __func__, mCameraId);
for (const auto& bundle : mBundles) {
delete bundle;
}
mBundles.clear();
}
void PolicyManager::setActive(bool isActive)
{
AutoMutex lock(mPolicyLock);
LOG1("@%s: camera id:%d update active mode from %d to %d",
__func__, mCameraId, mIsActive, isActive);
if (mIsActive == isActive) return; // No action is needed if the mode unchanged.
for (auto& bundle : mBundles) {
AutoMutex lock(bundle->mLock);
bundle->mWaitingCount = 0;
bundle->mIsActive = isActive;
for (auto& executorData : bundle->mExecutorData) {
executorData.second.mRunCount = 0;
}
// Wake up the executors who are waiting for other executors.
if (!bundle->mIsActive) {
bundle->mCondition.broadcast();
}
}
mIsActive = isActive;
}
int PolicyManager::addExecutorBundle(const std::vector<std::string>& executors,
const std::vector<int>& depths) {
LOG1("@%s: camera id:%d", __func__, mCameraId);
AutoMutex lock(mPolicyLock);
uint8_t size = executors.size();
CheckError(size != depths.size(),
BAD_VALUE, "The size for executor and its depth not match");
int maxDepth = 0;
std::map<std::string, ExecutorData> executorData;
for (uint8_t i = 0; i < size; i++) {
executorData[executors[i]] = ExecutorData(depths[i]);
if (depths[i] > maxDepth) {
maxDepth = depths[i];
}
LOG1("%s, bundled executor name:%s, depth:%d)", __func__, executors[i].c_str(), depths[i]);
}
ExecutorBundle* bundle = new ExecutorBundle();
bundle->mExecutorData = executorData;
bundle->mExecutorNum = size;
bundle->mMaxDepth = maxDepth;
bundle->mWaitingCount = 0;
bundle->mIsActive = true;
mBundles.push_back(bundle);
return OK;
}
int PolicyManager::wait(std::string executorName)
{
ExecutorBundle* bundle = nullptr;
{
AutoMutex lock(mPolicyLock);
// No need to wait when it's already inactive.
if (!mIsActive) return OK;
for (const auto& item : mBundles) {
if (item->mExecutorData.find(executorName) != item->mExecutorData.end()) {
bundle = item;
break;
}
}
// If the executor not in mBundles, it means it doesn't need to wait for others.
if (bundle == nullptr) return OK;
}
ConditionLock lock(bundle->mLock);
// If it's already inactive, there is no need to align the executors anymore.
if (!bundle->mIsActive) return OK;
ExecutorData& executorData = bundle->mExecutorData[executorName];
executorData.mRunCount++;
/**
* If an executor's run count plus its depth less than the max depth of all executors,
* it means the executor can run without checking other executors' status, since other
* may wait on this executor's output to reach the precondition of running together.
*/
if (executorData.mRunCount + executorData.mDepth <= bundle->mMaxDepth) {
return OK;
}
bundle->mWaitingCount++;
/**
* If waiting count less than total executor number in the bundle, it means
* we need to wait for other executors to run with them together.
*/
if (bundle->mWaitingCount < bundle->mExecutorNum) {
LOG2("%s: need wait for other executors.", executorName.c_str());
const int64_t kWaitDuration = 66000000; // 66ms
int ret = bundle->mCondition.waitRelative(lock, kWaitDuration * SLOWLY_MULTIPLIER);
CheckWarning(ret == TIMED_OUT, ret, "%s: wait executors timeout", executorName.c_str());
} else {
bundle->mWaitingCount = 0;
bundle->mCondition.broadcast();
}
return OK;
}
} // end of namespace icamera