/* * Copyright (c) 2022 Huawei Device Co., Ltd. * 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. */ #include <set> #include "work_queue.h" #include "work_condition.h" #include "work_sched_hilog.h" #include "work_sched_errors.h" #include "work_scheduler_service.h" using namespace std; namespace OHOS { namespace WorkScheduler { vector<shared_ptr<WorkStatus>> WorkQueue::OnConditionChanged(WorkCondition::Type type, shared_ptr<DetectorValue> conditionVal) { shared_ptr<Condition> value = ParseCondition(type, conditionVal); vector<shared_ptr<WorkStatus>> result; std::set<int32_t> uidList; std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_); workList_.sort(WorkComp()); for (auto it : workList_) { if (it->OnConditionChanged(type, value) == E_GROUP_CHANGE_NOT_MATCH_HAP) { continue; } if (uidList.count(it->uid_) > 0 && it->GetMinInterval() != 0 && !DelayedSingleton<WorkSchedulerService>::GetInstance()->CheckEffiResApplyInfo(it->uid_)) { WS_HILOGI("One uid can start only one work, uid:%{public}d, bundleName:%{public}s", it->uid_, it->bundleName_.c_str()); continue; } if (it->IsReady()) { result.emplace_back(it); uidList.insert(it->uid_); } else { if (it->IsReadyStatus()) { it->MarkStatus(WorkStatus::Status::WAIT_CONDITION); } } if (it->needRetrigger_) { result.emplace_back(it); } } return result; } shared_ptr<Condition> WorkQueue::ParseCondition(WorkCondition::Type type, shared_ptr<DetectorValue> conditionVal) { shared_ptr<Condition> value = make_shared<Condition>(); switch (type) { case WorkCondition::Type::NETWORK: // fall-through case WorkCondition::Type::BATTERY_STATUS: // fall-through case WorkCondition::Type::STORAGE: { value->enumVal = conditionVal->intVal; break; } case WorkCondition::Type::CHARGER: { value->enumVal = conditionVal->intVal; value->boolVal = conditionVal->boolVal; break; } case WorkCondition::Type::BATTERY_LEVEL: { value->intVal = conditionVal->intVal; break; } case WorkCondition::Type::TIMER: { break; } case WorkCondition::Type::GROUP: { value->enumVal = conditionVal->intVal; value->intVal = conditionVal->timeVal; value->boolVal = conditionVal->boolVal; value->strVal = conditionVal->strVal; break; } case WorkCondition::Type::DEEP_IDLE: case WorkCondition::Type::STANDBY: { value->boolVal = conditionVal->boolVal; break; } default: {} } return value; } void WorkQueue::Push(shared_ptr<vector<shared_ptr<WorkStatus>>> workStatusVector) { for (auto it : *workStatusVector) { Push(it); } std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_); workList_.sort(WorkComp()); } void WorkQueue::Push(shared_ptr<WorkStatus> workStatus) { std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_); if (this->Contains(make_shared<string>(workStatus->workId_))) { for (auto it : workList_) { if (it->workId_.compare(workStatus->workId_) == 0) { return; } } return; } workList_.push_back(workStatus); } bool WorkQueue::Remove(shared_ptr<WorkStatus> workStatus) { std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_); auto iter = std::find(workList_.cbegin(), workList_.cend(), workStatus); if (iter != workList_.end()) { workList_.remove(*iter); } return true; } uint32_t WorkQueue::GetSize() { std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_); return workList_.size(); } bool WorkQueue::Contains(std::shared_ptr<std::string> workId) { std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_); auto iter = std::find_if(workList_.cbegin(), workList_.cend(), [&workId] (const shared_ptr<WorkStatus> &workStatus) { return workId->compare(workStatus->workId_) == 0; }); if (iter != workList_.end()) { return true; } return false; } shared_ptr<WorkStatus> WorkQueue::Find(string workId) { std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_); auto iter = std::find_if(workList_.cbegin(), workList_.cend(), [&workId](const shared_ptr<WorkStatus> &workStatus) { return workStatus->workId_ == workId; }); if (iter != workList_.end()) { return *iter; } return nullptr; } bool WorkQueue::Find(const int32_t userId, const std::string &bundleName) { std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_); auto iter = std::find_if(workList_.cbegin(), workList_.cend(), [userId, &bundleName](const shared_ptr<WorkStatus> &workStatus) { return workStatus->userId_ == userId && workStatus->bundleName_ == bundleName; }); return iter != workList_.end(); } shared_ptr<WorkStatus> WorkQueue::GetWorkToRunByPriority() { std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_); workList_.sort(WorkComp()); auto work = workList_.begin(); shared_ptr<WorkStatus> workStatus = nullptr; while (work != workList_.end()) { if ((*work)->GetStatus() == WorkStatus::CONDITION_READY) { workStatus = *work; workStatus->priority_++; break; } work++; } return workStatus; } bool WorkQueue::CancelWork(shared_ptr<WorkStatus> workStatus) { std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_); workList_.remove(workStatus); return true; } list<shared_ptr<WorkStatus>> WorkQueue::GetWorkList() { std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_); return workList_; } void WorkQueue::RemoveUnReady() { std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_); workList_.remove_if([](shared_ptr<WorkStatus> value) { return (value->GetStatus() != WorkStatus::Status::CONDITION_READY); }); } int32_t WorkQueue::GetRunningCount() { int32_t count = 0; std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_); for (shared_ptr<WorkStatus> work : workList_) { if (work->IsRunning()) { count++; } } return count; } std::list<std::shared_ptr<WorkInfo>> WorkQueue::GetRunningWorks() { std::list<std::shared_ptr<WorkInfo>> workInfo; std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_); for (shared_ptr<WorkStatus> work : workList_) { if (work->IsRunning()) { auto info = std::make_shared<WorkInfo>(); info->SetElement(work->bundleName_, work->abilityName_); info->RefreshUid(work->uid_); workInfo.emplace_back(info); } } return workInfo; } std::list<std::shared_ptr<WorkStatus>> WorkQueue::GetDeepIdleWorks() { std::list<std::shared_ptr<WorkStatus>> works; std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_); for (shared_ptr<WorkStatus> work : workList_) { if (work->IsRunning() && work->workInfo_->GetDeepIdle() == WorkCondition::DeepIdle::DEEP_IDLE_IN) { works.emplace_back(work); } } return works; } void WorkQueue::GetWorkIdStr(string& result) { std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_); for (auto it : workList_) { result.append(it->workId_ + ", "); } } void WorkQueue::Dump(string& result) { std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_); for (auto it : workList_) { it->Dump(result); } } void WorkQueue::ClearAll() { std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_); workList_.clear(); } bool WorkComp::operator () (const shared_ptr<WorkStatus> w1, const shared_ptr<WorkStatus> w2) { return w1->priority_ < w2->priority_; } void WorkQueue::SetMinIntervalByDump(int64_t interval) { std::lock_guard<ffrt::recursive_mutex> lock(workListMutex_); for (auto it : workList_) { it->SetMinIntervalByDump(interval); } } } // namespace WorkScheduler } // namespace OHOS