| /* |
| * 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 |
| |