/* * 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 "work_scheduler_service.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "parameters.h" #include "accesstoken_kit.h" #include "bundle_mgr_proxy.h" #ifdef DEVICE_USAGE_STATISTICS_ENABLE #include "bundle_active_client.h" #endif #ifdef DEVICE_STANDBY_ENABLE #include "standby_service_client.h" #include "allow_type.h" #endif #include "conditions/battery_level_listener.h" #include "conditions/battery_status_listener.h" #include "conditions/charger_listener.h" #include "conditions/network_listener.h" #include "conditions/storage_listener.h" #include "conditions/timer_listener.h" #include "conditions/group_listener.h" #include "event_publisher.h" #include "json/json.h" #include "policy/app_data_clear_listener.h" #include "policy/memory_policy.h" #include "policy/thermal_policy.h" #ifdef RESOURCESCHEDULE_BGTASKMGR_ENABLE #include "scheduler_bg_task_subscriber.h" #include "background_task_mgr_helper.h" #include "resource_type.h" #endif #include "work_scheduler_connection.h" #include "work_bundle_group_change_callback.h" #include "work_sched_errors.h" #include "work_sched_hilog.h" #include "work_sched_utils.h" using namespace std; using namespace OHOS::AppExecFwk; namespace OHOS { namespace WorkScheduler { namespace { const std::string WORKSCHEDULER_SERVICE_NAME = "WorkSchedulerService"; auto instance = DelayedSingleton::GetInstance(); auto wss = instance.get(); const bool G_REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(wss); const int32_t INIT_DELAY = 2 * 1000; const int32_t MAX_BUFFER = 2048; const int32_t DUMP_OPTION = 0; const int32_t DUMP_PARAM_INDEX = 1; const int32_t DUMP_VALUE_INDEX = 2; const char* g_persistedFilePath = "/data/service/el1/public/WorkScheduler/persisted_work"; const char* g_persistedPath = "/data/service/el1/public/WorkScheduler"; #ifdef DEVICE_USAGE_STATISTICS_ENABLE static int g_hasGroupObserver = -1; #endif const static std::string STRATEGY_NAME = "WORK_SCHEDULER"; } WorkSchedulerService::WorkSchedulerService() : SystemAbility(WORK_SCHEDULE_SERVICE_ID, true) {} WorkSchedulerService::~WorkSchedulerService() {} void WorkSchedulerService::OnStart() { if (ready_) { WS_HILOGI("OnStart is ready, nothing to do."); return; } // Init handler. if (!eventRunner_) { eventRunner_ = AppExecFwk::EventRunner::Create(WORKSCHEDULER_SERVICE_NAME); } if (eventRunner_ == nullptr) { WS_HILOGE("Init failed due to create EventRunner"); return; } handler_ = std::make_shared(eventRunner_, instance); // Try to init. Init(eventRunner_); #ifdef DEVICE_USAGE_STATISTICS_ENABLE AddSystemAbilityListener(DEVICE_USAGE_STATISTICS_SYS_ABILITY_ID); #endif #ifdef DEVICE_STANDBY_ENABLE AddSystemAbilityListener(DEVICE_STANDBY_SERVICE_SYSTEM_ABILITY_ID); #endif WS_HILOGD("On start success."); } bool WorkSchedulerService::IsBaseAbilityReady() { sptr systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); if (systemAbilityManager == nullptr || systemAbilityManager->CheckSystemAbility(APP_MGR_SERVICE_ID) == nullptr || systemAbilityManager->CheckSystemAbility(COMMON_EVENT_SERVICE_ID) == nullptr || systemAbilityManager->CheckSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID) == nullptr || systemAbilityManager->CheckSystemAbility(BACKGROUND_TASK_MANAGER_SERVICE_ID) == nullptr) { return false; } return true; } void WorkSchedulerService::InitPersisted() { WS_HILOGD("init persisted work"); list> persistedWorks = ReadPersistedWorks(); for (auto it : persistedWorks) { WS_HILOGI("get persisted work, id: %{public}d", it->GetWorkId()); InitPersistedWork(*it); } } list> WorkSchedulerService::ReadPersistedWorks() { list> workInfos; ifstream fin; std::string realPath; if (!WorkSchedUtils::ConvertFullPath(g_persistedFilePath, realPath)) { WS_HILOGE("Get real path failed"); return workInfos; } WS_HILOGD("Read from %{public}s", realPath.c_str()); fin.open(realPath, ios::in); if (!fin.is_open()) { WS_HILOGE("cannot open file %{public}s", realPath.c_str()); return workInfos; } char buffer[MAX_BUFFER]; ostringstream os; while (fin.getline(buffer, MAX_BUFFER)) { os << buffer; } string data = os.str(); JSONCPP_STRING errs; Json::Value root; Json::CharReaderBuilder readerBuilder; const unique_ptr jsonReader(readerBuilder.newCharReader()); bool res = jsonReader->parse(data.c_str(), data.c_str() + data.length(), &root, &errs); fin.close(); if (!res || !errs.empty()) { return workInfos; } for (auto it : root.getMemberNames()) { Json::Value workJson = root[it]; shared_ptr workInfo = make_shared(); if (workInfo->ParseFromJson(workJson)) { workInfos.emplace_back(workInfo); string workId = "u" + to_string(workInfo->GetUid()) + "_" + to_string(workInfo->GetWorkId()); persistedMap_[workId] = workInfo; } } return workInfos; } void WorkSchedulerService::OnStop() { WS_HILOGI("stop service."); std::lock_guard observerLock(observerMutex_); #ifdef DEVICE_USAGE_STATISTICS_ENABLE DeviceUsageStats::BundleActiveClient::GetInstance().UnRegisterAppGroupCallBack(groupObserver_); groupObserver_ = nullptr; g_hasGroupObserver = -1; #endif #ifdef DEVICE_STANDBY_ENABLE DevStandbyMgr::StandbyServiceClient::GetInstance().UnsubscribeStandbyCallback(standbyStateObserver_); standbyStateObserver_ = nullptr; #endif #ifdef RESOURCESCHEDULE_BGTASKMGR_ENABLE ErrCode ret = BackgroundTaskMgr::BackgroundTaskMgrHelper::UnsubscribeBackgroundTask(*subscriber_); if (ret != ERR_OK) { WS_HILOGE("unscribe bgtask failed."); } #endif eventRunner_.reset(); handler_.reset(); ready_ = false; } bool WorkSchedulerService::Init(const std::shared_ptr& runner) { if (!IsBaseAbilityReady()) { WS_HILOGE("request system service is not ready yet!"); GetHandler()->SendEvent(InnerEvent::Get(WorkEventHandler::SERVICE_INIT_MSG, 0), INIT_DELAY); return false; } WorkQueueManagerInit(runner); if (!WorkPolicyManagerInit(runner)) { WS_HILOGE("init failed due to work policy manager init."); return false; } InitPersisted(); if (!Publish(wss)) { WS_HILOGE("OnStart register to system ability manager failed!"); return false; } WS_HILOGI("start init background task subscriber!"); if (!InitBgTaskSubscriber()) { WS_HILOGE("subscribe background task failed!"); return false; } checkBundle_ = true; ready_ = true; WS_HILOGI("init success."); return true; } bool WorkSchedulerService::InitBgTaskSubscriber() { #ifdef RESOURCESCHEDULE_BGTASKMGR_ENABLE subscriber_ = make_shared(); ErrCode ret = BackgroundTaskMgr::BackgroundTaskMgrHelper::SubscribeBackgroundTask(*subscriber_); if (ret != ERR_OK) { WS_HILOGE("SubscribeBackgroundTask failed."); return false; } this->QueryResAppliedUid(); WS_HILOGD("subscribe background TASK success!"); #endif return true; } ErrCode WorkSchedulerService::QueryResAppliedUid() { #ifdef RESOURCESCHEDULE_BGTASKMGR_ENABLE std::vector> appList; std::vector> procList; ErrCode result = BackgroundTaskMgr::BackgroundTaskMgrHelper::GetEfficiencyResourcesInfos(appList, procList); if (result != ERR_OK) { WS_HILOGE("failed to GetEfficiencyResourcesInfos, errcode: %{public}d", result); return result; } std::lock_guard lock(whitelistMutex_); for (const auto& info : appList) { if ((info->GetResourceNumber() & BackgroundTaskMgr::ResourceType::WORK_SCHEDULER) != 0) { whitelist_.emplace(info->GetUid()); } } for (const auto& info : procList) { if ((info->GetResourceNumber() & BackgroundTaskMgr::ResourceType::WORK_SCHEDULER) != 0) { whitelist_.emplace(info->GetUid()); } } WS_HILOGI("get efficiency resources infos succeed."); #endif return ERR_OK; } void WorkSchedulerService::WorkQueueManagerInit(const std::shared_ptr& runner) { WS_HILOGD("come in"); if (workQueueManager_ == nullptr) { workQueueManager_ = make_shared(instance); } auto networkListener = make_shared(workQueueManager_); #ifdef POWERMGR_BATTERY_MANAGER_ENABLE auto chargerListener = make_shared(workQueueManager_); auto batteryStatusListener = make_shared(workQueueManager_); auto batteryLevelListener = make_shared(workQueueManager_); #endif // POWERMGR_BATTERY_MANAGER_ENABLE auto storageListener = make_shared(workQueueManager_); auto timerListener = make_shared(workQueueManager_, runner); auto groupListener = make_shared(workQueueManager_, runner); workQueueManager_->AddListener(WorkCondition::Type::NETWORK, networkListener); #ifdef POWERMGR_BATTERY_MANAGER_ENABLE workQueueManager_->AddListener(WorkCondition::Type::CHARGER, chargerListener); workQueueManager_->AddListener(WorkCondition::Type::BATTERY_STATUS, batteryStatusListener); workQueueManager_->AddListener(WorkCondition::Type::BATTERY_LEVEL, batteryLevelListener); #endif // POWERMGR_BATTERY_MANAGER_ENABLE workQueueManager_->AddListener(WorkCondition::Type::STORAGE, storageListener); workQueueManager_->AddListener(WorkCondition::Type::TIMER, timerListener); workQueueManager_->AddListener(WorkCondition::Type::GROUP, groupListener); #ifdef DEVICE_USAGE_STATISTICS_ENABLE GroupObserverInit(); #endif RegisterStandbyStateObserver(); } bool WorkSchedulerService::WorkPolicyManagerInit(const std::shared_ptr& runner) { WS_HILOGD("come in"); if (workPolicyManager_ == nullptr) { workPolicyManager_ = make_shared(instance); } if (!workPolicyManager_->Init(runner)) { WS_HILOGE("work policy manager init failed!"); return false; } #ifdef POWERMGR_THERMAL_MANAGER_ENABLE auto thermalFilter = make_shared(workPolicyManager_); workPolicyManager_->AddPolicyFilter(thermalFilter); #endif // POWERMGR_THERMAL_MANAGER_ENABLE auto memoryFilter = make_shared(workPolicyManager_); workPolicyManager_->AddPolicyFilter(memoryFilter); auto appDataClearListener = make_shared(workPolicyManager_); workPolicyManager_->AddAppDataClearListener(appDataClearListener); WS_HILOGI("work policy manager init success."); return true; } bool WorkSchedulerService::CheckWorkInfo(WorkInfo &workInfo, int32_t &uid) { sptr systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); if (!systemAbilityManager) { WS_HILOGE("fail to get system ability mgr."); return false; } sptr remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); if (!remoteObject) { WS_HILOGE("fail to get bundle manager proxy."); return false; } sptr bundleMgr = iface_cast(remoteObject); BundleInfo bundleInfo; int32_t currentAccountId = WorkSchedUtils::GetCurrentAccountId(); std::string bundleName = workInfo.GetBundleName(); WS_HILOGD("check work info currentAccountId : %{public}d, bundleName : %{public}s.", currentAccountId, bundleName.c_str()); if (bundleMgr->GetBundleInfo(bundleName, BundleFlag::GET_BUNDLE_WITH_ABILITIES, bundleInfo, currentAccountId)) { WS_HILOGD("bundleUid : %{public}d , uid : %{public}d.", bundleInfo.uid, uid); return bundleInfo.uid == uid; } WS_HILOGE("Get bundle info failed."); return false; } bool WorkSchedulerService::CheckCondition(WorkInfo& workInfo) { if (workInfo.GetConditionMap()->size() < 1) { return false; } if (workInfo.GetConditionMap()->count(WorkCondition::Type::TIMER) > 0) { uint32_t time = workInfo.GetConditionMap()->at(WorkCondition::Type::TIMER)->uintVal; if (time < workQueueManager_->GetTimeCycle()) { WS_HILOGE("fail, set time:%{public}u must more than %{public}u", time, workQueueManager_->GetTimeCycle()); return false; } } return true; } int32_t WorkSchedulerService::StartWork(WorkInfo& workInfo) { if (!ready_) { WS_HILOGE("service is not ready."); return E_SERVICE_NOT_READY; } int32_t uid = IPCSkeleton::GetCallingUid(); if (checkBundle_ && !CheckWorkInfo(workInfo, uid)) { return E_CHECK_WORKINFO_FAILED; } if (!CheckCondition(workInfo)) { return E_REPEAT_CYCLE_TIME_ERR; } time_t baseTime; (void)time(&baseTime); workInfo.RequestBaseTime(baseTime); WS_HILOGD("workInfo %{public}s/%{public}s ID: %{public}d, uid: %{public}d", workInfo.GetBundleName().c_str(), workInfo.GetAbilityName().c_str(), workInfo.GetWorkId(), uid); shared_ptr workStatus = make_shared(workInfo, uid); int32_t ret = workPolicyManager_->AddWork(workStatus, uid); if (ret == ERR_OK) { workQueueManager_->AddWork(workStatus); if (workInfo.IsPersisted()) { std::lock_guard lock(mutex_); workStatus->workInfo_->RefreshUid(uid); persistedMap_.emplace(workStatus->workId_, workStatus->workInfo_); RefreshPersistedWorks(); } } return ret; } void WorkSchedulerService::InitPersistedWork(WorkInfo& workInfo) { WS_HILOGD("come in"); if (workInfo.GetUid() > 0) { shared_ptr workStatus = make_shared(workInfo, workInfo.GetUid()); if (workPolicyManager_->AddWork(workStatus, workInfo.GetUid()) == ERR_OK) { workQueueManager_->AddWork(workStatus); } } else { WS_HILOGE("uid is invalid : %{public}d", workInfo.GetUid()); } } int32_t WorkSchedulerService::StopWork(WorkInfo& workInfo) { if (!ready_) { WS_HILOGE("service is not ready."); return E_SERVICE_NOT_READY; } int32_t uid = IPCSkeleton::GetCallingUid(); if (checkBundle_ && !CheckWorkInfo(workInfo, uid)) { return E_CHECK_WORKINFO_FAILED; } shared_ptr workStatus = workPolicyManager_->FindWorkStatus(workInfo, uid); if (workStatus == nullptr) { WS_HILOGE("workStatus is nullptr"); return E_WORK_NOT_EXIST_FAILED; } StopWorkInner(workStatus, uid, false, false); return ERR_OK; } int32_t WorkSchedulerService::StopAndCancelWork(WorkInfo& workInfo) { if (!ready_) { WS_HILOGE("service is not ready."); return E_SERVICE_NOT_READY; } int32_t uid = IPCSkeleton::GetCallingUid(); if (checkBundle_ && !CheckWorkInfo(workInfo, uid)) { return E_CHECK_WORKINFO_FAILED; } shared_ptr workStatus = workPolicyManager_->FindWorkStatus(workInfo, uid); if (workStatus == nullptr) { WS_HILOGE("workStatus is nullptr"); return E_WORK_NOT_EXIST_FAILED; } StopWorkInner(workStatus, uid, true, false); if (workStatus->persisted_) { std::lock_guard lock(mutex_); persistedMap_.erase(workStatus->workId_); RefreshPersistedWorks(); } return ERR_OK; } bool WorkSchedulerService::StopWorkInner(std::shared_ptr workStatus, int32_t uid, const bool needCancel, bool isTimeOut) { if (workPolicyManager_->StopWork(workStatus, uid, needCancel, isTimeOut)) { workQueueManager_->CancelWork(workStatus); } return true; } void WorkSchedulerService::WatchdogTimeOut(std::shared_ptr workStatus) { StopWorkInner(workStatus, workStatus->uid_, false, true); } int32_t WorkSchedulerService::StopAndClearWorks() { if (!ready_) { WS_HILOGE("service is not ready."); return E_SERVICE_NOT_READY; } StopAndClearWorksByUid(IPCSkeleton::GetCallingUid()); return ERR_OK; } bool WorkSchedulerService::StopAndClearWorksByUid(int32_t uid) { WS_HILOGD("Stop and clear works by Uid:%{public}d", uid); list> allWorks = workPolicyManager_->GetAllWorkStatus(uid); list workIdList; std::transform(allWorks.cbegin(), allWorks.cend(), std::back_inserter(workIdList), [](std::shared_ptr work) { return work->workId_; }); bool ret = workQueueManager_->StopAndClearWorks(allWorks) && workPolicyManager_->StopAndClearWorks(uid); if (ret) { std::lock_guard lock(mutex_); for (auto workId : workIdList) { if (persistedMap_.count(workId) != 0) { persistedMap_.erase(workId); } } RefreshPersistedWorks(); } return ret; } int32_t WorkSchedulerService::IsLastWorkTimeout(int32_t workId, bool &result) { if (!ready_) { WS_HILOGE("service is not ready."); return E_SERVICE_NOT_READY; } int32_t uid = IPCSkeleton::GetCallingUid(); return workPolicyManager_->IsLastWorkTimeout(workId, uid, result); } void WorkSchedulerService::OnConditionReady(shared_ptr>> workStatusVector) { workPolicyManager_->OnConditionReady(workStatusVector); } int32_t WorkSchedulerService::ObtainAllWorks(int32_t &uid, int32_t &pid, std::list>& workInfos) { if (!ready_) { WS_HILOGE("service is not ready."); return E_SERVICE_NOT_READY; } workInfos = workPolicyManager_->ObtainAllWorks(uid); return ERR_OK; } int32_t WorkSchedulerService::GetWorkStatus(int32_t &uid, int32_t &workId, std::shared_ptr& workInfo) { if (!ready_) { WS_HILOGE("service is not ready."); workInfo = nullptr; return E_SERVICE_NOT_READY; } workInfo = workPolicyManager_->GetWorkStatus(uid, workId); return ERR_OK; } int32_t WorkSchedulerService::GetAllRunningWorks(std::list>& workInfos) { if (!ready_) { WS_HILOGE("service is not ready."); return E_SERVICE_NOT_READY; } workInfos = workPolicyManager_->GetAllRunningWorks(); return ERR_OK; } void WorkSchedulerService::UpdateWorkBeforeRealStart(std::shared_ptr work) { if (work == nullptr) { return; } work->UpdateTimerIfNeed(); if (work->NeedRemove()) { workQueueManager_->RemoveWork(work); } } bool WorkSchedulerService::AllowDump() { Security::AccessToken::AccessTokenID tokenId = IPCSkeleton::GetFirstTokenID(); int32_t ret = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, "ohos.permission.DUMP"); if (ret != Security::AccessToken::PermissionState::PERMISSION_GRANTED) { WS_HILOGE("CheckPermission failed"); return false; } int32_t ENG_MODE = OHOS::system::GetIntParameter("const.debuggable", 0); bool SECURE_MODE = OHOS::system::GetBoolParameter("const.security.developermode.state", false); if (ENG_MODE == 1 || SECURE_MODE) { return true; } WS_HILOGE("Not eng mode and developer mode"); return false; } void WorkSchedulerService::DumpProcess(std::vector &argsInStr, std::string &result) { switch (argsInStr.size()) { case 0: // hidumper -s said '-h' DumpUsage(result); break; case DUMP_OPTION + 1: // hidumper -s said '-h' or hidumper -s said '-a' if (argsInStr[DUMP_OPTION] == "-h") { DumpUsage(result); } else if (argsInStr[DUMP_OPTION] == "-a") { DumpAllInfo(result); } else { result.append("Error params."); } break; case DUMP_PARAM_INDEX + 1: DumpParamSet(argsInStr[DUMP_OPTION], argsInStr[DUMP_PARAM_INDEX], result); break; case DUMP_VALUE_INDEX + 1: if (argsInStr[DUMP_OPTION] == "-d") { EventPublisher eventPublisher; eventPublisher.Dump(result, argsInStr[DUMP_PARAM_INDEX], argsInStr[DUMP_VALUE_INDEX]); } else if (argsInStr[DUMP_OPTION] == "-t") { DumpProcessWorks(argsInStr[DUMP_PARAM_INDEX], argsInStr[DUMP_VALUE_INDEX], result); } else { result.append("Error params."); } break; default: result.append("Error params."); } } int32_t WorkSchedulerService::Dump(int32_t fd, const std::vector& args) { if (!AllowDump()) { return ERR_OK; } std::string result; if (!ready_) { WS_HILOGE("service is not ready."); result.append("service is not ready."); if (!SaveStringToFd(fd, result)) { WS_HILOGE("save to fd failed."); } return ERR_OK; } std::vector argsInStr; std::transform(args.begin(), args.end(), std::back_inserter(argsInStr), [](const std::u16string &arg) { return Str16ToStr8(arg); }); DumpProcess(argsInStr, result); if (!SaveStringToFd(fd, result)) { WS_HILOGE("save to fd failed."); } return ERR_OK; } void WorkSchedulerService::DumpUsage(std::string &result) { result.append("usage: workscheduler dump []\n") .append(" -h: show the help.\n") .append(" -a: show all info.\n") .append(" -d event info: show the event info.\n") .append(" -d (eventType) (TypeValue): publish the event.\n") .append(" -t (bundleName) (abilityName): trigger the work.\n") .append(" -memory (number): set the available memory.\n") .append(" -watchdog_time (number): set watch dog time, default 120000.\n") .append(" -repeat_time_min (number): set min repeat cycle time, default 1200000.\n") .append(" -min_interval (number): set min interval time, set 0 means close test mode.\n"); } void WorkSchedulerService::DumpAllInfo(std::string &result) { result.append("================Work Queue Infos================\n"); if (workQueueManager_ != nullptr) { workQueueManager_->Dump(result); } result.append("================Work Policy Infos================\n"); if (workPolicyManager_ != nullptr) { workPolicyManager_->Dump(result); } result.append("================Other Infos================\n"); result.append("Need check bundle:" + std::to_string(checkBundle_) + "\n") .append("Dump set memory:" + std::to_string(workPolicyManager_->GetDumpSetMemory()) + "\n") .append("Repeat cycle time min:" + std::to_string(workQueueManager_->GetTimeCycle()) + "\n") .append("Watchdog time:" + std::to_string(workPolicyManager_->GetWatchdogTime()) + "\n") .append("whitelist:" + GetEffiResApplyUid()); } bool WorkSchedulerService::IsDebugApp(const std::string &bundleName) { sptr systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); if (!systemAbilityManager) { WS_HILOGE("fail to get system ability mgr."); return false; } sptr remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); if (!remoteObject) { WS_HILOGE("fail to get bundle manager proxy."); return false; } sptr bundleMgr = iface_cast(remoteObject); BundleInfo bundleInfo; int32_t currentAccountId = WorkSchedUtils::GetCurrentAccountId(); if (bundleMgr->GetBundleInfo(bundleName, BundleFlag::GET_BUNDLE_WITH_ABILITIES, bundleInfo, currentAccountId)) { WS_HILOGD("bundleUid : %{public}d , debug : %{public}d.", bundleInfo.uid, bundleInfo.applicationInfo.debug); return bundleInfo.applicationInfo.debug; } WS_HILOGE("Get bundle info failed."); return false; } void WorkSchedulerService::DumpProcessWorks(const std::string &bundleName, const std::string &abilityName, std::string &result) { if (bundleName.empty() || abilityName.empty()) { result.append("param error"); return; } workPolicyManager_->DumpCheckIdeWorkToRun(bundleName, abilityName); } std::string WorkSchedulerService::GetEffiResApplyUid() { std::lock_guard lock(whitelistMutex_); if (whitelist_.empty()) { return "empty"; } std::string res {""}; for (auto &it : whitelist_) { res.append(std::to_string(it) + " "); } WS_HILOGD("GetWhiteList : %{public}s", res.c_str()); return res; } void WorkSchedulerService::DumpParamSet(std::string &key, std::string &value, std::string &result) { if (key == "-memory") { workPolicyManager_->SetMemoryByDump(std::stoi(value)); result.append("Set memory success."); } else if (key == "-watchdog_time") { workPolicyManager_->SetWatchdogTimeByDump(std::stoi(value)); result.append("Set watchdog time success."); } else if (key == "-repeat_time_min") { workQueueManager_->SetTimeCycle(std::stoi(value)); result.append("Set repeat time min value success."); } else if (key == "-min_interval") { workQueueManager_->SetMinIntervalByDump(std::stoi(value)); result.append("Set min interval value success."); } else { result.append("Error params."); } } void WorkSchedulerService::RefreshPersistedWorks() { Json::Value root; for (auto &it : persistedMap_) { auto workInfo = it.second; string data = workInfo->ParseToJsonStr(); JSONCPP_STRING errs; Json::Value workJson; Json::CharReaderBuilder readerBuilder; const unique_ptr jsonReader(readerBuilder.newCharReader()); bool res = jsonReader->parse(data.c_str(), data.c_str() + data.length(), &workJson, &errs); if (res && errs.empty()) { root[it.first] = workJson; } } Json::StreamWriterBuilder writerBuilder; ostringstream os; unique_ptr jsonWriter(writerBuilder.newStreamWriter()); jsonWriter->write(root, &os); string result = os.str(); WS_HILOGD("Work JSON os result %{public}s", result.c_str()); CreateNodeDir(g_persistedPath); CreateNodeFile(g_persistedFilePath); ofstream fout; std::string realPath; if (!WorkSchedUtils::ConvertFullPath(g_persistedFilePath, realPath)) { WS_HILOGE("Get real path failed"); return; } WS_HILOGD("Refresh path %{public}s", realPath.c_str()); fout.open(realPath, ios::out); fout< lock(whitelistMutex_); if (isAdd) { whitelist_.emplace(uid); } else { whitelist_.erase(uid); } } bool WorkSchedulerService::CheckEffiResApplyInfo(int32_t uid) { std::lock_guard lock(whitelistMutex_); return whitelist_.find(uid) != whitelist_.end(); } bool WorkSchedulerService::CheckStandbyApplyInfo(std::string& bundleName) { WS_HILOGD("%{public}s is checking standby applyInfo", bundleName.c_str()); #ifdef DEVICE_STANDBY_ENABLE std::lock_guard observerLock(observerMutex_); if (!standbyStateObserver_) { return true; } std::vector allowInfoArray; DevStandbyMgr::StandbyServiceClient::GetInstance().GetAllowList(DevStandbyMgr::AllowType::WORK_SCHEDULER, allowInfoArray, DevStandbyMgr::ReasonCodeEnum::REASON_APP_API); WS_HILOGD("allowInfoArray size is %{public}d", static_cast(allowInfoArray.size())); for (const auto& item : allowInfoArray) { if (item.GetName() == bundleName) { return true; } } #endif return false; } void WorkSchedulerService::OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId) { if (systemAbilityId == DEVICE_USAGE_STATISTICS_SYS_ABILITY_ID) { #ifdef DEVICE_USAGE_STATISTICS_ENABLE GroupObserverInit(); #endif } if (systemAbilityId == DEVICE_STANDBY_SERVICE_SYSTEM_ABILITY_ID) { RegisterStandbyStateObserver(); } } void WorkSchedulerService::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId) { if (systemAbilityId == DEVICE_STANDBY_SERVICE_SYSTEM_ABILITY_ID) { if (!workQueueManager_) { return; } workQueueManager_->OnConditionChanged(WorkCondition::Type::STANDBY, std::make_shared(0, 0, false, std::string())); #ifdef DEVICE_STANDBY_ENABLE std::lock_guard observerLock(observerMutex_); standbyStateObserver_ = nullptr; #endif } else if (systemAbilityId == DEVICE_USAGE_STATISTICS_SYS_ABILITY_ID) { #ifdef DEVICE_USAGE_STATISTICS_ENABLE std::lock_guard observerLock(observerMutex_); groupObserver_ = nullptr; #endif } } #ifdef DEVICE_USAGE_STATISTICS_ENABLE void WorkSchedulerService::GroupObserverInit() { if (!workQueueManager_) { return; } std::lock_guard observerLock(observerMutex_); if (!groupObserver_) { groupObserver_ = new (std::nothrow) WorkBundleGroupChangeCallback(workQueueManager_); } if (groupObserver_ && g_hasGroupObserver != ERR_OK) { g_hasGroupObserver = DeviceUsageStats::BundleActiveClient::GetInstance().RegisterAppGroupCallBack(groupObserver_); } } #endif void WorkSchedulerService::RegisterStandbyStateObserver() { if (!workQueueManager_) { return; } #ifdef DEVICE_STANDBY_ENABLE std::lock_guard observerLock(observerMutex_); if (standbyStateObserver_) { WS_HILOGD("standbyStateObserver_ is already exist, do not need repeat process."); return; } standbyStateObserver_ = new (std::nothrow) WorkStandbyStateChangeCallback(workQueueManager_); if (!standbyStateObserver_) { return; } standbyStateObserver_->SetSubscriberName(STRATEGY_NAME); ErrCode ret = DevStandbyMgr::StandbyServiceClient::GetInstance().SubscribeStandbyCallback(standbyStateObserver_); if (ret != ERR_OK) { WS_HILOGE("Subscriber standbyStateObserver_ failed."); standbyStateObserver_ = nullptr; } #endif } } // namespace WorkScheduler } // namespace OHOS