1 /*
2 * Copyright (c) 2022 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
22 #include <dirent.h>
23 #include <fcntl.h>
24 #include <file_ex.h>
25 #include <if_system_ability_manager.h>
26 #include <ipc_skeleton.h>
27 #include <iservice_registry.h>
28 #include <string_ex.h>
29 #include <system_ability_definition.h>
30 #include <sys/stat.h>
31 #include <unistd.h>
32
33 #include "bundle_mgr_proxy.h"
34 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
35 #include "bundle_active_client.h"
36 #endif
37 #include "conditions/battery_level_listener.h"
38 #include "conditions/battery_status_listener.h"
39 #include "conditions/charger_listener.h"
40 #include "conditions/network_listener.h"
41 #include "conditions/storage_listener.h"
42 #include "conditions/timer_listener.h"
43 #include "conditions/group_listener.h"
44 #include "event_publisher.h"
45 #include "json/json.h"
46 #include "policy/app_data_clear_listener.h"
47 #include "policy/app_removed_listener.h"
48 #include "policy/memory_policy.h"
49 #include "policy/thermal_policy.h"
50 #ifdef RESOURCESCHEDULE_BGTASKMGR_ENABLE
51 #include "scheduler_bg_task_subscriber.h"
52 #include "background_task_mgr_helper.h"
53 #include "resource_type.h"
54 #endif
55 #include "work_scheduler_connection.h"
56 #include "work_bundle_group_change_callback.h"
57 #include "work_sched_errors.h"
58 #include "work_sched_hilog.h"
59 #include "work_sched_utils.h"
60
61 using namespace std;
62 using namespace OHOS::AppExecFwk;
63
64 namespace OHOS {
65 namespace WorkScheduler {
66 namespace {
67 const std::string WORKSCHEDULER_SERVICE_NAME = "WorkSchedulerService";
68 auto instance = DelayedSpSingleton<WorkSchedulerService>::GetInstance();
69 auto wss = instance.GetRefPtr();
70 const bool G_REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(wss);
71 const int32_t INIT_DELAY = 2 * 1000;
72 const int32_t MAX_BUFFER = 2048;
73 const int32_t DUMP_OPTION = 0;
74 const int32_t DUMP_PARAM_INDEX = 1;
75 const int32_t DUMP_VALUE_INDEX = 2;
76 const char* g_persistedFilePath = "/data/service/el1/public/WorkScheduler/persisted_work";
77 const char* g_persistedPath = "/data/service/el1/public/WorkScheduler";
78 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
79 static int g_hasGroupObserver = -1;
80 #endif
81 }
82
WorkSchedulerService()83 WorkSchedulerService::WorkSchedulerService() : SystemAbility(WORK_SCHEDULE_SERVICE_ID, true) {}
84
~WorkSchedulerService()85 WorkSchedulerService::~WorkSchedulerService() {}
86
OnStart()87 void WorkSchedulerService::OnStart()
88 {
89 if (ready_) {
90 WS_HILOGI("OnStart is ready, nothing to do.");
91 return;
92 }
93
94 // Init handler.
95 if (!eventRunner_) {
96 eventRunner_ = AppExecFwk::EventRunner::Create(WORKSCHEDULER_SERVICE_NAME);
97 }
98 if (eventRunner_ == nullptr) {
99 WS_HILOGE("Init failed due to create EventRunner");
100 return;
101 }
102 handler_ = std::make_shared<WorkEventHandler>(eventRunner_, wss);
103
104 // Try to init.
105 Init();
106 WS_HILOGD("On start success.");
107 }
108
IsBaseAbilityReady()109 bool WorkSchedulerService::IsBaseAbilityReady()
110 {
111 sptr<ISystemAbilityManager> systemAbilityManager
112 = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
113 if (systemAbilityManager == nullptr
114 || systemAbilityManager->CheckSystemAbility(APP_MGR_SERVICE_ID) == nullptr
115 || systemAbilityManager->CheckSystemAbility(COMMON_EVENT_SERVICE_ID) == nullptr
116 || systemAbilityManager->CheckSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID) == nullptr
117 || systemAbilityManager->CheckSystemAbility(BACKGROUND_TASK_MANAGER_SERVICE_ID) == nullptr) {
118 return false;
119 }
120 return true;
121 }
122
InitPersisted()123 void WorkSchedulerService::InitPersisted()
124 {
125 WS_HILOGD("init persisted work");
126 list<shared_ptr<WorkInfo>> persistedWorks = ReadPersistedWorks();
127 for (auto it : persistedWorks) {
128 WS_HILOGD("get persisted work, id: %{public}d", it->GetWorkId());
129 InitPersistedWork(*it);
130 }
131 }
132
ReadPersistedWorks()133 list<shared_ptr<WorkInfo>> WorkSchedulerService::ReadPersistedWorks()
134 {
135 list<shared_ptr<WorkInfo>> workInfos;
136 ifstream fin;
137 std::string realPath;
138 if (!WorkSchedUtils::ConvertFullPath(g_persistedFilePath, realPath)) {
139 WS_HILOGE("Get real path failed");
140 return workInfos;
141 }
142 WS_HILOGD("Read from %{public}s", realPath.c_str());
143 fin.open(realPath, ios::in);
144 if (!fin.is_open()) {
145 WS_HILOGE("cannot open file %{public}s", realPath.c_str());
146 return workInfos;
147 }
148 char buffer[MAX_BUFFER];
149 ostringstream os;
150 while (fin.getline(buffer, MAX_BUFFER)) {
151 os << buffer;
152 }
153 string data = os.str();
154 JSONCPP_STRING errs;
155 Json::Value root;
156 Json::CharReaderBuilder readerBuilder;
157 const unique_ptr<Json::CharReader> jsonReader(readerBuilder.newCharReader());
158 bool res = jsonReader->parse(data.c_str(), data.c_str() + data.length(), &root, &errs);
159 fin.close();
160 if (!res || !errs.empty()) {
161 return workInfos;
162 }
163 for (auto it : root.getMemberNames()) {
164 Json::Value workJson = root[it];
165 shared_ptr<WorkInfo> workInfo = make_shared<WorkInfo>();
166 if (workInfo->ParseFromJson(workJson)) {
167 workInfos.emplace_back(workInfo);
168 }
169 }
170 return workInfos;
171 }
172
OnStop()173 void WorkSchedulerService::OnStop()
174 {
175 WS_HILOGI("stop service.");
176 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
177 DeviceUsageStats::BundleActiveClient::GetInstance().UnRegisterAppGroupCallBack(groupObserver_);
178 groupObserver_ = nullptr;
179 g_hasGroupObserver = -1;
180 #endif
181 #ifdef RESOURCESCHEDULE_BGTASKMGR_ENABLE
182 ErrCode ret = BackgroundTaskMgr::BackgroundTaskMgrHelper::UnsubscribeBackgroundTask(*subscriber_);
183 if (ret != ERR_OK) {
184 WS_HILOGE("unscribe bgtask failed.");
185 }
186 subscriber_.reset();
187 #endif
188 eventRunner_.reset();
189 handler_.reset();
190 ready_ = false;
191 }
192
Init()193 bool WorkSchedulerService::Init()
194 {
195 if (!IsBaseAbilityReady()) {
196 WS_HILOGE("request system service is not ready yet!");
197 GetHandler()->SendEvent(InnerEvent::Get(WorkEventHandler::SERVICE_INIT_MSG, 0), INIT_DELAY);
198 return false;
199 }
200 WorkQueueManagerInit();
201 if (!WorkPolicyManagerInit()) {
202 WS_HILOGE("init failed due to work policy manager init.");
203 return false;
204 }
205 InitPersisted();
206 if (!Publish(wss)) {
207 WS_HILOGE("OnStart register to system ability manager failed!");
208 return false;
209 }
210 WS_HILOGI("start init background task subscriber!");
211 if (!InitBgTaskSubscriber()) {
212 WS_HILOGE("subscribe background task failed!");
213 return false;
214 }
215 checkBundle_ = true;
216 ready_ = true;
217 WS_HILOGI("init success.");
218 return true;
219 }
220
InitBgTaskSubscriber()221 bool WorkSchedulerService::InitBgTaskSubscriber()
222 {
223 #ifdef RESOURCESCHEDULE_BGTASKMGR_ENABLE
224 subscriber_ = make_shared<SchedulerBgTaskSubscriber>();
225 ErrCode ret = BackgroundTaskMgr::BackgroundTaskMgrHelper::SubscribeBackgroundTask(*subscriber_);
226 if (ret != ERR_OK) {
227 WS_HILOGE("SubscribeBackgroundTask failed.");
228 return false;
229 }
230 this->QueryResAppliedUid();
231 WS_HILOGD("subscribe background TASK success!");
232 #endif
233 return true;
234 }
235
QueryResAppliedUid()236 ErrCode WorkSchedulerService::QueryResAppliedUid()
237 {
238 #ifdef RESOURCESCHEDULE_BGTASKMGR_ENABLE
239 std::vector<std::shared_ptr<BackgroundTaskMgr::ResourceCallbackInfo>> appList;
240 std::vector<std::shared_ptr<BackgroundTaskMgr::ResourceCallbackInfo>> procList;
241 ErrCode result = BackgroundTaskMgr::BackgroundTaskMgrHelper::GetEfficiencyResourcesInfos(appList, procList);
242 if (result != ERR_OK) {
243 WS_HILOGE("failed to GetEfficiencyResourcesInfos, errcode: %{public}d", result);
244 return result;
245 }
246 for (const auto& info : appList) {
247 if ((info->GetResourceNumber() & BackgroundTaskMgr::ResourceType::WORK_SCHEDULER) != 0) {
248 whitelist_.emplace(info->GetUid());
249 }
250 }
251 for (const auto& info : procList) {
252 if ((info->GetResourceNumber() & BackgroundTaskMgr::ResourceType::WORK_SCHEDULER) != 0) {
253 whitelist_.emplace(info->GetUid());
254 }
255 }
256 WS_HILOGI("get efficiency resources infos succeed.");
257 #endif
258 return ERR_OK;
259 }
260
WorkQueueManagerInit()261 void WorkSchedulerService::WorkQueueManagerInit()
262 {
263 WS_HILOGD("come in");
264 if (workQueueManager_ == nullptr) {
265 workQueueManager_ = make_shared<WorkQueueManager>(wss);
266 }
267
268 auto networkListener = make_shared<NetworkListener>(workQueueManager_);
269 auto chargerListener = make_shared<ChargerListener>(workQueueManager_);
270 auto batteryStatusListener = make_shared<BatteryStatusListener>(workQueueManager_);
271 auto batteryLevelListener = make_shared<BatteryLevelListener>(workQueueManager_);
272 auto storageListener = make_shared<StorageListener>(workQueueManager_);
273 auto timerListener = make_shared<TimerListener>(workQueueManager_);
274 auto groupListener = make_shared<GroupListener>(workQueueManager_);
275
276 workQueueManager_->AddListener(WorkCondition::Type::NETWORK, networkListener);
277 workQueueManager_->AddListener(WorkCondition::Type::CHARGER, chargerListener);
278 workQueueManager_->AddListener(WorkCondition::Type::BATTERY_STATUS, batteryStatusListener);
279 workQueueManager_->AddListener(WorkCondition::Type::BATTERY_LEVEL, batteryLevelListener);
280 workQueueManager_->AddListener(WorkCondition::Type::STORAGE, storageListener);
281 workQueueManager_->AddListener(WorkCondition::Type::TIMER, timerListener);
282 workQueueManager_->AddListener(WorkCondition::Type::GROUP, groupListener);
283
284 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
285 GroupObserverInit();
286 #endif
287 }
288
WorkPolicyManagerInit()289 bool WorkSchedulerService::WorkPolicyManagerInit()
290 {
291 WS_HILOGD("come in");
292 if (workPolicyManager_ == nullptr) {
293 workPolicyManager_ = make_shared<WorkPolicyManager>(wss);
294 }
295 if (!workPolicyManager_->Init()) {
296 WS_HILOGE("work policy manager init failed!");
297 return false;
298 }
299
300 auto thermalFilter = make_shared<ThermalPolicy>(workPolicyManager_);
301 auto memoryFilter = make_shared<MemoryPolicy>(workPolicyManager_);
302 workPolicyManager_->AddPolicyFilter(thermalFilter);
303 workPolicyManager_->AddPolicyFilter(memoryFilter);
304
305 auto appRemoveListener = make_shared<AppRemovedListener>(workPolicyManager_);
306 workPolicyManager_->AddAppRemoveListener(appRemoveListener);
307
308 auto appDataClearListener = make_shared<AppDataClearListener>(workPolicyManager_);
309 workPolicyManager_->AddAppDataClearListener(appDataClearListener);
310
311 WS_HILOGI("work policy manager init success.");
312 return true;
313 }
314
CheckWorkInfo(WorkInfo & workInfo,int32_t & uid)315 bool WorkSchedulerService::CheckWorkInfo(WorkInfo &workInfo, int32_t &uid)
316 {
317 sptr<ISystemAbilityManager> systemAbilityManager =
318 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
319 if (!systemAbilityManager) {
320 WS_HILOGE("fail to get system ability mgr.");
321 return false;
322 }
323 sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
324 if (!remoteObject) {
325 WS_HILOGE("fail to get bundle manager proxy.");
326 return false;
327 }
328 sptr<IBundleMgr> bundleMgr = iface_cast<IBundleMgr>(remoteObject);
329 BundleInfo bundleInfo;
330 int32_t currentAccountId = WorkSchedUtils::GetCurrentAccountId();
331 std::string bundleName = workInfo.GetBundleName();
332 WS_HILOGD("check work info currentAccountId : %{public}d, bundleName : %{public}s.",
333 currentAccountId, bundleName.c_str());
334 if (bundleMgr->GetBundleInfo(bundleName, BundleFlag::GET_BUNDLE_WITH_ABILITIES,
335 bundleInfo, currentAccountId)) {
336 WS_HILOGD("bundleUid : %{public}d , uid : %{public}d.", bundleInfo.uid, uid);
337 return bundleInfo.uid == uid;
338 }
339 WS_HILOGE("Get bundle info failed.");
340 return false;
341 }
342
CheckCondition(WorkInfo & workInfo)343 bool WorkSchedulerService::CheckCondition(WorkInfo& workInfo)
344 {
345 if (workInfo.GetConditionMap()->size() < 1) {
346 return false;
347 }
348 if (workInfo.GetConditionMap()->count(WorkCondition::Type::TIMER) > 0) {
349 uint32_t time = workInfo.GetConditionMap()->at(WorkCondition::Type::TIMER)->uintVal;
350 if (time < workQueueManager_->GetTimeCycle()) {
351 WS_HILOGE("fail, set time:%{public}u must more than %{public}u", time,
352 workQueueManager_->GetTimeCycle());
353 return false;
354 }
355 }
356 return true;
357 }
358
StartWork(WorkInfo & workInfo)359 int32_t WorkSchedulerService::StartWork(WorkInfo& workInfo)
360 {
361 if (!ready_) {
362 WS_HILOGE("service is not ready.");
363 return E_SERVICE_NOT_READY;
364 }
365 int32_t uid = IPCSkeleton::GetCallingUid();
366 if (checkBundle_ && !CheckWorkInfo(workInfo, uid)) {
367 return E_CHECK_WORKINFO_FAILED;
368 }
369 if (!CheckCondition(workInfo)) {
370 return E_REPEAT_CYCLE_TIME_ERR;
371 }
372 WS_HILOGD("workInfo %{public}s/%{public}s ID: %{public}d, uid: %{public}d",
373 workInfo.GetBundleName().c_str(), workInfo.GetAbilityName().c_str(), workInfo.GetWorkId(), uid);
374 shared_ptr<WorkStatus> workStatus = make_shared<WorkStatus>(workInfo, uid);
375 int32_t ret = workPolicyManager_->AddWork(workStatus, uid);
376 if (ret == ERR_OK) {
377 workQueueManager_->AddWork(workStatus);
378 if (workInfo.IsPersisted()) {
379 std::lock_guard<std::mutex> lock(mutex_);
380 std::shared_ptr<WorkInfo> persistedInfo = make_shared<WorkInfo>(workInfo);
381 persistedInfo->RefreshUid(uid);
382 persistedMap_.emplace(workStatus->workId_, persistedInfo);
383 RefreshPersistedWorks();
384 }
385 }
386 return ret;
387 }
388
InitPersistedWork(WorkInfo & workInfo)389 void WorkSchedulerService::InitPersistedWork(WorkInfo& workInfo)
390 {
391 WS_HILOGD("come in");
392 if (workInfo.GetUid() > 0) {
393 shared_ptr<WorkStatus> workStatus = make_shared<WorkStatus>(workInfo, workInfo.GetUid());
394 if (workPolicyManager_->AddWork(workStatus, workInfo.GetUid())) {
395 workQueueManager_->AddWork(workStatus);
396 }
397 } else {
398 WS_HILOGE("uid is invalid : %{public}d", workInfo.GetUid());
399 }
400 }
401
StopWork(WorkInfo & workInfo)402 int32_t WorkSchedulerService::StopWork(WorkInfo& workInfo)
403 {
404 if (!ready_) {
405 WS_HILOGE("service is not ready.");
406 return E_SERVICE_NOT_READY;
407 }
408 int32_t uid = IPCSkeleton::GetCallingUid();
409 if (checkBundle_ && !CheckWorkInfo(workInfo, uid)) {
410 return E_CHECK_WORKINFO_FAILED;
411 }
412 shared_ptr<WorkStatus> workStatus = workPolicyManager_->FindWorkStatus(workInfo, uid);
413 if (workStatus == nullptr) {
414 WS_HILOGE("workStatus is nullptr");
415 return E_WORK_NOT_EXIST_FAILED;
416 }
417 StopWorkInner(workStatus, uid, false, false);
418 return ERR_OK;
419 }
420
StopAndCancelWork(WorkInfo & workInfo)421 int32_t WorkSchedulerService::StopAndCancelWork(WorkInfo& workInfo)
422 {
423 if (!ready_) {
424 WS_HILOGE("service is not ready.");
425 return E_SERVICE_NOT_READY;
426 }
427 int32_t uid = IPCSkeleton::GetCallingUid();
428 if (checkBundle_ && !CheckWorkInfo(workInfo, uid)) {
429 return E_CHECK_WORKINFO_FAILED;
430 }
431 shared_ptr<WorkStatus> workStatus = workPolicyManager_->FindWorkStatus(workInfo, uid);
432 if (workStatus == nullptr) {
433 WS_HILOGE("workStatus is nullptr");
434 return E_WORK_NOT_EXIST_FAILED;
435 }
436 StopWorkInner(workStatus, uid, true, false);
437 if (workStatus->persisted_) {
438 std::lock_guard<std::mutex> lock(mutex_);
439 persistedMap_.erase(workStatus->workId_);
440 RefreshPersistedWorks();
441 }
442 return ERR_OK;
443 }
444
StopWorkInner(std::shared_ptr<WorkStatus> workStatus,int32_t uid,const bool needCancel,bool isTimeOut)445 bool WorkSchedulerService::StopWorkInner(std::shared_ptr<WorkStatus> workStatus, int32_t uid,
446 const bool needCancel, bool isTimeOut)
447 {
448 if (workPolicyManager_->StopWork(workStatus, uid, needCancel, isTimeOut)) {
449 workQueueManager_->CancelWork(workStatus);
450 }
451 return true;
452 }
453
WatchdogTimeOut(std::shared_ptr<WorkStatus> workStatus)454 void WorkSchedulerService::WatchdogTimeOut(std::shared_ptr<WorkStatus> workStatus)
455 {
456 StopWorkInner(workStatus, workStatus->uid_, false, true);
457 }
458
StopAndClearWorks()459 int32_t WorkSchedulerService::StopAndClearWorks()
460 {
461 if (!ready_) {
462 WS_HILOGE("service is not ready.");
463 return E_SERVICE_NOT_READY;
464 }
465 StopAndClearWorksByUid(IPCSkeleton::GetCallingUid());
466 return ERR_OK;
467 }
468
StopAndClearWorksByUid(int32_t uid)469 bool WorkSchedulerService::StopAndClearWorksByUid(int32_t uid)
470 {
471 WS_HILOGD("Stop and clear works by Uid:%{public}d", uid);
472 list<std::shared_ptr<WorkStatus>> allWorks = workPolicyManager_->GetAllWorkStatus(uid);
473 list<std::string> workIdList;
474 std::transform(allWorks.cbegin(), allWorks.cend(), std::back_inserter(workIdList),
475 [](std::shared_ptr<WorkStatus> work) { return work->workId_; });
476 bool ret = workQueueManager_->StopAndClearWorks(allWorks)
477 && workPolicyManager_->StopAndClearWorks(uid);
478 if (ret) {
479 std::lock_guard<std::mutex> lock(mutex_);
480 for (auto workId : workIdList) {
481 if (persistedMap_.count(workId) != 0) {
482 persistedMap_.erase(workId);
483 }
484 }
485 RefreshPersistedWorks();
486 }
487 return ret;
488 }
489
IsLastWorkTimeout(int32_t workId,bool & result)490 int32_t WorkSchedulerService::IsLastWorkTimeout(int32_t workId, bool &result)
491 {
492 if (!ready_) {
493 WS_HILOGE("service is not ready.");
494 return E_SERVICE_NOT_READY;
495 }
496 int32_t uid = IPCSkeleton::GetCallingUid();
497 return workPolicyManager_->IsLastWorkTimeout(workId, uid, result);
498 }
499
OnConditionReady(shared_ptr<vector<shared_ptr<WorkStatus>>> workStatusVector)500 void WorkSchedulerService::OnConditionReady(shared_ptr<vector<shared_ptr<WorkStatus>>> workStatusVector)
501 {
502 workPolicyManager_->OnConditionReady(workStatusVector);
503 }
504
ObtainAllWorks(int32_t & uid,int32_t & pid,std::list<std::shared_ptr<WorkInfo>> & workInfos)505 int32_t WorkSchedulerService::ObtainAllWorks(int32_t &uid, int32_t &pid,
506 std::list<std::shared_ptr<WorkInfo>>& workInfos)
507 {
508 if (!ready_) {
509 WS_HILOGE("service is not ready.");
510 return E_SERVICE_NOT_READY;
511 }
512 workInfos = workPolicyManager_->ObtainAllWorks(uid);
513 return ERR_OK;
514 }
515
GetWorkStatus(int32_t & uid,int32_t & workId,std::shared_ptr<WorkInfo> & workInfo)516 int32_t WorkSchedulerService::GetWorkStatus(int32_t &uid, int32_t &workId, std::shared_ptr<WorkInfo>& workInfo)
517 {
518 if (!ready_) {
519 WS_HILOGE("service is not ready.");
520 workInfo = nullptr;
521 return E_SERVICE_NOT_READY;
522 }
523 workInfo = workPolicyManager_->GetWorkStatus(uid, workId);
524 return ERR_OK;
525 }
526
UpdateWorkBeforeRealStart(std::shared_ptr<WorkStatus> work)527 void WorkSchedulerService::UpdateWorkBeforeRealStart(std::shared_ptr<WorkStatus> work)
528 {
529 if (work == nullptr) {
530 return;
531 }
532 work->UpdateTimerIfNeed();
533 if (work->NeedRemove()) {
534 workQueueManager_->RemoveWork(work);
535 }
536 }
537
Dump(int32_t fd,const std::vector<std::u16string> & args)538 int32_t WorkSchedulerService::Dump(int32_t fd, const std::vector<std::u16string>& args)
539 {
540 std::string result;
541 if (!ready_) {
542 WS_HILOGE("service is not ready.");
543 result.append("service is not ready.");
544 if (!SaveStringToFd(fd, result)) {
545 WS_HILOGE("save to fd failed.");
546 }
547 return ERR_OK;
548 }
549
550 std::vector<std::string> argsInStr;
551 std::transform(args.begin(), args.end(), std::back_inserter(argsInStr),
552 [](const std::u16string &arg) {
553 return Str16ToStr8(arg);
554 });
555
556 switch (argsInStr.size()) {
557 case 0:
558 // hidumper -s said '-h'
559 DumpUsage(result);
560 break;
561 case DUMP_OPTION + 1:
562 // hidumper -s said '-h' or hidumper -s said '-a'
563 if (argsInStr[DUMP_OPTION] == "-h") {
564 DumpUsage(result);
565 } else if (argsInStr[DUMP_OPTION] == "-a") {
566 DumpAllInfo(result);
567 } else {
568 result.append("Error params.");
569 }
570 break;
571 case DUMP_PARAM_INDEX + 1:
572 DumpParamSet(argsInStr[DUMP_OPTION], argsInStr[DUMP_PARAM_INDEX], result);
573 break;
574 case DUMP_VALUE_INDEX + 1:
575 if (argsInStr[DUMP_OPTION] == "-d") {
576 EventPublisher eventPublisher;
577 eventPublisher.Dump(result, argsInStr[DUMP_PARAM_INDEX], argsInStr[DUMP_VALUE_INDEX]);
578 } else {
579 result.append("Error params.");
580 }
581 break;
582 default:
583 result.append("Error params.");
584 }
585
586 if (!SaveStringToFd(fd, result)) {
587 WS_HILOGE("save to fd failed.");
588 }
589 return ERR_OK;
590 }
591
DumpUsage(std::string & result)592 void WorkSchedulerService::DumpUsage(std::string &result)
593 {
594 result.append("usage: workscheduler dump [<options>]\n")
595 .append(" -h: show the help.\n")
596 .append(" -a: show all info.\n")
597 .append(" -d event info: show the event info.\n")
598 .append(" -d (eventType) (TypeValue): publish the event.\n")
599 .append(" -memory (number): set the available memory.\n")
600 .append(" -watchdog_time (number): set watch dog time, default 120000.\n")
601 .append(" -repeat_time_min (number): set min repeat cycle time, default 1200000.\n")
602 .append(" -min_interval (number): set min interval time, set 0 means close test mode.\n");
603 }
604
DumpAllInfo(std::string & result)605 void WorkSchedulerService::DumpAllInfo(std::string &result)
606 {
607 result.append("================Work Queue Infos================\n");
608 if (workQueueManager_ != nullptr) {
609 workQueueManager_->Dump(result);
610 }
611 result.append("================Work Policy Infos================\n");
612 if (workPolicyManager_ != nullptr) {
613 workPolicyManager_->Dump(result);
614 }
615 result.append("================Other Infos================\n");
616 result.append("Need check bundle:" + std::to_string(checkBundle_) + "\n")
617 .append("Dump set memory:" + std::to_string(workPolicyManager_->GetDumpSetMemory()) + "\n")
618 .append("Repeat cycle time min:" + std::to_string(workQueueManager_->GetTimeCycle()) + "\n")
619 .append("Watchdog time:" + std::to_string(workPolicyManager_->GetWatchdogTime()) + "\n")
620 .append("whitelist:" + GetEffiResApplyUid());
621 }
622
GetEffiResApplyUid()623 std::string WorkSchedulerService::GetEffiResApplyUid()
624 {
625 if (whitelist_.empty()) {
626 return "empty";
627 }
628 std::string res {""};
629 for (auto &it : whitelist_) {
630 res.append(std::to_string(it) + " ");
631 }
632 WS_HILOGD("GetWhiteList : %{public}s", res.c_str());
633 return res;
634 }
635
DumpParamSet(std::string & key,std::string & value,std::string & result)636 void WorkSchedulerService::DumpParamSet(std::string &key, std::string &value, std::string &result)
637 {
638 if (key == "-memory") {
639 workPolicyManager_->SetMemoryByDump(std::stoi(value));
640 result.append("Set memory success.");
641 } else if (key == "-watchdog_time") {
642 workPolicyManager_->SetWatchdogTimeByDump(std::stoi(value));
643 result.append("Set watchdog time success.");
644 } else if (key == "-repeat_time_min") {
645 workQueueManager_->SetTimeCycle(std::stoi(value));
646 result.append("Set repeat time min value success.");
647 } else if (key == "-min_interval") {
648 workQueueManager_->SetMinIntervalByDump(std::stoi(value));
649 result.append("Set min interval value success.");
650 } else {
651 result.append("Error params.");
652 }
653 }
654
RefreshPersistedWorks()655 void WorkSchedulerService::RefreshPersistedWorks()
656 {
657 Json::Value root;
658 for (auto &it : persistedMap_) {
659 auto workInfo = it.second;
660 string data = workInfo->ParseToJsonStr();
661 JSONCPP_STRING errs;
662 Json::Value workJson;
663 Json::CharReaderBuilder readerBuilder;
664 const unique_ptr<Json::CharReader> jsonReader(readerBuilder.newCharReader());
665 bool res = jsonReader->parse(data.c_str(), data.c_str() + data.length(), &workJson, &errs);
666 if (res && errs.empty()) {
667 root[it.first] = workJson;
668 }
669 }
670 Json::StreamWriterBuilder writerBuilder;
671 ostringstream os;
672 unique_ptr<Json::StreamWriter> jsonWriter(writerBuilder.newStreamWriter());
673 jsonWriter->write(root, &os);
674 string result = os.str();
675 WS_HILOGD("Work JSON os result %{public}s", result.c_str());
676 CreateNodeDir(g_persistedPath);
677 CreateNodeFile(g_persistedFilePath);
678 ofstream fout;
679 std::string realPath;
680 if (!WorkSchedUtils::ConvertFullPath(g_persistedFilePath, realPath)) {
681 WS_HILOGE("Get real path failed");
682 return;
683 }
684 WS_HILOGD("Refresh path %{public}s", realPath.c_str());
685 fout.open(realPath, ios::out);
686 fout<<result.c_str()<<endl;
687 fout.close();
688 WS_HILOGD("come out");
689 }
690
CreateNodeDir(std::string dir)691 int32_t WorkSchedulerService::CreateNodeDir(std::string dir)
692 {
693 WS_HILOGD("Enter");
694 if (access(dir.c_str(), 0) != ERR_OK) {
695 int32_t flag = mkdir(dir.c_str(), S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH);
696 if (flag == ERR_OK) {
697 WS_HILOGD("Create directory successfully.");
698 } else {
699 WS_HILOGE("Fail to create directory, flag: %{public}d", flag);
700 return flag;
701 }
702 } else {
703 WS_HILOGD("This directory already exists.");
704 }
705 return ERR_OK;
706 }
707
CreateNodeFile(std::string filePath)708 int32_t WorkSchedulerService::CreateNodeFile(std::string filePath)
709 {
710 if (access(filePath.c_str(), 0) != 0) {
711 int32_t fd = open(filePath.c_str(), O_CREAT|O_RDWR, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
712 if (fd < ERR_OK) {
713 WS_HILOGE("Open file fail.");
714 return fd;
715 } else {
716 WS_HILOGE("Open file success.");
717 close(fd);
718 }
719 } else {
720 WS_HILOGE("The file already exists.");
721 }
722 return ERR_OK;
723 }
724
UpdateEffiResApplyInfo(int32_t uid,bool isAdd)725 void WorkSchedulerService::UpdateEffiResApplyInfo(int32_t uid, bool isAdd)
726 {
727 if (isAdd) {
728 whitelist_.emplace(uid);
729 } else {
730 whitelist_.erase(uid);
731 }
732 }
733
CheckEffiResApplyInfo(int32_t uid)734 bool WorkSchedulerService::CheckEffiResApplyInfo(int32_t uid)
735 {
736 return whitelist_.find(uid) != whitelist_.end();
737 }
738
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)739 void WorkSchedulerService::SystemAbilityStatusChangeListener::OnAddSystemAbility
740 (int32_t systemAbilityId, const std::string& deviceId)
741 {
742 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
743 if (systemAbilityId == DEVICE_USAGE_STATISTICS_SYS_ABILITY_ID) {
744 instance->GroupObserverInit();
745 }
746 #endif
747 }
748
749 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
GroupObserverInit()750 void WorkSchedulerService::GroupObserverInit()
751 {
752 if (!groupObserver_) {
753 groupObserver_ = new (std::nothrow) WorkBundleGroupChangeCallback(workQueueManager_);
754 }
755 if (groupObserver_ && g_hasGroupObserver != ERR_OK) {
756 g_hasGroupObserver =
757 DeviceUsageStats::BundleActiveClient::GetInstance().RegisterAppGroupCallBack(groupObserver_);
758 }
759 }
760 #endif
761 } // namespace WorkScheduler
762 } // namespace OHOS