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