• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "work_scheduler_service.h"
16 
17 #include <cstdio>
18 #include <cstdlib>
19 #include <fstream>
20 #include <iostream>
21 #include <climits>          // for PATH_MAX
22 
23 #include <dirent.h>
24 #include <fcntl.h>
25 #include <file_ex.h>
26 #include <if_system_ability_manager.h>
27 #include <ipc_skeleton.h>
28 #include <iservice_registry.h>
29 #include <string_ex.h>
30 #include <system_ability_definition.h>
31 #include <sys/stat.h>
32 #include <sys/statfs.h>
33 #include <unistd.h>
34 
35 #include "parameters.h"
36 #include "accesstoken_kit.h"
37 #include "bundle_mgr_proxy.h"
38 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
39 #include "bundle_active_client.h"
40 #endif
41 #ifdef DEVICE_STANDBY_ENABLE
42 #include "standby_service_client.h"
43 #include "allow_type.h"
44 #endif
45 #include "conditions/battery_level_listener.h"
46 #include "conditions/battery_status_listener.h"
47 #include "conditions/charger_listener.h"
48 #include "conditions/condition_checker.h"
49 #include "conditions/network_listener.h"
50 #include "conditions/screen_listener.h"
51 #include "conditions/storage_listener.h"
52 #include "conditions/timer_listener.h"
53 #include "conditions/group_listener.h"
54 #include "config_policy_utils.h"           // for GetOneCfgFile
55 #include "directory_ex.h"
56 #include "event_publisher.h"
57 #include "policy/app_data_clear_listener.h"
58 #include "policy/memory_policy.h"
59 #include "policy/thermal_policy.h"
60 #include "policy/cpu_policy.h"
61 #ifdef POWERMGR_POWER_MANAGER_ENABLE
62 #include "policy/power_mode_policy.h"
63 #endif
64 #ifdef RESOURCESCHEDULE_BGTASKMGR_ENABLE
65 #include "scheduler_bg_task_subscriber.h"
66 #include "background_task_mgr_helper.h"
67 #include "resource_type.h"
68 #endif
69 #include "work_datashare_helper.h"
70 #include "work_scheduler_connection.h"
71 #include "work_bundle_group_change_callback.h"
72 #include "work_sched_errors.h"
73 #include "work_sched_hilog.h"
74 #include "work_sched_utils.h"
75 #include "hitrace_meter.h"
76 #include "hisysevent.h"
77 #include "res_type.h"
78 #include "res_sched_client.h"
79 #include "work_sched_data_manager.h"
80 #include "work_sched_config.h"
81 #include "work_sched_constants.h"
82 #include "work_sched_hisysevent_report.h"
83 
84 #ifdef HICOLLIE_ENABLE
85 #include "xcollie/xcollie.h"
86 #include "xcollie/xcollie_define.h"
87 #define XCOLLIE_TIMEOUT_SECONDS 10
88 #endif
89 
90 using namespace std;
91 using namespace OHOS::AppExecFwk;
92 
93 namespace OHOS {
94 namespace WorkScheduler {
95 namespace {
96 const std::string WORKSCHEDULER_SERVICE_NAME = "WorkSchedulerService";
97 const std::string PRINSTALLED_WORKS_KEY = "work_scheduler_preinstalled_works";
98 const std::string EXEMPTION_BUNDLES_KEY = "work_scheduler_eng_exemption_bundles";
99 const std::string MIN_REPEAT_TIME_KEY = "work_scheduler_min_repeat_time";
100 auto instance = DelayedSingleton<WorkSchedulerService>::GetInstance();
101 auto wss = instance.get();
102 const bool G_REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(wss);
103 const int32_t UID_TRANSFORM_DIVISOR = 200000;
104 const int32_t INIT_DELAY = 2 * 1000;
105 const int32_t CHECK_CONDITION_DELAY = 5 * 1000;
106 const int32_t MAX_BUFFER = 2048;
107 const int32_t DUMP_OPTION = 0;
108 const int32_t DUMP_PARAM_INDEX = 1;
109 const int32_t DUMP_VALUE_INDEX = 2;
110 const int32_t TIME_OUT = 4;
111 const uint32_t SYS_APP_MIN_REPEAT_TIME = 5 * 60 * 1000;
112 const char* PERSISTED_FILE_PATH = "/data/service/el1/public/WorkScheduler/persisted_work";
113 const char* PERSISTED_PATH = "/data/service/el1/public/WorkScheduler";
114 const char* PREINSTALLED_FILE_PATH = "etc/backgroundtask/config.json";
115 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
116 static int g_hasGroupObserver = -1;
117 #endif
118 const static std::string STRATEGY_NAME = "WORK_SCHEDULER";
119 const std::set<std::string> WORK_SCHED_NATIVE_OPERATE_CALLER = {
120     "resource_schedule_service",
121     "hidumper_service",
122 };
123 
124 const std::set<std::string> WORK_SCHED_SA_CALLER = {
125     "push_manager_service",
126 };
127 }
128 
129 #ifdef WORK_SCHEDULER_TEST
130 #define WEAK_FUNC __attribute__((weak))
131 #else
132 #define WEAK_FUNC
133 #endif
134 
WorkSchedulerService()135 WorkSchedulerService::WorkSchedulerService() : SystemAbility(WORK_SCHEDULE_SERVICE_ID, true) {}
~WorkSchedulerService()136 WorkSchedulerService::~WorkSchedulerService() {}
137 
OnStart()138 void WorkSchedulerService::OnStart()
139 {
140     if (ready_) {
141         WS_HILOGI("OnStart is ready, nothing to do.");
142         return;
143     }
144 
145     // Init handler.
146     if (!eventRunner_) {
147         eventRunner_ = AppExecFwk::EventRunner::Create(WORKSCHEDULER_SERVICE_NAME, AppExecFwk::ThreadMode::FFRT);
148     }
149     if (eventRunner_ == nullptr) {
150         WS_HILOGE("Init failed due to create EventRunner");
151         return;
152     }
153     handler_ = std::make_shared<WorkEventHandler>(eventRunner_, instance);
154     if (!handler_) {
155         WS_HILOGE("Init failed due to create handler_");
156         return;
157     }
158 
159     // Try to init.
160     Init(eventRunner_);
161 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
162     AddSystemAbilityListener(DEVICE_USAGE_STATISTICS_SYS_ABILITY_ID);
163 #endif
164 #ifdef DEVICE_STANDBY_ENABLE
165     AddSystemAbilityListener(DEVICE_STANDBY_SERVICE_SYSTEM_ABILITY_ID);
166 #endif
167     WS_HILOGD("On start success.");
168 }
169 
IsBaseAbilityReady()170 WEAK_FUNC bool WorkSchedulerService::IsBaseAbilityReady()
171 {
172     sptr<ISystemAbilityManager> systemAbilityManager
173         = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
174     if (systemAbilityManager == nullptr
175         || systemAbilityManager->CheckSystemAbility(APP_MGR_SERVICE_ID) == nullptr
176         || systemAbilityManager->CheckSystemAbility(COMMON_EVENT_SERVICE_ID) == nullptr
177         || systemAbilityManager->CheckSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID) == nullptr
178         || systemAbilityManager->CheckSystemAbility(BACKGROUND_TASK_MANAGER_SERVICE_ID) == nullptr
179         || systemAbilityManager->CheckSystemAbility(TIME_SERVICE_ID) == nullptr) {
180         return false;
181     }
182     return true;
183 }
184 
InitPersistedWork()185 void WorkSchedulerService::InitPersistedWork()
186 {
187     WS_HILOGD("init persisted work");
188     std::lock_guard<ffrt::mutex> lock(mutex_);
189     list<shared_ptr<WorkInfo>> persistedWorks = ReadPersistedWorks();
190     for (auto it : persistedWorks) {
191         WS_HILOGI("get persisted work, id: %{public}d, isSa:%{public}d", it->GetWorkId(), it->IsSA());
192         AddWorkInner(*it);
193     }
194     RefreshPersistedWorks();
195 }
196 
InitPreinstalledWork()197 void WorkSchedulerService::InitPreinstalledWork()
198 {
199     WS_HILOGD("init preinstalled work");
200     list<shared_ptr<WorkInfo>> preinstalledWorks = ReadPreinstalledWorks();
201     std::lock_guard<ffrt::mutex> lock(mutex_);
202     for (auto work : preinstalledWorks) {
203         WS_HILOGI("preinstalled workinfo id %{public}s, isSa:%{public}d", work->GetBriefInfo().c_str(), work->IsSA());
204         time_t baseTime;
205         (void)time(&baseTime);
206         work->RequestBaseTime(baseTime);
207         AddWorkInner(*work);
208         if (work->IsPersisted()) {
209             string workId = "u" + to_string(work->GetUid()) + "_" + to_string(work->GetWorkId());
210             persistedMap_.emplace(workId, work);
211         }
212     }
213     if (minCheckTime_ && minCheckTime_ < workQueueManager_->GetTimeCycle()) {
214         workQueueManager_->SetTimeCycle(minCheckTime_);
215     }
216 }
217 
InitWorkInner()218 void WorkSchedulerService::InitWorkInner()
219 {
220     InitPreinstalledWork();
221     InitPersistedWork();
222 }
223 
ReadPersistedWorks()224 list<shared_ptr<WorkInfo>> WorkSchedulerService::ReadPersistedWorks()
225 {
226     list<shared_ptr<WorkInfo>> workInfos;
227     nlohmann::json root;
228     if (!GetJsonFromFile(PERSISTED_FILE_PATH, root)) {
229         return workInfos;
230     }
231     if (root.is_null() || root.empty()) {
232         WS_HILOGE("ReadPersistedWorks failed, root is empty or not an object");
233         return workInfos;
234     }
235     for (const auto &[key, workJson] : root.items()) {
236         shared_ptr<WorkInfo> workInfo = make_shared<WorkInfo>();
237         if (!workInfo->ParseFromJson(workJson)) {
238             WS_HILOGE("ReadPersistedWorks failed, parseFromJson error");
239             continue;
240         }
241         workInfos.emplace_back(workInfo);
242         WS_HILOGI("find one persisted work %{public}s", workInfo->GetBriefInfo().c_str());
243         auto iter = std::find_if(persistedMap_.begin(), persistedMap_.end(), [&](const auto &pair) {
244             return (pair.second->GetUid() == workInfo->GetUid()) && (pair.second->GetWorkId() == workInfo->GetWorkId());
245         });
246         if (iter != persistedMap_.end()) {
247             WS_HILOGI("find work %{public}s in persisted map, ignore, isSA:%{public}d",
248                 workInfo->GetBriefInfo().c_str(),
249                 workInfo->IsSA());
250             // update basetime
251             continue;
252         }
253         string workId = "u" + to_string(workInfo->GetUid()) + "_" + to_string(workInfo->GetWorkId());
254         persistedMap_.emplace(workId, workInfo);
255     }
256     return workInfos;
257 }
258 
LoadWorksFromFile(const char * path,list<shared_ptr<WorkInfo>> & workInfos)259 void WorkSchedulerService::LoadWorksFromFile(const char *path, list<shared_ptr<WorkInfo>> &workInfos)
260 {
261     if (!path) {
262         return;
263     }
264     nlohmann::json root;
265     if (!GetJsonFromFile(path, root) || root.is_null() || root.empty()) {
266         WS_HILOGE("file is empty");
267         return;
268     }
269     if (!root.contains(PRINSTALLED_WORKS_KEY)) {
270         WS_HILOGE("no work_scheduler_preinstalled_works key");
271         return;
272     }
273     nlohmann::json preinstalledWorksRoot = root[PRINSTALLED_WORKS_KEY];
274     if (preinstalledWorksRoot.empty() || !preinstalledWorksRoot.is_object()) {
275         WS_HILOGE("work_scheduler_preinstalled_works content is empty");
276         return;
277     }
278     for (const auto &[key, workJson] : preinstalledWorksRoot.items()) {
279         shared_ptr<WorkInfo> workinfo = make_shared<WorkInfo>();
280         if (!workinfo->ParseFromJson(workJson)) {
281             WS_HILOGE("LoadWorksFromFile failed, parseFromJson error");
282             continue;
283         }
284         if (!workinfo->IsSA()) {
285             int32_t uid;
286             if (!GetUidByBundleName(workinfo->GetBundleName(), uid)) {
287                 continue;
288             }
289             workinfo->RefreshUid(uid);
290             preinstalledBundles_.insert(workinfo->GetBundleName());
291         }
292         workinfo->SetPreinstalled(true);
293         workInfos.emplace_back(workinfo);
294     }
295 }
296 
LoadExemptionBundlesFromFile(const char * path)297 void WorkSchedulerService::LoadExemptionBundlesFromFile(const char *path)
298 {
299     if (!path) {
300         return;
301     }
302     nlohmann::json root;
303     if (!GetJsonFromFile(path, root) || root.is_null() || root.empty()) {
304         WS_HILOGE("file is empty");
305         return;
306     }
307     if (!root.contains(EXEMPTION_BUNDLES_KEY)) {
308         WS_HILOGE("no work_scheduler_eng_exemption_bundles key");
309         return;
310     }
311     nlohmann::json exemptionBundlesRoot = root[EXEMPTION_BUNDLES_KEY];
312     if (exemptionBundlesRoot.empty() || !exemptionBundlesRoot.is_array()) {
313         WS_HILOGE("work_scheduler_eng_exemption_bundles content is empty");
314         return;
315     }
316 
317     for (const auto &exemptionBundleName : exemptionBundlesRoot) {
318         if (exemptionBundleName.empty() || !exemptionBundleName.is_string()) {
319             WS_HILOGE("Item type error");
320         } else {
321             WS_HILOGI("bundle name:%{public}s", exemptionBundleName.get<std::string>().c_str());
322             exemptionBundles_.insert(exemptionBundleName.get<std::string>());
323         }
324     }
325 }
326 
LoadMinRepeatTimeFromFile(const char * path)327 void WorkSchedulerService::LoadMinRepeatTimeFromFile(const char *path)
328 {
329     if (!path) {
330         return;
331     }
332     nlohmann::json root;
333     if (!GetJsonFromFile(path, root) || root.is_null() || root.empty()) {
334         WS_HILOGE("file is empty");
335         return;
336     }
337     if (!root.contains(MIN_REPEAT_TIME_KEY)) {
338         WS_HILOGE("no work_scheduler_min_repeat_time key");
339         return;
340     }
341     nlohmann::json minRepeatTimeRoot = root[MIN_REPEAT_TIME_KEY];
342     if (minRepeatTimeRoot.empty() || !minRepeatTimeRoot.is_object()) {
343         WS_HILOGE("work_scheduler_min_repeat_time content is empty");
344         return;
345     }
346     if (minRepeatTimeRoot.contains("default") && minRepeatTimeRoot["default"].is_number_unsigned()) {
347         minTimeCycle_ = minRepeatTimeRoot["default"].get<uint32_t>();
348     }
349     if (!minRepeatTimeRoot.contains("special")) {
350         WS_HILOGE("no special key");
351         return;
352     }
353     nlohmann::json specialRoot = minRepeatTimeRoot["special"];
354     if (specialRoot.empty() || !specialRoot.is_array()) {
355         WS_HILOGE("special content is empty");
356         return;
357     }
358     minCheckTime_ = workQueueManager_->GetTimeCycle();
359     for (const auto &it : specialRoot) {
360         if (!it.contains("bundleName") || !it["bundleName"].is_string() ||
361             !it.contains("time") || !it["time"].is_number_unsigned()) {
362             WS_HILOGE("special content is error");
363             continue;
364         }
365         uint32_t time = it["time"].get<uint32_t>();
366         if (time < SYS_APP_MIN_REPEAT_TIME) {
367             WS_HILOGE("bundleName: %{public}s set time: %{public}d not available, must more than %{public}d",
368                 it["bundleName"].get<std::string>().c_str(), time, SYS_APP_MIN_REPEAT_TIME);
369             continue;
370         }
371         if (minCheckTime_ > time) {
372             minCheckTime_ = time;
373         }
374         specialMap_.emplace(it["bundleName"].get<std::string>(), time);
375     }
376 }
377 
ReadPreinstalledWorks()378 list<shared_ptr<WorkInfo>> WorkSchedulerService::ReadPreinstalledWorks()
379 {
380     list<shared_ptr<WorkInfo>> workInfos;
381     CfgFiles *files = GetCfgFiles(PREINSTALLED_FILE_PATH);
382     if (!files) {
383         WS_HILOGE("GetCfgFiles failed");
384         WorkSchedUtil::HiSysEventException(EventErrorCode::LOAD_WORK, "get cfg files failed");
385         return workInfos;
386     }
387     // china->base
388     for (int i = MAX_CFG_POLICY_DIRS_CNT - 1; i >= 0; i--) {
389         LoadWorksFromFile(files->paths[i], workInfos);
390         LoadExemptionBundlesFromFile(files->paths[i]);
391         LoadMinRepeatTimeFromFile(files->paths[i]);
392     }
393     FreeCfgFiles(files);
394     return workInfos;
395 }
396 
GetJsonFromFile(const char * filePath,nlohmann::json & root)397 bool WorkSchedulerService::GetJsonFromFile(const char *filePath, nlohmann::json &root)
398 {
399     std::string realPath;
400     if (!WorkSchedUtils::ConvertFullPath(filePath, realPath)) {
401         WS_HILOGE("Get real path failed %{private}s", filePath);
402         WorkSchedUtil::HiSysEventException(EventErrorCode::LOAD_WORK, "convert real path failed");
403         return false;
404     }
405     WS_HILOGD("Read from %{private}s", realPath.c_str());
406     std::string data;
407     LoadStringFromFile(realPath.c_str(), data);
408     WS_HILOGI("data read success");
409     root = nlohmann::json::parse(data, nullptr, false);
410     if (root.is_discarded()) {
411         WS_HILOGE("parse %{private}s json error", realPath.c_str());
412         WorkSchedUtil::HiSysEventException(EventErrorCode::LOAD_WORK, "json parse failed");
413         return false;
414     }
415     WS_HILOGI("json parse success");
416     return true;
417 }
418 
OnStop()419 void WorkSchedulerService::OnStop()
420 {
421     WS_HILOGI("stop service.");
422     std::lock_guard<ffrt::mutex> observerLock(observerMutex_);
423 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
424     DeviceUsageStats::BundleActiveClient::GetInstance().UnRegisterAppGroupCallBack(groupObserver_);
425     groupObserver_ = nullptr;
426     g_hasGroupObserver = -1;
427 #endif
428 #ifdef DEVICE_STANDBY_ENABLE
429     DevStandbyMgr::StandbyServiceClient::GetInstance().UnsubscribeStandbyCallback(standbyStateObserver_);
430     standbyStateObserver_ = nullptr;
431 #endif
432 #ifdef RESOURCESCHEDULE_BGTASKMGR_ENABLE
433     ErrCode ret = BackgroundTaskMgr::BackgroundTaskMgrHelper::UnsubscribeBackgroundTask(*subscriber_);
434     if (ret != ERR_OK) {
435         WS_HILOGE("unscribe bgtask failed.");
436         WorkSchedUtil::HiSysEventException(EventErrorCode::SERVICE_STOP, "unsubscribe background task failed");
437     }
438 #endif
439     eventRunner_.reset();
440     handler_.reset();
441     ready_ = false;
442 }
443 
Init(const std::shared_ptr<AppExecFwk::EventRunner> & runner)444 bool WorkSchedulerService::Init(const std::shared_ptr<AppExecFwk::EventRunner>& runner)
445 {
446     if (!IsBaseAbilityReady()) {
447         WS_HILOGE("request system service is not ready yet!");
448         WorkSchedUtil::HiSysEventException(EventErrorCode::SERVICE_INIT, "request system service is not ready");
449         GetHandler()->SendEvent(InnerEvent::Get(WorkEventHandler::SERVICE_INIT_MSG, 0), INIT_DELAY);
450         return false;
451     }
452     WorkQueueManagerInit(runner);
453     if (!WorkPolicyManagerInit(runner)) {
454         WS_HILOGE("init failed due to work policy manager init.");
455         return false;
456     }
457     InitWorkInner();
458     if (!Publish(wss)) {
459         WS_HILOGE("OnStart register to system ability manager failed!");
460         WorkSchedUtil::HiSysEventException(EventErrorCode::SERVICE_INIT, "register to system ability manager failed");
461         return false;
462     }
463     checkBundle_ = true;
464     ready_ = true;
465     WS_HILOGI("start init background task subscriber!");
466     if (!InitBgTaskSubscriber()) {
467         WS_HILOGE("subscribe background task failed!");
468         return false;
469     }
470     WS_HILOGI("init success.");
471     return true;
472 }
473 
InitBgTaskSubscriber()474 bool WorkSchedulerService::InitBgTaskSubscriber()
475 {
476 #ifdef RESOURCESCHEDULE_BGTASKMGR_ENABLE
477     subscriber_ = make_shared<SchedulerBgTaskSubscriber>();
478     ErrCode ret = BackgroundTaskMgr::BackgroundTaskMgrHelper::SubscribeBackgroundTask(*subscriber_);
479     if (ret != ERR_OK) {
480         WS_HILOGE("SubscribeBackgroundTask failed.");
481         WorkSchedUtil::HiSysEventException(EventErrorCode::SERVICE_INIT, "subscribe background task failed");
482         return false;
483     }
484     this->QueryResAppliedUid();
485     WS_HILOGD("subscribe background TASK success!");
486 #endif
487     return true;
488 }
489 
QueryResAppliedUid()490 ErrCode WorkSchedulerService::QueryResAppliedUid()
491 {
492 #ifdef RESOURCESCHEDULE_BGTASKMGR_ENABLE
493     std::vector<std::shared_ptr<BackgroundTaskMgr::ResourceCallbackInfo>> appList;
494     std::vector<std::shared_ptr<BackgroundTaskMgr::ResourceCallbackInfo>> procList;
495     ErrCode result = BackgroundTaskMgr::BackgroundTaskMgrHelper::GetEfficiencyResourcesInfos(appList, procList);
496     if (result != ERR_OK) {
497         WS_HILOGE("failed to GetEfficiencyResourcesInfos, errcode: %{public}d", result);
498         WorkSchedUtil::HiSysEventException(EventErrorCode::SERVICE_INIT, "get efficiency resources info failed");
499         return result;
500     }
501     std::lock_guard<ffrt::mutex> lock(whitelistMutex_);
502     for (const auto& info : appList) {
503         if ((info->GetResourceNumber() & BackgroundTaskMgr::ResourceType::WORK_SCHEDULER) != 0) {
504             whitelist_.emplace(info->GetUid());
505         }
506     }
507     for (const auto& info : procList) {
508         if ((info->GetResourceNumber() & BackgroundTaskMgr::ResourceType::WORK_SCHEDULER) != 0) {
509             whitelist_.emplace(info->GetUid());
510         }
511     }
512     WS_HILOGI("get efficiency resources infos succeed.");
513 #endif
514     return ERR_OK;
515 }
516 
WorkQueueManagerInit(const std::shared_ptr<AppExecFwk::EventRunner> & runner)517 void WorkSchedulerService::WorkQueueManagerInit(const std::shared_ptr<AppExecFwk::EventRunner>& runner)
518 {
519     WS_HILOGD("come in");
520     if (workQueueManager_ == nullptr) {
521         workQueueManager_ = make_shared<WorkQueueManager>(instance);
522     }
523 
524     auto networkListener = make_shared<NetworkListener>(workQueueManager_);
525 #ifdef POWERMGR_BATTERY_MANAGER_ENABLE
526     auto chargerListener = make_shared<ChargerListener>(workQueueManager_);
527     auto batteryStatusListener = make_shared<BatteryStatusListener>(workQueueManager_);
528     auto batteryLevelListener = make_shared<BatteryLevelListener>(workQueueManager_, shared_from_this());
529     batteryLevelListener->Start();
530 #endif // POWERMGR_BATTERY_MANAGER_ENABLE
531     auto storageListener = make_shared<StorageListener>(workQueueManager_);
532     auto timerListener = make_shared<TimerListener>(workQueueManager_, runner);
533     auto groupListener = make_shared<GroupListener>(workQueueManager_, runner);
534     auto screenListener = make_shared<ScreenListener>(workQueueManager_, shared_from_this());
535 
536     workQueueManager_->AddListener(WorkCondition::Type::NETWORK, networkListener);
537 #ifdef POWERMGR_BATTERY_MANAGER_ENABLE
538     workQueueManager_->AddListener(WorkCondition::Type::CHARGER, chargerListener);
539     workQueueManager_->AddListener(WorkCondition::Type::BATTERY_STATUS, batteryStatusListener);
540     workQueueManager_->AddListener(WorkCondition::Type::BATTERY_LEVEL, batteryLevelListener);
541 #endif // POWERMGR_BATTERY_MANAGER_ENABLE
542     workQueueManager_->AddListener(WorkCondition::Type::STORAGE, storageListener);
543     workQueueManager_->AddListener(WorkCondition::Type::TIMER, timerListener);
544     workQueueManager_->AddListener(WorkCondition::Type::GROUP, groupListener);
545     workQueueManager_->AddListener(WorkCondition::Type::DEEP_IDLE, screenListener);
546 
547 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
548     GroupObserverInit();
549 #endif
550     RegisterStandbyStateObserver();
551 }
552 
WorkPolicyManagerInit(const std::shared_ptr<AppExecFwk::EventRunner> & runner)553 bool WorkSchedulerService::WorkPolicyManagerInit(const std::shared_ptr<AppExecFwk::EventRunner>& runner)
554 {
555     WS_HILOGD("come in");
556     if (workPolicyManager_ == nullptr) {
557         workPolicyManager_ = make_shared<WorkPolicyManager>(instance);
558     }
559     if (!workPolicyManager_->Init(runner)) {
560         WS_HILOGE("work policy manager init failed!");
561         WorkSchedUtil::HiSysEventException(EventErrorCode::SERVICE_INIT, "work policy manager init failed");
562         return false;
563     }
564 
565 #ifdef POWERMGR_THERMAL_MANAGER_ENABLE
566     auto thermalFilter = make_shared<ThermalPolicy>(workPolicyManager_);
567     workPolicyManager_->AddPolicyFilter(thermalFilter);
568 #endif // POWERMGR_THERMAL_MANAGER_ENABLE
569     auto memoryFilter = make_shared<MemoryPolicy>(workPolicyManager_);
570     workPolicyManager_->AddPolicyFilter(memoryFilter);
571 
572     auto cpuFilter = make_shared<CpuPolicy>(workPolicyManager_);
573     workPolicyManager_->AddPolicyFilter(cpuFilter);
574 
575 #ifdef POWERMGR_POWER_MANAGER_ENABLE
576     auto powerModeFilter = make_shared<PowerModePolicy>(workPolicyManager_);
577     workPolicyManager_->AddPolicyFilter(powerModeFilter);
578 #endif
579 
580     auto appDataClearListener = make_shared<AppDataClearListener>(workPolicyManager_);
581     workPolicyManager_->AddAppDataClearListener(appDataClearListener);
582 
583     WS_HILOGI("work policy manager init success.");
584     return true;
585 }
586 
GetUidByBundleName(const string & bundleName,int32_t & uid)587 WEAK_FUNC bool WorkSchedulerService::GetUidByBundleName(const string &bundleName, int32_t &uid)
588 {
589     sptr<ISystemAbilityManager> systemAbilityManager =
590         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
591     if (!systemAbilityManager) {
592         WS_HILOGE("fail to get system ability mgr.");
593         WorkSchedUtil::HiSysEventException(EventErrorCode::WORK_CHECK, "fail to get system ability manager");
594         return false;
595     }
596     sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
597     if (!remoteObject) {
598         WS_HILOGE("fail to get bundle manager proxy.");
599         WorkSchedUtil::HiSysEventException(EventErrorCode::WORK_CHECK, "fail to get bundle manager proxy");
600         return false;
601     }
602     sptr<IBundleMgr> bundleMgr =  iface_cast<IBundleMgr>(remoteObject);
603     BundleInfo bundleInfo;
604     int32_t currentAccountId = WorkSchedUtils::GetCurrentAccountId();
605     if (bundleMgr->GetBundleInfo(bundleName, BundleFlag::GET_BUNDLE_WITH_ABILITIES,
606         bundleInfo, currentAccountId)) {
607         WS_HILOGD("currentAccountId : %{public}d, bundleName : %{public}s, uid = %{public}d",
608             currentAccountId, bundleName.c_str(), bundleInfo.uid);
609         uid = bundleInfo.uid;
610         return true;
611     }
612     WS_HILOGE("Get bundle info %{public}s failed.", bundleName.c_str());
613     WorkSchedUtil::HiSysEventException(EventErrorCode::WORK_CHECK, "fail to get bundle info");
614     return false;
615 }
616 
GetAppIndexAndBundleNameByUid(int32_t uid,int32_t & appIndex,std::string & bundleName)617 bool WorkSchedulerService::GetAppIndexAndBundleNameByUid(int32_t uid, int32_t &appIndex, std::string &bundleName)
618 {
619     sptr<ISystemAbilityManager> systemAbilityManager =
620         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
621     if (!systemAbilityManager) {
622         WS_HILOGE("fail to get system ability mgr.");
623         return false;
624     }
625     sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
626     if (!remoteObject) {
627         WS_HILOGE("fail to get bundle manager proxy.");
628         return false;
629     }
630     sptr<IBundleMgr> bundleMgr =  iface_cast<IBundleMgr>(remoteObject);
631     ErrCode ret = bundleMgr->GetNameAndIndexForUid(uid, bundleName, appIndex);
632     if (ret == ERR_OK) {
633         WS_HILOGD("appIndex = %{public}d", appIndex);
634         return true;
635     }
636     WS_HILOGE("fail to get app index.");
637     return false;
638 }
639 
CheckExtensionInfos(WorkInfo & workInfo,int32_t uid)640 bool WorkSchedulerService::CheckExtensionInfos(WorkInfo &workInfo, int32_t uid)
641 {
642     sptr<ISystemAbilityManager> systemAbilityManager =
643         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
644     if (!systemAbilityManager) {
645         WS_HILOGE("fail to get system ability mgr.");
646         return false;
647     }
648     sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
649     if (!remoteObject) {
650         WS_HILOGE("fail to get bundle manager proxy.");
651         return false;
652     }
653     sptr<IBundleMgr> bundleMgr =  iface_cast<IBundleMgr>(remoteObject);
654     BundleInfo bundleInfo;
655     if (bundleMgr->GetBundleInfo(workInfo.GetBundleName(),
656         BundleFlag::GET_BUNDLE_WITH_EXTENSION_INFO,
657         bundleInfo, uid / UID_TRANSFORM_DIVISOR)) {
658         auto findIter = std::find_if(bundleInfo.extensionInfos.begin(), bundleInfo.extensionInfos.end(),
659             [&](const auto &info) {
660                 WS_HILOGD("%{public}s %{public}s %{public}d", info.bundleName.c_str(), info.name.c_str(), info.type);
661                 return info.bundleName == workInfo.GetBundleName() &&
662                     info.name == workInfo.GetAbilityName() &&
663                     info.type == ExtensionAbilityType::WORK_SCHEDULER;
664             });
665         if (findIter == bundleInfo.extensionInfos.end()) {
666             workInfo.RefreshExtension(false);
667             WS_HILOGE("extension info is error");
668             return false;
669         }
670     }
671     return true;
672 }
673 
CheckWorkInfo(WorkInfo & workInfo,int32_t & uid)674 bool WorkSchedulerService::CheckWorkInfo(WorkInfo &workInfo, int32_t &uid)
675 {
676     int32_t appIndex;
677     string bundleName;
678     if (!GetAppIndexAndBundleNameByUid(uid, appIndex, bundleName)) {
679         WS_HILOGE("uid %{public}d is invalid", uid);
680         return false;
681     }
682     workInfo.RefreshAppIndex(appIndex);
683     if (workInfo.GetBundleName() != bundleName) {
684         WS_HILOGE("bundleName %{public}s is invalid", workInfo.GetBundleName().c_str());
685         return false;
686     }
687     if (!CheckExtensionInfos(workInfo, uid)) {
688         WS_HILOGE("workInfo is invalid");
689     }
690     return true;
691 }
692 
CheckCondition(WorkInfo & workInfo)693 bool WorkSchedulerService::CheckCondition(WorkInfo& workInfo)
694 {
695     if (workInfo.GetConditionMap()->size() < 1) {
696         return false;
697     }
698     if (workInfo.GetConditionMap()->count(WorkCondition::Type::TIMER) > 0) {
699         uint32_t time = workInfo.GetConditionMap()->at(WorkCondition::Type::TIMER)->uintVal;
700         string bundleName = workInfo.GetBundleName();
701         std::lock_guard<ffrt::mutex> lock(specialMutex_);
702         if (specialMap_.count(bundleName) > 0) {
703             if (time < specialMap_.at(bundleName)) {
704                 WS_HILOGE("fail, set time:%{public}u must more than %{public}u", time, specialMap_.at(bundleName));
705                 return false;
706             }
707             return true;
708         }
709         if (time < minTimeCycle_) {
710             WS_HILOGE("fail, set time:%{public}u must more than %{public}u", time, minTimeCycle_);
711             return false;
712         }
713     }
714     return true;
715 }
716 
StartWork(const WorkInfo & workInfo)717 int32_t WorkSchedulerService::StartWork(const WorkInfo& workInfo)
718 {
719     HitraceScoped traceScoped(HITRACE_TAG_OHOS, "WorkSchedulerService::StartWork");
720     int32_t timerId = SetTimer();
721     int32_t uid = IPCSkeleton::GetCallingUid();
722     int32_t ret = StartWorkInner(workInfo, uid);
723     CancelTimer(timerId);
724     return ret;
725 }
726 
StartWorkInner(const WorkInfo & workInfo,int32_t uid)727 int32_t WorkSchedulerService::StartWorkInner(const WorkInfo& workInfo, int32_t uid)
728 {
729     WorkInfo workInfo_ = workInfo;
730     if (!ready_) {
731         WS_HILOGE("service is not ready.");
732         return E_SERVICE_NOT_READY;
733     }
734     if (checkBundle_ && !CheckWorkInfo(workInfo_, uid)) {
735         WS_HILOGE("check workInfo failed, bundleName inconsistency.");
736         return E_CHECK_WORKINFO_FAILED;
737     }
738     if (!CheckCondition(workInfo_)) {
739         return E_REPEAT_CYCLE_TIME_ERR;
740     }
741     time_t baseTime;
742     (void)time(&baseTime);
743     workInfo_.RequestBaseTime(baseTime);
744     WS_HILOGD("workInfo %{public}s/%{public}s ID: %{public}d, uid: %{public}d",
745         workInfo_.GetBundleName().c_str(), workInfo_.GetAbilityName().c_str(), workInfo_.GetWorkId(), uid);
746     shared_ptr<WorkStatus> workStatus = make_shared<WorkStatus>(workInfo_, uid);
747     int32_t ret = workPolicyManager_->AddWork(workStatus, uid);
748     if (ret == ERR_OK) {
749         workQueueManager_->AddWork(workStatus);
750         if (workInfo_.IsPersisted()) {
751             std::lock_guard<ffrt::mutex> lock(mutex_);
752             workStatus->workInfo_->RefreshUid(uid);
753             persistedMap_.emplace(workStatus->workId_, workStatus->workInfo_);
754             RefreshPersistedWorks();
755         }
756         GetHandler()->RemoveEvent(WorkEventHandler::CHECK_CONDITION_MSG);
757         GetHandler()->SendEvent(InnerEvent::Get(WorkEventHandler::CHECK_CONDITION_MSG, 0),
758             CHECK_CONDITION_DELAY);
759     }
760     return ret;
761 }
762 
AddWorkInner(WorkInfo & workInfo)763 void WorkSchedulerService::AddWorkInner(WorkInfo& workInfo)
764 {
765     WS_HILOGD("come in");
766     if (workInfo.GetUid() > 0) {
767         shared_ptr<WorkStatus> workStatus = make_shared<WorkStatus>(workInfo, workInfo.GetUid());
768         if (workPolicyManager_->AddWork(workStatus, workInfo.GetUid()) == ERR_OK) {
769             workQueueManager_->AddWork(workStatus);
770         }
771     } else {
772         WS_HILOGE("uid is invalid : %{public}d", workInfo.GetUid());
773     }
774 }
775 
StartWorkForInner(const WorkInfo & workInfo)776 int32_t WorkSchedulerService::StartWorkForInner(const WorkInfo& workInfo)
777 {
778     HitraceScoped traceScoped(HITRACE_TAG_OHOS, "WorkSchedulerService::StartWorkForInner");
779     if (!CheckCallingToken() || !CheckCallingServiceName()) {
780         WS_HILOGE("StartWorkForInner not allowed.");
781         return E_PERMISSION_DENIED;
782     }
783     WorkInfo workInfo_ = workInfo;
784     workInfo_.SetIsInnerApply(true);
785     int32_t timerId = SetTimer();
786     int32_t uid;
787     if (!GetUidByBundleName(workInfo_.GetBundleName(), uid)) {
788         return E_INVALID_PROCESS_NAME;
789     }
790     int32_t ret = StartWorkInner(workInfo, uid);
791     CancelTimer(timerId);
792     return ret;
793 }
794 
StopWork(const WorkInfo & workInfo)795 int32_t WorkSchedulerService::StopWork(const WorkInfo& workInfo)
796 {
797     HitraceScoped traceScoped(HITRACE_TAG_OHOS, "WorkSchedulerService::StopWork");
798     WorkInfo workInfo_ = workInfo;
799     if (!ready_) {
800         WS_HILOGE("service is not ready.");
801         return E_SERVICE_NOT_READY;
802     }
803     int32_t uid = IPCSkeleton::GetCallingUid();
804     if (checkBundle_ && !CheckWorkInfo(workInfo_, uid)) {
805         WS_HILOGE("check workInfo failed, bundleName inconsistency.");
806         return E_CHECK_WORKINFO_FAILED;
807     }
808     shared_ptr<WorkStatus> workStatus = workPolicyManager_->FindWorkStatus(workInfo_, uid);
809     if (workStatus == nullptr) {
810         WS_HILOGE("workStatus is nullptr");
811         return E_WORK_NOT_EXIST_FAILED;
812     }
813     WS_HILOGI("StopWork %{public}s workId:%{public}d", workInfo_.GetBundleName().c_str(), workInfo_.GetWorkId());
814     StopWorkInner(workStatus, uid, false, false);
815     return ERR_OK;
816 }
817 
StopWorkForInner(const WorkInfo & workInfo,bool needCancel)818 int32_t WorkSchedulerService::StopWorkForInner(const WorkInfo& workInfo, bool needCancel)
819 {
820     HitraceScoped traceScoped(HITRACE_TAG_OHOS, "WorkSchedulerService::StopWorkForInner");
821     if (!CheckCallingToken() || !CheckCallingServiceName()) {
822         WS_HILOGE("StopWorkForInner not allowed.");
823         return E_PERMISSION_DENIED;
824     }
825     WorkInfo workInfo_ = workInfo;
826     if (!ready_) {
827         WS_HILOGE("service is not ready.");
828         return E_SERVICE_NOT_READY;
829     }
830     int32_t uid;
831     if (!GetUidByBundleName(workInfo_.GetBundleName(), uid)) {
832         return E_INVALID_PROCESS_NAME;
833     }
834     shared_ptr<WorkStatus> workStatus = workPolicyManager_->FindWorkStatus(workInfo_, uid);
835     if (workStatus == nullptr) {
836         WS_HILOGE("workStatus is nullptr");
837         return E_WORK_NOT_EXIST_FAILED;
838     }
839     WS_HILOGI("StopWorkForInner %{public}s workId:%{public}d",
840         workInfo_.GetBundleName().c_str(), workInfo_.GetWorkId());
841     StopWorkInner(workStatus, uid, needCancel, false);
842     return ERR_OK;
843 }
844 
StopAndCancelWork(const WorkInfo & workInfo)845 int32_t WorkSchedulerService::StopAndCancelWork(const WorkInfo& workInfo)
846 {
847     if (!ready_) {
848         WS_HILOGE("service is not ready.");
849         return E_SERVICE_NOT_READY;
850     }
851     WorkInfo workInfo_ = workInfo;
852     int32_t uid = IPCSkeleton::GetCallingUid();
853     if (checkBundle_ && !CheckWorkInfo(workInfo_, uid)) {
854         WS_HILOGE("check workInfo failed, bundleName inconsistency.");
855         return E_CHECK_WORKINFO_FAILED;
856     }
857     shared_ptr<WorkStatus> workStatus = workPolicyManager_->FindWorkStatus(workInfo_, uid);
858     if (workStatus == nullptr) {
859         WS_HILOGE("workStatus is nullptr");
860         return E_WORK_NOT_EXIST_FAILED;
861     }
862     StopWorkInner(workStatus, uid, true, false);
863     if (workStatus->persisted_) {
864         std::lock_guard<ffrt::mutex> lock(mutex_);
865         persistedMap_.erase(workStatus->workId_);
866         RefreshPersistedWorks();
867     }
868     WS_HILOGI("StopAndCancelWork %{public}s workId:%{public}d",
869         workInfo_.GetBundleName().c_str(), workInfo_.GetWorkId());
870     return ERR_OK;
871 }
872 
StopWorkInner(std::shared_ptr<WorkStatus> workStatus,int32_t uid,const bool needCancel,bool isTimeOut)873 bool WorkSchedulerService::StopWorkInner(std::shared_ptr<WorkStatus> workStatus, int32_t uid,
874     const bool needCancel, bool isTimeOut)
875 {
876     if (workPolicyManager_->StopWork(workStatus, uid, needCancel, isTimeOut)) {
877         workQueueManager_->CancelWork(workStatus);
878     }
879     if (!isTimeOut) {
880         workPolicyManager_->RemoveWatchDog(workStatus);
881     }
882     return true;
883 }
884 
WatchdogTimeOut(std::shared_ptr<WorkStatus> workStatus)885 void WorkSchedulerService::WatchdogTimeOut(std::shared_ptr<WorkStatus> workStatus)
886 {
887     StopWorkInner(workStatus, workStatus->uid_, false, true);
888 }
889 
StopAndClearWorks()890 int32_t WorkSchedulerService::StopAndClearWorks()
891 {
892     HitraceScoped traceScoped(HITRACE_TAG_OHOS, "WorkSchedulerService::StopAndClearWorks");
893     if (!ready_) {
894         WS_HILOGE("service is not ready.");
895         return E_SERVICE_NOT_READY;
896     }
897     StopAndClearWorksByUid(IPCSkeleton::GetCallingUid());
898     return ERR_OK;
899 }
900 
StopAndClearWorksByUid(int32_t uid)901 bool WorkSchedulerService::StopAndClearWorksByUid(int32_t uid)
902 {
903     WS_HILOGD("Stop and clear works by Uid:%{public}d", uid);
904     list<std::shared_ptr<WorkStatus>> allWorks = workPolicyManager_->GetAllWorkStatus(uid);
905     list<std::string> workIdList;
906     std::transform(allWorks.cbegin(), allWorks.cend(), std::back_inserter(workIdList),
907         [](std::shared_ptr<WorkStatus> work) { return work->workId_; });
908     bool ret = workQueueManager_->StopAndClearWorks(allWorks)
909         && workPolicyManager_->StopAndClearWorks(uid);
910     if (ret) {
911         std::lock_guard<ffrt::mutex> lock(mutex_);
912         for (auto workId : workIdList) {
913             if (persistedMap_.count(workId) != 0) {
914                 persistedMap_.erase(workId);
915             }
916         }
917         RefreshPersistedWorks();
918     }
919     return ret;
920 }
921 
IsLastWorkTimeout(int32_t workId,bool & result)922 int32_t WorkSchedulerService::IsLastWorkTimeout(int32_t workId, bool &result)
923 {
924     HitraceScoped traceScoped(HITRACE_TAG_OHOS, "WorkSchedulerService::IsLastWorkTimeout");
925     if (!ready_) {
926         WS_HILOGE("service is not ready.");
927         return E_SERVICE_NOT_READY;
928     }
929     int32_t uid = IPCSkeleton::GetCallingUid();
930     return workPolicyManager_->IsLastWorkTimeout(workId, uid, result);
931 }
932 
OnConditionReady(shared_ptr<vector<shared_ptr<WorkStatus>>> workStatusVector)933 void WorkSchedulerService::OnConditionReady(shared_ptr<vector<shared_ptr<WorkStatus>>> workStatusVector)
934 {
935     workPolicyManager_->OnConditionReady(workStatusVector);
936 }
937 
ObtainAllWorks(std::vector<WorkInfo> & workInfos)938 int32_t WorkSchedulerService::ObtainAllWorks(std::vector<WorkInfo>& workInfos)
939 {
940     HitraceScoped traceScoped(HITRACE_TAG_OHOS, "WorkSchedulerService::ObtainAllWorks");
941     int32_t uid = IPCSkeleton::GetCallingUid();
942     if (!ready_) {
943         WS_HILOGE("service is not ready.");
944         return E_SERVICE_NOT_READY;
945     }
946     workInfos = workPolicyManager_->ObtainAllWorks(uid);
947     return ERR_OK;
948 }
949 
ObtainWorksByUidAndWorkIdForInner(int32_t uid,std::vector<WorkInfo> & workInfos,int32_t workId)950 int32_t WorkSchedulerService::ObtainWorksByUidAndWorkIdForInner(int32_t uid,
951     std::vector<WorkInfo>& workInfos, int32_t workId)
952 {
953     HitraceScoped traceScoped(HITRACE_TAG_OHOS, "WorkSchedulerService::ObtainWorksByUidAndWorkIdForInner");
954     if (!ready_) {
955         WS_HILOGE("service is not ready.");
956         return E_SERVICE_NOT_READY;
957     }
958     if (!CheckCallingToken()) {
959         WS_HILOGE("ObtainWorksByUidAndWorkIdForInner not allowed.");
960         return E_PERMISSION_DENIED;
961     }
962     if (workId != -1) {
963         std::shared_ptr<WorkInfo> workInfoPtr = workPolicyManager_->GetWorkStatus(uid, workId);
964         if (workInfoPtr != nullptr) {
965             workInfos.push_back(*workInfoPtr);
966             return ERR_OK;
967         } else {
968             WS_HILOGE("uid: %{public}d, workId: %{public}d no have task.", uid, workId);
969             return E_WORK_NOT_EXIST_FAILED;
970         }
971     }
972     workInfos = workPolicyManager_->ObtainAllWorks(uid);
973     return ERR_OK;
974 }
975 
GetWorkStatus(int32_t workId,WorkInfo & workInfo)976 int32_t WorkSchedulerService::GetWorkStatus(int32_t workId, WorkInfo& workInfo)
977 {
978     HitraceScoped traceScoped(HITRACE_TAG_OHOS, "WorkSchedulerService::GetWorkStatus");
979     int32_t uid = IPCSkeleton::GetCallingUid();
980     if (!ready_) {
981         WS_HILOGE("service is not ready.");
982         return E_SERVICE_NOT_READY;
983     }
984     std::shared_ptr<WorkInfo> workInfoPtr = workPolicyManager_->GetWorkStatus(uid, workId);
985     if (workInfoPtr != nullptr) {
986         workInfo = *workInfoPtr;
987         return ERR_OK;
988     }
989     return E_WORK_NOT_EXIST_FAILED;
990 }
991 
GetAllRunningWorks(std::vector<WorkInfo> & workInfos)992 int32_t WorkSchedulerService::GetAllRunningWorks(std::vector<WorkInfo>& workInfos)
993 {
994     if (!ready_) {
995         WS_HILOGE("service is not ready.");
996         return E_SERVICE_NOT_READY;
997     }
998     if (!CheckProcessName()) {
999         return E_INVALID_PROCESS_NAME;
1000     }
1001     workInfos = workPolicyManager_->GetAllRunningWorks();
1002     return ERR_OK;
1003 }
1004 
UpdateWorkBeforeRealStart(std::shared_ptr<WorkStatus> work)1005 void WorkSchedulerService::UpdateWorkBeforeRealStart(std::shared_ptr<WorkStatus> work)
1006 {
1007     if (work == nullptr) {
1008         return;
1009     }
1010     work->UpdateTimerIfNeed();
1011     if (work->NeedRemove()) {
1012         workQueueManager_->RemoveWork(work);
1013         if (work->persisted_ && !work->IsRepeating()) {
1014             std::lock_guard<ffrt::mutex> lock(mutex_);
1015             persistedMap_.erase(work->workId_);
1016             RefreshPersistedWorks();
1017         }
1018     }
1019 }
1020 
AllowDump()1021 bool WorkSchedulerService::AllowDump()
1022 {
1023     Security::AccessToken::AccessTokenID tokenId = IPCSkeleton::GetFirstTokenID();
1024     int32_t ret = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, "ohos.permission.DUMP");
1025     if (ret != Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
1026         WS_HILOGE("CheckPermission failed");
1027         return false;
1028     }
1029     return true;
1030 }
1031 
DumpProcessForEngMode(std::vector<std::string> & argsInStr,std::string & result)1032 void WorkSchedulerService::DumpProcessForEngMode(std::vector<std::string> &argsInStr, std::string &result)
1033 {
1034     switch (argsInStr.size()) {
1035         case 0:
1036             // hidumper -s said '-h'
1037             DumpUsage(result);
1038             break;
1039         case DUMP_OPTION + 1:
1040             // hidumper -s said '-h' or hidumper -s said '-a'
1041             if (argsInStr[DUMP_OPTION] == "-h") {
1042                 DumpUsage(result);
1043             } else if (argsInStr[DUMP_OPTION] == "-a") {
1044                 DumpAllInfo(result);
1045             } else {
1046                 result.append("Error params.");
1047             }
1048             break;
1049         case DUMP_PARAM_INDEX + 1:
1050             if (argsInStr[DUMP_OPTION] == "-k") {
1051                 string key = argsInStr[DUMP_PARAM_INDEX];
1052                 string value;
1053                 WorkDatashareHelper::GetInstance().GetStringValue(key, value);
1054                 result.append("key: " + key + ", value: " + value);
1055                 break;
1056             }
1057             DumpParamSet(argsInStr[DUMP_OPTION], argsInStr[DUMP_PARAM_INDEX], result);
1058             break;
1059         case DUMP_VALUE_INDEX + 1:
1060             if (argsInStr[DUMP_OPTION] == "-d") {
1061                 EventPublisher eventPublisher;
1062                 eventPublisher.Dump(result, argsInStr[DUMP_PARAM_INDEX], argsInStr[DUMP_VALUE_INDEX]);
1063             } else if (argsInStr[DUMP_OPTION] == "-t") {
1064                 DumpProcessWorks(argsInStr[DUMP_PARAM_INDEX], argsInStr[DUMP_VALUE_INDEX], result);
1065             } else if (argsInStr[DUMP_OPTION] == "-x") {
1066                 DumpRunningWorks(argsInStr[DUMP_PARAM_INDEX], argsInStr[DUMP_VALUE_INDEX], result);
1067             } else if (argsInStr[DUMP_OPTION] == "-s") {
1068                 DumpLoadSaWorks(argsInStr[DUMP_PARAM_INDEX], argsInStr[DUMP_VALUE_INDEX], result);
1069             } else if (argsInStr[DUMP_OPTION] == "-g") {
1070                 DumpGetWorks(argsInStr[DUMP_PARAM_INDEX], argsInStr[DUMP_VALUE_INDEX], result);
1071             } else if (argsInStr[DUMP_OPTION] == "-f") {
1072                 DumpTriggerWork(argsInStr[DUMP_PARAM_INDEX], argsInStr[DUMP_VALUE_INDEX], result);
1073             } else {
1074                 result.append("Error params.");
1075             }
1076             break;
1077         default:
1078             result.append("Error params.");
1079     }
1080 }
1081 
Dump(int32_t fd,const std::vector<std::u16string> & args)1082 int32_t WorkSchedulerService::Dump(int32_t fd, const std::vector<std::u16string>& args)
1083 {
1084     if (!AllowDump()) {
1085         return ERR_OK;
1086     }
1087     std::string result;
1088     if (!ready_) {
1089         WS_HILOGE("service is not ready.");
1090         result.append("service is not ready.");
1091         if (!SaveStringToFd(fd, result)) {
1092             WS_HILOGE("save to fd failed.");
1093         }
1094         return ERR_OK;
1095     }
1096 
1097     std::vector<std::string> argsInStr;
1098     std::transform(args.begin(), args.end(), std::back_inserter(argsInStr),
1099         [](const std::u16string &arg) {
1100         return Str16ToStr8(arg);
1101     });
1102     bool secureMode = OHOS::system::GetBoolParameter("const.security.developermode.state", false);
1103     bool debugable = OHOS::system::GetIntParameter("const.debuggable", 0) == 1;
1104     if (secureMode && !debugable) {
1105         WS_HILOGD("User mode.");
1106         DumpProcessForUserMode(argsInStr, result);
1107     } else if (debugable) {
1108         WS_HILOGD("Eng mode.");
1109         DumpProcessForEngMode(argsInStr, result);
1110     }
1111     if (!SaveStringToFd(fd, result)) {
1112         WS_HILOGE("save to fd failed.");
1113     }
1114     return ERR_OK;
1115 }
1116 
DumpProcessForUserMode(std::vector<std::string> & argsInStr,std::string & result)1117 void WorkSchedulerService::DumpProcessForUserMode(std::vector<std::string> &argsInStr, std::string &result)
1118 {
1119     if (argsInStr.size() == (DUMP_VALUE_INDEX + 1) && argsInStr[DUMP_OPTION] == "-t") {
1120         DumpProcessWorks(argsInStr[DUMP_PARAM_INDEX], argsInStr[DUMP_VALUE_INDEX], result);
1121     } else if (argsInStr.size() == (DUMP_VALUE_INDEX + 1) && argsInStr[DUMP_OPTION] == "-s") {
1122         DumpLoadSaWorks(argsInStr[DUMP_PARAM_INDEX], argsInStr[DUMP_VALUE_INDEX], result);
1123     }
1124 }
1125 
DumpUsage(std::string & result)1126 void WorkSchedulerService::DumpUsage(std::string &result)
1127 {
1128     result.append("usage: workscheduler dump [<options>]\n")
1129         .append("    -h: show the help.\n")
1130         .append("    -a: show all info.\n")
1131         .append("    -d event info: show the event info.\n")
1132         .append("    -d (eventType) (TypeValue): publish the event.\n")
1133         .append("    -t (bundleName) (abilityName): trigger the bundleName all works.\n")
1134         .append("    -f (uId) (workId): trigger the work.\n")
1135         .append("    -x (uid) (option): pause or resume the work.\n")
1136         .append("    -memory (number): set the available memory.\n")
1137         .append("    -watchdog_time (number): set watch dog time, default 120000.\n")
1138         .append("    -repeat_time_min (number): set min repeat cycle time, default 1200000.\n")
1139         .append("    -min_interval (number): set min interval time, set 0 means close test mode.\n")
1140         .append("    -cpu (number): set the usage cpu.\n")
1141         .append("    -count (number): set the max running task count.\n")
1142         .append("    -s (saId) (uId): load or report sa.\n");
1143 }
1144 
DumpAllInfo(std::string & result)1145 void WorkSchedulerService::DumpAllInfo(std::string &result)
1146 {
1147     result.append("================Work Queue Infos================\n");
1148     if (workQueueManager_ != nullptr) {
1149         workQueueManager_->Dump(result);
1150     }
1151     result.append("================Work Policy Infos================\n");
1152     if (workPolicyManager_ != nullptr) {
1153         workPolicyManager_->Dump(result);
1154     }
1155     result.append("================Other Infos================\n");
1156     result.append("Need check bundle:" + std::to_string(checkBundle_) + "\n")
1157         .append("Dump set memory:" + std::to_string(workPolicyManager_->GetDumpSetMemory()) + "\n")
1158         .append("Repeat cycle time min:" + std::to_string(workQueueManager_->GetTimeCycle()) + "\n")
1159         .append("Watchdog time:" + std::to_string(workPolicyManager_->GetWatchdogTime()) + "\n")
1160         .append("Exemption bundle whitelist:" + DumpExemptionBundles() + "\n")
1161         .append("Efficiency Resource whitelist:" + DumpEffiResApplyUid() + "\n");
1162 }
1163 
IsDebugApp(const std::string & bundleName)1164 bool WorkSchedulerService::IsDebugApp(const std::string &bundleName)
1165 {
1166     sptr<ISystemAbilityManager> systemAbilityManager =
1167         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
1168     if (!systemAbilityManager) {
1169         WS_HILOGE("fail to get system ability mgr.");
1170         WorkSchedUtil::HiSysEventException(EventErrorCode::WORK_CHECK, "fail to get system ability manager");
1171         return false;
1172     }
1173     sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
1174     if (!remoteObject) {
1175         WS_HILOGE("fail to get bundle manager proxy.");
1176         WorkSchedUtil::HiSysEventException(EventErrorCode::WORK_CHECK, "fail to get bundle manager proxy");
1177         return false;
1178     }
1179     sptr<IBundleMgr> bundleMgr =  iface_cast<IBundleMgr>(remoteObject);
1180     BundleInfo bundleInfo;
1181     int32_t currentAccountId = WorkSchedUtils::GetCurrentAccountId();
1182     if (bundleMgr->GetBundleInfo(bundleName, BundleFlag::GET_BUNDLE_WITH_ABILITIES,
1183         bundleInfo, currentAccountId)) {
1184         WS_HILOGD("bundleUid : %{public}d , debug : %{public}d.", bundleInfo.uid, bundleInfo.applicationInfo.debug);
1185         return bundleInfo.applicationInfo.debug;
1186     }
1187     WS_HILOGE("Get bundle info failed.");
1188     WorkSchedUtil::HiSysEventException(EventErrorCode::WORK_CHECK, "fail to get bundle info");
1189     return false;
1190 }
1191 
DumpProcessWorks(const std::string & bundleName,const std::string & abilityName,std::string & result)1192 void WorkSchedulerService::DumpProcessWorks(const std::string &bundleName, const std::string &abilityName,
1193     std::string &result)
1194 {
1195     if (bundleName.empty() || abilityName.empty()) {
1196         result.append("param error");
1197         return;
1198     }
1199     workPolicyManager_->DumpCheckIdeWorkToRun(bundleName, abilityName);
1200 }
1201 
DumpTriggerWork(const std::string & uIdStr,const std::string & workIdStr,std::string & result)1202 void WorkSchedulerService::DumpTriggerWork(const std::string& uIdStr, const std::string& workIdStr, std::string& result)
1203 {
1204     if (uIdStr.empty() || workIdStr.empty() || !std::all_of(uIdStr.begin(), uIdStr.end(), ::isdigit)
1205         || !std::all_of(workIdStr.begin(), workIdStr.end(), ::isdigit)) {
1206         result.append("param invalid\n");
1207         return;
1208     }
1209     int32_t uId = std::atoi(uIdStr.c_str());
1210     if (uId <= 0) {
1211         result.append("uIdStr param invalid, uIdStr:" + uIdStr + "\n");
1212         return;
1213     }
1214     int32_t workId = std::atoi(workIdStr.c_str());
1215     if (workId <= 0) {
1216         result.append("workIdStr param invalid, workIdStr:" + workIdStr + "\n");
1217         return;
1218     }
1219     workPolicyManager_->DumpTriggerWork(uId, workId, result);
1220 }
1221 
DumpRunningWorks(const std::string & uidStr,const std::string & option,std::string & result)1222 void WorkSchedulerService::DumpRunningWorks(const std::string &uidStr, const std::string &option, std::string &result)
1223 {
1224     if (!std::all_of(uidStr.begin(), uidStr.end(), ::isdigit) || option.empty()) {
1225         result.append("param error");
1226         return;
1227     }
1228 
1229     int32_t uid = std::atoi(uidStr.c_str());
1230     if (uid == 0) {
1231         result.append("uidStr param error, uidStr:" + uidStr);
1232         return;
1233     }
1234     int32_t ret = ERR_OK;
1235     if (option == "p") {
1236         ret = workPolicyManager_->PauseRunningWorks(uid);
1237     } else if (option == "r") {
1238         ret = workPolicyManager_->ResumePausedWorks(uid);
1239     } else {
1240         result.append("param error");
1241     }
1242 
1243     if (ret != ERR_OK) {
1244         auto iter = paramErrCodeMsgMap.find(ret);
1245         if (iter != paramErrCodeMsgMap.end()) {
1246             result.append("BussinessError:" + iter->second);
1247         }
1248     }
1249 }
1250 
DumpEffiResApplyUid()1251 std::string WorkSchedulerService::DumpEffiResApplyUid()
1252 {
1253     std::lock_guard<ffrt::mutex> lock(whitelistMutex_);
1254     if (whitelist_.empty()) {
1255         return "[]";
1256     }
1257     std::string res {""};
1258     for (auto &it : whitelist_) {
1259         res.append(std::to_string(it) + " ");
1260     }
1261     WS_HILOGD("GetWhiteList  : %{public}s", res.c_str());
1262     return res;
1263 }
1264 
DumpExemptionBundles()1265 std::string WorkSchedulerService::DumpExemptionBundles()
1266 {
1267     if (exemptionBundles_.empty()) {
1268         return "[]";
1269     }
1270 
1271     std::string bundles {""};
1272     for (auto &bundle : exemptionBundles_) {
1273         bundles.append(bundle + " ");
1274     }
1275     return bundles;
1276 }
1277 
DumpParamSet(std::string & key,std::string & value,std::string & result)1278 void WorkSchedulerService::DumpParamSet(std::string &key, std::string &value, std::string &result)
1279 {
1280     if (!std::all_of(value.begin(), value.end(), ::isdigit)) {
1281         result.append("Error params.");
1282         return;
1283     }
1284     if (key == "-memory") {
1285         workPolicyManager_->SetMemoryByDump(std::stoi(value));
1286         result.append("Set memory success.");
1287     } else if (key == "-watchdog_time") {
1288         workPolicyManager_->SetWatchdogTimeByDump(std::stoi(value));
1289         result.append("Set watchdog time success.");
1290     } else if (key == "-repeat_time_min") {
1291         workQueueManager_->SetTimeCycle(std::stoi(value));
1292         result.append("Set repeat time min value success.");
1293     } else if (key == "-min_interval") {
1294         workQueueManager_->SetMinIntervalByDump(std::stoi(value));
1295         result.append("Set min interval value success.");
1296     } else if (key == "-cpu") {
1297         workPolicyManager_->SetCpuUsageByDump(std::stoi(value));
1298         result.append("Set cpu success.");
1299     } else if (key == "-nap") {
1300 #ifdef DEVICE_STANDBY_ENABLE
1301         standbyStateObserver_->OnDeviceIdleMode(std::stoi(value), 0);
1302 #endif
1303     } else if (key == "-count") {
1304         workPolicyManager_->SetMaxRunningCountByDump(std::stoi(value));
1305         result.append("Set max running task count success.");
1306     } else {
1307         result.append("Error params.");
1308     }
1309 }
1310 
RefreshPersistedWorks()1311 void WorkSchedulerService::RefreshPersistedWorks()
1312 {
1313     nlohmann::json root;
1314     for (auto &it : persistedMap_) {
1315         if (it.second == nullptr) {
1316             WS_HILOGE("workInfo is nullptr");
1317             continue;
1318         }
1319         auto workInfo = it.second;
1320         string data = workInfo->ParseToJsonStr();
1321         const nlohmann::json &workJson = nlohmann::json::parse(data, nullptr, false);
1322         if (!workJson.is_discarded()) {
1323             root[it.first] = workJson;
1324         }
1325     }
1326     string result = root.dump(4);
1327     CreateNodeDir(PERSISTED_PATH);
1328     CreateNodeFile();
1329     ofstream fout;
1330     std::string realPath;
1331     if (!WorkSchedUtils::ConvertFullPath(PERSISTED_FILE_PATH, realPath)) {
1332         WS_HILOGE("Get real path failed");
1333         WorkSchedUtil::HiSysEventException(EventErrorCode::SERVICE_INIT, "get real path failed");
1334         return;
1335     }
1336     WS_HILOGD("Refresh path %{private}s", realPath.c_str());
1337     fout.open(realPath, ios::out);
1338     fout<<result.c_str()<<endl;
1339     fout.close();
1340     ReportUserDataSizeEvent();
1341     WS_HILOGD("Refresh persisted works success");
1342 }
1343 
CreateNodeDir(std::string dir)1344 int32_t WorkSchedulerService::CreateNodeDir(std::string dir)
1345 {
1346     WS_HILOGD("Enter");
1347     if (access(dir.c_str(), 0) != ERR_OK) {
1348         int32_t flag = mkdir(dir.c_str(), S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH);
1349         if (flag == ERR_OK) {
1350             WS_HILOGD("Create directory successfully.");
1351         } else {
1352             WS_HILOGE("Fail to create directory, flag: %{public}d", flag);
1353             WorkSchedUtil::HiSysEventException(EventErrorCode::SERVICE_INIT, "fail to create directory");
1354             return flag;
1355         }
1356     } else {
1357         WS_HILOGD("This directory already exists.");
1358     }
1359     return ERR_OK;
1360 }
1361 
CreateNodeFile()1362 int32_t WorkSchedulerService::CreateNodeFile()
1363 {
1364     if (access(PERSISTED_FILE_PATH, 0) != 0) {
1365         FILE *file = fopen(PERSISTED_FILE_PATH, "w+");
1366         if (file == nullptr) {
1367             WS_HILOGE("Fail to open file: %{private}s, errno: %{public}s", PERSISTED_FILE_PATH, strerror(errno));
1368             WorkSchedUtil::HiSysEventException(EventErrorCode::SERVICE_INIT, "fail to open file");
1369             return errno;
1370         }
1371         WS_HILOGI("Open file success.");
1372         int closeResult = fclose(file);
1373         if (closeResult < 0) {
1374             WS_HILOGE("Fail to close file: %{private}s, errno: %{public}s", PERSISTED_FILE_PATH, strerror(errno));
1375             WorkSchedUtil::HiSysEventException(EventErrorCode::SERVICE_INIT, "fail to close file");
1376             return errno;
1377         }
1378     } else {
1379         WS_HILOGD("The file already exists.");
1380     }
1381     return ERR_OK;
1382 }
1383 
UpdateEffiResApplyInfo(int32_t uid,bool isAdd)1384 void WorkSchedulerService::UpdateEffiResApplyInfo(int32_t uid, bool isAdd)
1385 {
1386     std::lock_guard<ffrt::mutex> lock(whitelistMutex_);
1387     if (isAdd) {
1388         whitelist_.emplace(uid);
1389     } else {
1390         whitelist_.erase(uid);
1391     }
1392 }
1393 
CheckEffiResApplyInfo(int32_t uid)1394 bool WorkSchedulerService::CheckEffiResApplyInfo(int32_t uid)
1395 {
1396     std::lock_guard<ffrt::mutex> lock(whitelistMutex_);
1397     return whitelist_.find(uid) != whitelist_.end();
1398 }
1399 
InitDeviceStandyWhitelist()1400 void WorkSchedulerService::InitDeviceStandyWhitelist()
1401 {
1402 #ifdef DEVICE_STANDBY_ENABLE
1403     std::vector<DevStandbyMgr::AllowInfo> allowInfoArray;
1404     auto res = DevStandbyMgr::StandbyServiceClient::GetInstance().GetAllowList(DevStandbyMgr::AllowType::WORK_SCHEDULER,
1405         allowInfoArray, DevStandbyMgr::ReasonCodeEnum::REASON_APP_API);
1406     if (res != ERR_OK) {
1407         WS_HILOGE("GetAllowList fail");
1408         WorkSchedUtil::HiSysEventException(EventErrorCode::SERVICE_INIT, "get device standby white list failed");
1409         return;
1410     }
1411     WS_HILOGI("allowInfoArray size is %{public}d", static_cast<int32_t>(allowInfoArray.size()));
1412     std::list<std::string> tempList = {};
1413     for (const auto& item : allowInfoArray) {
1414         WS_HILOGI("Allow bundleName %{public}s", item.GetName().c_str());
1415         tempList.push_back(item.GetName());
1416     }
1417     DelayedSingleton<DataManager>::GetInstance()->AddDeviceStandyWhitelist(tempList);
1418 #endif
1419 }
1420 
InitDeviceStandyRestrictlist()1421 void WorkSchedulerService::InitDeviceStandyRestrictlist()
1422 {
1423 #ifdef DEVICE_STANDBY_ENABLE
1424     std::vector<DevStandbyMgr::AllowInfo> allowInfoArray;
1425     auto res = DevStandbyMgr::StandbyServiceClient::GetInstance().GetRestrictList(
1426         DevStandbyMgr::AllowType::WORK_SCHEDULER, allowInfoArray, DevStandbyMgr::ReasonCodeEnum::REASON_APP_API);
1427     if (res != ERR_OK) {
1428         WS_HILOGE("GetRestrictlist fail");
1429         WorkSchedUtil::HiSysEventException(EventErrorCode::SERVICE_INIT, "get device standby restrict list failed");
1430         return;
1431     }
1432     WS_HILOGI("restrictInfoArray size is %{public}d", static_cast<int32_t>(allowInfoArray.size()));
1433     std::list<std::string> tempList = {};
1434     for (const auto& item : allowInfoArray) {
1435         WS_HILOGI("Restrict bundleName %{public}s", item.GetName().c_str());
1436         tempList.push_back(item.GetName());
1437     }
1438     DelayedSingleton<DataManager>::GetInstance()->AddDeviceStandyRestrictlist(tempList);
1439 #endif
1440 }
1441 
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)1442 void WorkSchedulerService::OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
1443 {
1444     if (systemAbilityId == DEVICE_USAGE_STATISTICS_SYS_ABILITY_ID) {
1445 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
1446         GroupObserverInit();
1447 #endif
1448     }
1449     if (systemAbilityId == DEVICE_STANDBY_SERVICE_SYSTEM_ABILITY_ID) {
1450         InitDeviceStandyWhitelist();
1451         InitDeviceStandyRestrictlist();
1452         RegisterStandbyStateObserver();
1453     }
1454 }
1455 
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)1456 void WorkSchedulerService::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
1457 {
1458     if (systemAbilityId == DEVICE_STANDBY_SERVICE_SYSTEM_ABILITY_ID) {
1459         DelayedSingleton<DataManager>::GetInstance()->ClearDeviceStandyWhitelist();
1460         DelayedSingleton<DataManager>::GetInstance()->ClearDeviceStandyRestrictlist();
1461         if (!workQueueManager_) {
1462             return;
1463         }
1464         workQueueManager_->OnConditionChanged(WorkCondition::Type::STANDBY,
1465             std::make_shared<DetectorValue>(0, 0, false, std::string()));
1466 #ifdef  DEVICE_STANDBY_ENABLE
1467         std::lock_guard<ffrt::mutex> observerLock(observerMutex_);
1468         standbyStateObserver_ = nullptr;
1469 #endif
1470     } else if (systemAbilityId == DEVICE_USAGE_STATISTICS_SYS_ABILITY_ID) {
1471 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
1472         std::lock_guard<ffrt::mutex> observerLock(observerMutex_);
1473         groupObserver_ = nullptr;
1474         DelayedSingleton<DataManager>::GetInstance()->ClearAllGroup();
1475 #endif
1476     }
1477 }
1478 
1479 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
GroupObserverInit()1480 __attribute__((no_sanitize("cfi"))) void WorkSchedulerService::GroupObserverInit()
1481 {
1482     if (!workQueueManager_) {
1483         return;
1484     }
1485     std::lock_guard<ffrt::mutex> observerLock(observerMutex_);
1486     if (!groupObserver_) {
1487         groupObserver_ = new (std::nothrow) WorkBundleGroupChangeCallback(workQueueManager_);
1488     }
1489     if (groupObserver_ && g_hasGroupObserver != ERR_OK) {
1490         g_hasGroupObserver =
1491             DeviceUsageStats::BundleActiveClient::GetInstance().RegisterAppGroupCallBack(groupObserver_);
1492     }
1493 }
1494 #endif
1495 
RegisterStandbyStateObserver()1496 void WorkSchedulerService::RegisterStandbyStateObserver()
1497 {
1498     if (!workQueueManager_) {
1499         return;
1500     }
1501 #ifdef  DEVICE_STANDBY_ENABLE
1502     std::lock_guard<ffrt::mutex> observerLock(observerMutex_);
1503     if (standbyStateObserver_) {
1504         WS_HILOGD("standbyStateObserver_ is already exist, do not need repeat process.");
1505         return;
1506     }
1507     standbyStateObserver_ = new (std::nothrow) WorkStandbyStateChangeCallback(workQueueManager_);
1508     if (!standbyStateObserver_) {
1509         WorkSchedUtil::HiSysEventException(EventErrorCode::SERVICE_INIT, "create standby state observer failed");
1510         return;
1511     }
1512     standbyStateObserver_->SetSubscriberName(STRATEGY_NAME);
1513     ErrCode ret = DevStandbyMgr::StandbyServiceClient::GetInstance().SubscribeStandbyCallback(standbyStateObserver_);
1514     if (ret != ERR_OK) {
1515         WS_HILOGE("Subscriber standbyStateObserver_ failed.");
1516         WorkSchedUtil::HiSysEventException(EventErrorCode::SERVICE_INIT, "subscribe standby state observer failed");
1517         standbyStateObserver_ = nullptr;
1518     }
1519 #endif
1520 }
1521 
CheckProcessName()1522 bool WorkSchedulerService::CheckProcessName()
1523 {
1524     Security::AccessToken::AccessTokenID tokenId = OHOS::IPCSkeleton::GetCallingTokenID();
1525     Security::AccessToken::NativeTokenInfo callingTokenInfo;
1526     Security::AccessToken::AccessTokenKit::GetNativeTokenInfo(tokenId, callingTokenInfo);
1527     if (WORK_SCHED_NATIVE_OPERATE_CALLER.find(callingTokenInfo.processName) == WORK_SCHED_NATIVE_OPERATE_CALLER.end()) {
1528         WS_HILOGE("check process name illegal access to this interface");
1529         WorkSchedUtil::HiSysEventException(EventErrorCode::TOKEN_CHECK, "illegal process name");
1530         return false;
1531     }
1532     return true;
1533 }
1534 
CheckCallingServiceName()1535 bool WorkSchedulerService::CheckCallingServiceName()
1536 {
1537     Security::AccessToken::AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
1538     Security::AccessToken::NativeTokenInfo callingTokenInfo;
1539     Security::AccessToken::AccessTokenKit::GetNativeTokenInfo(tokenId, callingTokenInfo);
1540     if (WORK_SCHED_SA_CALLER.find(callingTokenInfo.processName) == WORK_SCHED_SA_CALLER.end()) {
1541         WS_HILOGE("check process name illegal");
1542         return false;
1543     }
1544     return true;
1545 }
1546 
PauseRunningWorks(int32_t uid)1547 int32_t WorkSchedulerService::PauseRunningWorks(int32_t uid)
1548 {
1549     WS_HILOGD("pause Running Work Scheduler Work, uid:%{public}d", uid);
1550     if (!CheckProcessName() || !CheckCallingToken()) {
1551         return E_INVALID_PROCESS_NAME;
1552     }
1553 
1554     int32_t ret = workPolicyManager_->PauseRunningWorks(uid);
1555     return ret;
1556 }
1557 
ResumePausedWorks(int32_t uid)1558 int32_t WorkSchedulerService::ResumePausedWorks(int32_t uid)
1559 {
1560     WS_HILOGD("resume Paused Work Scheduler Work, uid:%{public}d", uid);
1561     if (!CheckProcessName() || !CheckCallingToken()) {
1562         return E_INVALID_PROCESS_NAME;
1563     }
1564 
1565     int32_t ret = workPolicyManager_->ResumePausedWorks(uid);
1566     return ret;
1567 }
1568 
TriggerWorkIfConditionReady()1569 void WorkSchedulerService::TriggerWorkIfConditionReady()
1570 {
1571     ConditionChecker checker(workQueueManager_);
1572     checker.CheckAllStatus();
1573 }
1574 
StopDeepIdleWorks()1575 int32_t WorkSchedulerService::StopDeepIdleWorks()
1576 {
1577     if (!ready_) {
1578         WS_HILOGE("service is not ready.");
1579         return E_SERVICE_NOT_READY;
1580     }
1581     std::list<std::shared_ptr<WorkStatus>> works =  workPolicyManager_->GetDeepIdleWorks();
1582     if (works.size() == 0) {
1583         WS_HILOGD("stop work by condition, no matched works");
1584         return ERR_OK;
1585     }
1586 
1587     for (shared_ptr<WorkStatus> workStatus : works) {
1588         WS_HILOGI("stop work by condition, bundleName:%{public}s, workId:%{public}s",
1589             workStatus->bundleName_.c_str(), workStatus->workId_.c_str());
1590         StopWorkInner(workStatus, workStatus->uid_, false, false);
1591         workPolicyManager_->RemoveWatchDog(workStatus);
1592     }
1593     return ERR_OK;
1594 }
1595 
SetWorkSchedulerConfig(const std::string & configData,int32_t sourceType)1596 int32_t WorkSchedulerService::SetWorkSchedulerConfig(const std::string &configData, int32_t sourceType)
1597 {
1598     if (!ready_) {
1599         WS_HILOGE("service is not ready");
1600         return E_SERVICE_NOT_READY;
1601     }
1602     if (!CheckProcessName() || !CheckCallingToken()) {
1603         return E_INVALID_PROCESS_NAME;
1604     }
1605     WS_HILOGD("Set work scheduler configData: %{public}s, sourceType: %{public}d", configData.c_str(), sourceType);
1606     DelayedSingleton<WorkSchedulerConfig>::GetInstance()->InitActiveGroupWhitelist(configData);
1607     return ERR_OK;
1608 }
1609 
IsExemptionBundle(const std::string & checkBundleName)1610 bool WorkSchedulerService::IsExemptionBundle(const std::string& checkBundleName)
1611 {
1612     if (checkBundleName.empty()) {
1613         WS_HILOGE("check exemption bundle error, bundleName is empty");
1614         return false;
1615     }
1616     auto iter = std::find_if(exemptionBundles_.begin(), exemptionBundles_.end(),
1617     [&](const std::string &bundleName) {
1618         return checkBundleName == bundleName;
1619     });
1620     return iter != exemptionBundles_.end();
1621 }
1622 
LoadSa(std::shared_ptr<WorkStatus> workStatus,const std::string & action)1623 bool WorkSchedulerService::LoadSa(std::shared_ptr<WorkStatus> workStatus, const std::string& action)
1624 {
1625     if (!ready_) {
1626         WS_HILOGE("service is not ready.");
1627         return false;
1628     }
1629     sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
1630     if (samgr == nullptr) {
1631         WS_HILOGE("get SA manager failed.");
1632         WorkSchedUtil::HiSysEventException(EventErrorCode::LOAD_SA, "get system ability manager failed");
1633         return false;
1634     }
1635     int32_t saId = workStatus->workInfo_->GetSaId();
1636     bool isResidentSa = workStatus->workInfo_->IsResidentSa();
1637     sptr<IRemoteObject> object = samgr->CheckSystemAbility(saId);
1638     if (isResidentSa && object == nullptr) {
1639         WS_HILOGE("resident SA: %{public}d residentSA:%{public}d does not exist.", saId, isResidentSa);
1640         WorkSchedUtil::HiSysEventException(EventErrorCode::LOAD_SA, "sa dose not exist");
1641         return false;
1642     } else if (!isResidentSa && object == nullptr) {
1643         object = samgr->LoadSystemAbility(saId, TIME_OUT);
1644         if (object == nullptr) {
1645             WS_HILOGE("load SA: %{public}d residentSA:%{public}d failed.", saId, isResidentSa);
1646             WorkSchedUtil::HiSysEventException(EventErrorCode::LOAD_SA, "load system ability failed");
1647             return false;
1648         }
1649         WS_HILOGI("load SA: %{public}d residentSA:%{public}d successed.", saId, isResidentSa);
1650     }
1651     std::unordered_map<std::string, std::string> payload;
1652     payload["action"] = action;
1653     payload["saId"] = std::to_string(saId);
1654     uint32_t type = ResourceSchedule::ResType::RES_TYPE_DEVICE_IDLE;
1655     ResourceSchedule::ResSchedClient::GetInstance().ReportData(type, 0, payload);
1656     WS_HILOGI("Report SA: %{public}d residentSA:%{public}d successed.", saId, isResidentSa);
1657     return true;
1658 }
1659 
DumpLoadSaWorks(const std::string & saIdStr,const std::string & uidStr,std::string & result)1660 void WorkSchedulerService::DumpLoadSaWorks(const std::string &saIdStr, const std::string &uidStr, std::string &result)
1661 {
1662     if (!std::all_of(saIdStr.begin(), saIdStr.end(), ::isdigit) ||
1663         !std::all_of(uidStr.begin(), uidStr.end(), ::isdigit)) {
1664         result.append("param error.");
1665         return;
1666     }
1667     int32_t saId = std::atoi(saIdStr.c_str());
1668     int32_t uid = std::atoi(uidStr.c_str());
1669     if (saId <= 0 || uid <= 0) {
1670         result.append("the parameter is invalid.");
1671         return;
1672     }
1673     auto sa = workPolicyManager_->FindSA(saId, uid);
1674     if (sa == nullptr) {
1675         result.append("the sa does not exist.");
1676         return;
1677     }
1678     if (LoadSa(sa, "hidumper")) {
1679         result.append("load sa success.");
1680         return;
1681     }
1682     result.append("load sa failed.");
1683 }
1684 
DumpGetWorks(const std::string & uidStr,const std::string & workIdStr,std::string & result)1685 void WorkSchedulerService::DumpGetWorks(const std::string &uidStr, const std::string &workIdStr, std::string &result)
1686 {
1687     if (workIdStr.empty() || uidStr.empty()) {
1688         result.append("param error.");
1689         return;
1690     }
1691     int32_t workId = std::atoi(workIdStr.c_str());
1692     int32_t uid = std::atoi(uidStr.c_str());
1693     if (uid < 0) {
1694         result.append("the parameter is invalid.");
1695         return;
1696     }
1697     std::vector<WorkInfo> workInfos;
1698     int32_t ret = ObtainWorksByUidAndWorkIdForInner(uid, workInfos, workId);
1699     if (ret != ERR_OK) {
1700         result.append("get work fail.");
1701         return;
1702     }
1703     if (workInfos.size() == 0) {
1704         result.append("no have workscheduler task.");
1705         return;
1706     }
1707     for (auto &info : workInfos) {
1708         info.Dump(result);
1709     }
1710 }
1711 
HandleDeepIdleMsg()1712 void WorkSchedulerService::HandleDeepIdleMsg()
1713 {
1714     if (!ready_) {
1715         WS_HILOGE("service is not ready.");
1716         return;
1717     }
1718     workQueueManager_->OnConditionChanged(WorkCondition::Type::DEEP_IDLE,
1719         std::make_shared<DetectorValue>(0, 0, true, std::string()));
1720     WorkSchedUtil::HiSysEventStateChanged({"DEEP_IDLE", 1});
1721 }
1722 
IsPreinstalledBundle(const std::string & checkBundleName)1723 bool WorkSchedulerService::IsPreinstalledBundle(const std::string& checkBundleName)
1724 {
1725     if (checkBundleName.empty()) {
1726         WS_HILOGE("check preinstalled bundle error, bundleName is empty");
1727         return false;
1728     }
1729     return preinstalledBundles_.find(checkBundleName) != preinstalledBundles_.end();
1730 }
1731 
StopWorkForSA(int32_t saId)1732 int32_t WorkSchedulerService::StopWorkForSA(int32_t saId)
1733 {
1734     WS_HILOGI("StopWork for SA:%{public}d success", saId);
1735     return ERR_OK;
1736 }
1737 
SetTimer()1738 int32_t WorkSchedulerService::SetTimer()
1739 {
1740 #ifdef HICOLLIE_ENABLE
1741     int32_t idTimer = HiviewDFX::INVALID_ID;
1742     std::string collieName = "WorkSchedulerService:START_WORK";
1743     unsigned int flag = HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY;
1744     auto TimerCallback = [](void *) {
1745         WS_HILOGE("OnRemoteRequest timeout func: START_WORK");
1746     };
1747     idTimer = HiviewDFX::XCollie::GetInstance().SetTimer(
1748         collieName, XCOLLIE_TIMEOUT_SECONDS, TimerCallback, nullptr, flag);
1749     WS_HILOGI("SetTimer id: %{public}d, name: %{public}s.", idTimer, collieName.c_str());
1750     return idTimer;
1751 #else
1752     WS_HILOGD("No HICOLLIE_ENABLE");
1753     return -1;
1754 #endif
1755 }
1756 
CancelTimer(int32_t id)1757 void WorkSchedulerService::CancelTimer(int32_t id)
1758 {
1759 #ifdef HICOLLIE_ENABLE
1760     if (id == HiviewDFX::INVALID_ID) {
1761         return;
1762     }
1763     WS_HILOGI("CancelTimer id: %{public}d.", id);
1764     HiviewDFX::XCollie::GetInstance().CancelTimer(id);
1765 #else
1766     return;
1767 #endif
1768 }
1769 
CheckCallingToken()1770 bool WorkSchedulerService::CheckCallingToken()
1771 {
1772     Security::AccessToken::AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
1773     auto tokenFlag = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
1774     if (tokenFlag == Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE ||
1775         tokenFlag == Security::AccessToken::ATokenTypeEnum::TOKEN_SHELL) {
1776         return true;
1777     }
1778     return false;
1779 }
1780 
GetRemainPartitionSize(const std::string & partitionName)1781 uint64_t GetRemainPartitionSize(const std::string& partitionName)
1782 {
1783     struct statfs stat;
1784     if (statfs(partitionName.c_str(), &stat) != 0) {
1785         return -1;
1786     }
1787     uint64_t blockSize = stat.f_bsize;
1788     uint64_t freeSize = stat.f_bfree * blockSize;
1789     constexpr double units = 1024.0;
1790     return freeSize / (units * units);
1791 }
1792 
GetFileOrFolderSize(const std::vector<std::string> & paths)1793 std::vector<uint64_t> GetFileOrFolderSize(const std::vector<std::string>& paths)
1794 {
1795     std::vector<uint64_t> folderSize;
1796     for (auto path : paths) {
1797         folderSize.emplace_back(OHOS::GetFolderSize(path));
1798     }
1799     return folderSize;
1800 }
1801 
ReportUserDataSizeEvent()1802 void WorkSchedulerService::ReportUserDataSizeEvent()
1803 {
1804     std::vector<std::string> paths = {
1805         "/data/service/el1/public/WorkScheduler/"
1806     };
1807     uint64_t remainPartitionSize = GetRemainPartitionSize("/data");
1808     std::vector<uint64_t> folderSize = GetFileOrFolderSize(paths);
1809     HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::FILEMANAGEMENT, "USER_DATA_SIZE",
1810         HiviewDFX::HiSysEvent::EventType::STATISTIC,
1811         "COMPONENT_NAME", "work_scheduler",
1812         "PARTITION_NAME", "/data",
1813         "REMAIN_PARTITION_SIZE", remainPartitionSize,
1814         "FILE_OR_FOLDER_PATH", paths,
1815         "FILE_OR_FOLDER_SIZE", folderSize);
1816 }
1817 } // namespace WorkScheduler
1818 } // namespace OHOS
1819