• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     std::lock_guard<std::mutex> lock(whitelistMutex_);
247     for (const auto& info : appList) {
248         if ((info->GetResourceNumber() & BackgroundTaskMgr::ResourceType::WORK_SCHEDULER) != 0) {
249             whitelist_.emplace(info->GetUid());
250         }
251     }
252     for (const auto& info : procList) {
253         if ((info->GetResourceNumber() & BackgroundTaskMgr::ResourceType::WORK_SCHEDULER) != 0) {
254             whitelist_.emplace(info->GetUid());
255         }
256     }
257     WS_HILOGI("get efficiency resources infos succeed.");
258 #endif
259     return ERR_OK;
260 }
261 
WorkQueueManagerInit()262 void WorkSchedulerService::WorkQueueManagerInit()
263 {
264     WS_HILOGD("come in");
265     if (workQueueManager_ == nullptr) {
266         workQueueManager_ = make_shared<WorkQueueManager>(wss);
267     }
268 
269     auto networkListener = make_shared<NetworkListener>(workQueueManager_);
270     auto chargerListener = make_shared<ChargerListener>(workQueueManager_);
271     auto batteryStatusListener = make_shared<BatteryStatusListener>(workQueueManager_);
272     auto batteryLevelListener = make_shared<BatteryLevelListener>(workQueueManager_);
273     auto storageListener = make_shared<StorageListener>(workQueueManager_);
274     auto timerListener = make_shared<TimerListener>(workQueueManager_);
275     auto groupListener = make_shared<GroupListener>(workQueueManager_);
276 
277     workQueueManager_->AddListener(WorkCondition::Type::NETWORK, networkListener);
278     workQueueManager_->AddListener(WorkCondition::Type::CHARGER, chargerListener);
279     workQueueManager_->AddListener(WorkCondition::Type::BATTERY_STATUS, batteryStatusListener);
280     workQueueManager_->AddListener(WorkCondition::Type::BATTERY_LEVEL, batteryLevelListener);
281     workQueueManager_->AddListener(WorkCondition::Type::STORAGE, storageListener);
282     workQueueManager_->AddListener(WorkCondition::Type::TIMER, timerListener);
283     workQueueManager_->AddListener(WorkCondition::Type::GROUP, groupListener);
284 
285 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
286     GroupObserverInit();
287 #endif
288 }
289 
WorkPolicyManagerInit()290 bool WorkSchedulerService::WorkPolicyManagerInit()
291 {
292     WS_HILOGD("come in");
293     if (workPolicyManager_ == nullptr) {
294         workPolicyManager_ = make_shared<WorkPolicyManager>(wss);
295     }
296     if (!workPolicyManager_->Init()) {
297         WS_HILOGE("work policy manager init failed!");
298         return false;
299     }
300 
301     auto thermalFilter = make_shared<ThermalPolicy>(workPolicyManager_);
302     auto memoryFilter = make_shared<MemoryPolicy>(workPolicyManager_);
303     workPolicyManager_->AddPolicyFilter(thermalFilter);
304     workPolicyManager_->AddPolicyFilter(memoryFilter);
305 
306     auto appRemoveListener = make_shared<AppRemovedListener>(workPolicyManager_);
307     workPolicyManager_->AddAppRemoveListener(appRemoveListener);
308 
309     auto appDataClearListener = make_shared<AppDataClearListener>(workPolicyManager_);
310     workPolicyManager_->AddAppDataClearListener(appDataClearListener);
311 
312     WS_HILOGI("work policy manager init success.");
313     return true;
314 }
315 
CheckWorkInfo(WorkInfo & workInfo,int32_t & uid)316 bool WorkSchedulerService::CheckWorkInfo(WorkInfo &workInfo, int32_t &uid)
317 {
318     sptr<ISystemAbilityManager> systemAbilityManager =
319         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
320     if (!systemAbilityManager) {
321         WS_HILOGE("fail to get system ability mgr.");
322         return false;
323     }
324     sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
325     if (!remoteObject) {
326         WS_HILOGE("fail to get bundle manager proxy.");
327         return false;
328     }
329     sptr<IBundleMgr> bundleMgr =  iface_cast<IBundleMgr>(remoteObject);
330     BundleInfo bundleInfo;
331     int32_t currentAccountId = WorkSchedUtils::GetCurrentAccountId();
332     std::string bundleName = workInfo.GetBundleName();
333     WS_HILOGD("check work info currentAccountId : %{public}d, bundleName : %{public}s.",
334         currentAccountId, bundleName.c_str());
335     if (bundleMgr->GetBundleInfo(bundleName, BundleFlag::GET_BUNDLE_WITH_ABILITIES,
336         bundleInfo, currentAccountId)) {
337         WS_HILOGD("bundleUid : %{public}d , uid : %{public}d.", bundleInfo.uid, uid);
338         return bundleInfo.uid == uid;
339     }
340     WS_HILOGE("Get bundle info failed.");
341     return false;
342 }
343 
CheckCondition(WorkInfo & workInfo)344 bool WorkSchedulerService::CheckCondition(WorkInfo& workInfo)
345 {
346     if (workInfo.GetConditionMap()->size() < 1) {
347         return false;
348     }
349     if (workInfo.GetConditionMap()->count(WorkCondition::Type::TIMER) > 0) {
350         uint32_t time = workInfo.GetConditionMap()->at(WorkCondition::Type::TIMER)->uintVal;
351         if (time < workQueueManager_->GetTimeCycle()) {
352             WS_HILOGE("fail, set time:%{public}u must more than %{public}u", time,
353                 workQueueManager_->GetTimeCycle());
354             return false;
355         }
356     }
357     return true;
358 }
359 
StartWork(WorkInfo & workInfo)360 int32_t WorkSchedulerService::StartWork(WorkInfo& workInfo)
361 {
362     if (!ready_) {
363         WS_HILOGE("service is not ready.");
364         return E_SERVICE_NOT_READY;
365     }
366     int32_t uid = IPCSkeleton::GetCallingUid();
367     if (checkBundle_ && !CheckWorkInfo(workInfo, uid)) {
368         return E_CHECK_WORKINFO_FAILED;
369     }
370     if (!CheckCondition(workInfo)) {
371         return E_REPEAT_CYCLE_TIME_ERR;
372     }
373     WS_HILOGD("workInfo %{public}s/%{public}s ID: %{public}d, uid: %{public}d",
374         workInfo.GetBundleName().c_str(), workInfo.GetAbilityName().c_str(), workInfo.GetWorkId(), uid);
375     shared_ptr<WorkStatus> workStatus = make_shared<WorkStatus>(workInfo, uid);
376     int32_t ret = workPolicyManager_->AddWork(workStatus, uid);
377     if (ret == ERR_OK) {
378         workQueueManager_->AddWork(workStatus);
379         if (workInfo.IsPersisted()) {
380             std::lock_guard<std::mutex> lock(mutex_);
381             std::shared_ptr<WorkInfo> persistedInfo = make_shared<WorkInfo>(workInfo);
382             persistedInfo->RefreshUid(uid);
383             persistedMap_.emplace(workStatus->workId_, persistedInfo);
384             RefreshPersistedWorks();
385         }
386     }
387     return ret;
388 }
389 
InitPersistedWork(WorkInfo & workInfo)390 void WorkSchedulerService::InitPersistedWork(WorkInfo& workInfo)
391 {
392     WS_HILOGD("come in");
393     if (workInfo.GetUid() > 0) {
394         shared_ptr<WorkStatus> workStatus = make_shared<WorkStatus>(workInfo, workInfo.GetUid());
395         if (workPolicyManager_->AddWork(workStatus, workInfo.GetUid())) {
396             workQueueManager_->AddWork(workStatus);
397         }
398     } else {
399         WS_HILOGE("uid is invalid : %{public}d", workInfo.GetUid());
400     }
401 }
402 
StopWork(WorkInfo & workInfo)403 int32_t WorkSchedulerService::StopWork(WorkInfo& workInfo)
404 {
405     if (!ready_) {
406         WS_HILOGE("service is not ready.");
407         return E_SERVICE_NOT_READY;
408     }
409     int32_t uid = IPCSkeleton::GetCallingUid();
410     if (checkBundle_ && !CheckWorkInfo(workInfo, uid)) {
411         return E_CHECK_WORKINFO_FAILED;
412     }
413     shared_ptr<WorkStatus> workStatus = workPolicyManager_->FindWorkStatus(workInfo, uid);
414     if (workStatus == nullptr) {
415         WS_HILOGE("workStatus is nullptr");
416         return E_WORK_NOT_EXIST_FAILED;
417     }
418     StopWorkInner(workStatus, uid, false, false);
419     return ERR_OK;
420 }
421 
StopAndCancelWork(WorkInfo & workInfo)422 int32_t WorkSchedulerService::StopAndCancelWork(WorkInfo& workInfo)
423 {
424     if (!ready_) {
425         WS_HILOGE("service is not ready.");
426         return E_SERVICE_NOT_READY;
427     }
428     int32_t uid = IPCSkeleton::GetCallingUid();
429     if (checkBundle_ && !CheckWorkInfo(workInfo, uid)) {
430         return E_CHECK_WORKINFO_FAILED;
431     }
432     shared_ptr<WorkStatus> workStatus = workPolicyManager_->FindWorkStatus(workInfo, uid);
433     if (workStatus == nullptr) {
434         WS_HILOGE("workStatus is nullptr");
435         return E_WORK_NOT_EXIST_FAILED;
436     }
437     StopWorkInner(workStatus, uid, true, false);
438     if (workStatus->persisted_) {
439         std::lock_guard<std::mutex> lock(mutex_);
440         persistedMap_.erase(workStatus->workId_);
441         RefreshPersistedWorks();
442     }
443     return ERR_OK;
444 }
445 
StopWorkInner(std::shared_ptr<WorkStatus> workStatus,int32_t uid,const bool needCancel,bool isTimeOut)446 bool WorkSchedulerService::StopWorkInner(std::shared_ptr<WorkStatus> workStatus, int32_t uid,
447     const bool needCancel, bool isTimeOut)
448 {
449     if (workPolicyManager_->StopWork(workStatus, uid, needCancel, isTimeOut)) {
450         workQueueManager_->CancelWork(workStatus);
451     }
452     return true;
453 }
454 
WatchdogTimeOut(std::shared_ptr<WorkStatus> workStatus)455 void WorkSchedulerService::WatchdogTimeOut(std::shared_ptr<WorkStatus> workStatus)
456 {
457     StopWorkInner(workStatus, workStatus->uid_, false, true);
458 }
459 
StopAndClearWorks()460 int32_t WorkSchedulerService::StopAndClearWorks()
461 {
462     if (!ready_) {
463         WS_HILOGE("service is not ready.");
464         return E_SERVICE_NOT_READY;
465     }
466     StopAndClearWorksByUid(IPCSkeleton::GetCallingUid());
467     return ERR_OK;
468 }
469 
StopAndClearWorksByUid(int32_t uid)470 bool WorkSchedulerService::StopAndClearWorksByUid(int32_t uid)
471 {
472     WS_HILOGD("Stop and clear works by Uid:%{public}d", uid);
473     list<std::shared_ptr<WorkStatus>> allWorks = workPolicyManager_->GetAllWorkStatus(uid);
474     list<std::string> workIdList;
475     std::transform(allWorks.cbegin(), allWorks.cend(), std::back_inserter(workIdList),
476         [](std::shared_ptr<WorkStatus> work) { return work->workId_; });
477     bool ret = workQueueManager_->StopAndClearWorks(allWorks)
478         && workPolicyManager_->StopAndClearWorks(uid);
479     if (ret) {
480         std::lock_guard<std::mutex> lock(mutex_);
481         for (auto workId : workIdList) {
482             if (persistedMap_.count(workId) != 0) {
483                 persistedMap_.erase(workId);
484             }
485         }
486         RefreshPersistedWorks();
487     }
488     return ret;
489 }
490 
IsLastWorkTimeout(int32_t workId,bool & result)491 int32_t WorkSchedulerService::IsLastWorkTimeout(int32_t workId, bool &result)
492 {
493     if (!ready_) {
494         WS_HILOGE("service is not ready.");
495         return E_SERVICE_NOT_READY;
496     }
497     int32_t uid = IPCSkeleton::GetCallingUid();
498     return workPolicyManager_->IsLastWorkTimeout(workId, uid, result);
499 }
500 
OnConditionReady(shared_ptr<vector<shared_ptr<WorkStatus>>> workStatusVector)501 void WorkSchedulerService::OnConditionReady(shared_ptr<vector<shared_ptr<WorkStatus>>> workStatusVector)
502 {
503     workPolicyManager_->OnConditionReady(workStatusVector);
504 }
505 
ObtainAllWorks(int32_t & uid,int32_t & pid,std::list<std::shared_ptr<WorkInfo>> & workInfos)506 int32_t WorkSchedulerService::ObtainAllWorks(int32_t &uid, int32_t &pid,
507     std::list<std::shared_ptr<WorkInfo>>& workInfos)
508 {
509     if (!ready_) {
510         WS_HILOGE("service is not ready.");
511         return E_SERVICE_NOT_READY;
512     }
513     workInfos = workPolicyManager_->ObtainAllWorks(uid);
514     return ERR_OK;
515 }
516 
GetWorkStatus(int32_t & uid,int32_t & workId,std::shared_ptr<WorkInfo> & workInfo)517 int32_t WorkSchedulerService::GetWorkStatus(int32_t &uid, int32_t &workId, std::shared_ptr<WorkInfo>& workInfo)
518 {
519     if (!ready_) {
520         WS_HILOGE("service is not ready.");
521         workInfo = nullptr;
522         return E_SERVICE_NOT_READY;
523     }
524     workInfo = workPolicyManager_->GetWorkStatus(uid, workId);
525     return ERR_OK;
526 }
527 
UpdateWorkBeforeRealStart(std::shared_ptr<WorkStatus> work)528 void WorkSchedulerService::UpdateWorkBeforeRealStart(std::shared_ptr<WorkStatus> work)
529 {
530     if (work == nullptr) {
531         return;
532     }
533     work->UpdateTimerIfNeed();
534     if (work->NeedRemove()) {
535         workQueueManager_->RemoveWork(work);
536     }
537 }
538 
Dump(int32_t fd,const std::vector<std::u16string> & args)539 int32_t WorkSchedulerService::Dump(int32_t fd, const std::vector<std::u16string>& args)
540 {
541     std::string result;
542     if (!ready_) {
543         WS_HILOGE("service is not ready.");
544         result.append("service is not ready.");
545         if (!SaveStringToFd(fd, result)) {
546             WS_HILOGE("save to fd failed.");
547         }
548         return ERR_OK;
549     }
550 
551     std::vector<std::string> argsInStr;
552     std::transform(args.begin(), args.end(), std::back_inserter(argsInStr),
553         [](const std::u16string &arg) {
554         return Str16ToStr8(arg);
555     });
556 
557     switch (argsInStr.size()) {
558         case 0:
559             // hidumper -s said '-h'
560             DumpUsage(result);
561             break;
562         case DUMP_OPTION + 1:
563             // hidumper -s said '-h' or hidumper -s said '-a'
564             if (argsInStr[DUMP_OPTION] == "-h") {
565                 DumpUsage(result);
566             } else if (argsInStr[DUMP_OPTION] == "-a") {
567                 DumpAllInfo(result);
568             } else {
569                 result.append("Error params.");
570             }
571             break;
572         case DUMP_PARAM_INDEX + 1:
573             DumpParamSet(argsInStr[DUMP_OPTION], argsInStr[DUMP_PARAM_INDEX], result);
574             break;
575         case DUMP_VALUE_INDEX + 1:
576             if (argsInStr[DUMP_OPTION] == "-d") {
577                 EventPublisher eventPublisher;
578                 eventPublisher.Dump(result, argsInStr[DUMP_PARAM_INDEX], argsInStr[DUMP_VALUE_INDEX]);
579             } else {
580                 result.append("Error params.");
581             }
582             break;
583         default:
584             result.append("Error params.");
585     }
586 
587     if (!SaveStringToFd(fd, result)) {
588         WS_HILOGE("save to fd failed.");
589     }
590     return ERR_OK;
591 }
592 
DumpUsage(std::string & result)593 void WorkSchedulerService::DumpUsage(std::string &result)
594 {
595     result.append("usage: workscheduler dump [<options>]\n")
596         .append("    -h: show the help.\n")
597         .append("    -a: show all info.\n")
598         .append("    -d event info: show the event info.\n")
599         .append("    -d (eventType) (TypeValue): publish the event.\n")
600         .append("    -memory (number): set the available memory.\n")
601         .append("    -watchdog_time (number): set watch dog time, default 120000.\n")
602         .append("    -repeat_time_min (number): set min repeat cycle time, default 1200000.\n")
603         .append("    -min_interval (number): set min interval time, set 0 means close test mode.\n");
604 }
605 
DumpAllInfo(std::string & result)606 void WorkSchedulerService::DumpAllInfo(std::string &result)
607 {
608     result.append("================Work Queue Infos================\n");
609     if (workQueueManager_ != nullptr) {
610         workQueueManager_->Dump(result);
611     }
612     result.append("================Work Policy Infos================\n");
613     if (workPolicyManager_ != nullptr) {
614         workPolicyManager_->Dump(result);
615     }
616     result.append("================Other Infos================\n");
617     result.append("Need check bundle:" + std::to_string(checkBundle_) + "\n")
618         .append("Dump set memory:" + std::to_string(workPolicyManager_->GetDumpSetMemory()) + "\n")
619         .append("Repeat cycle time min:" + std::to_string(workQueueManager_->GetTimeCycle()) + "\n")
620         .append("Watchdog time:" + std::to_string(workPolicyManager_->GetWatchdogTime()) + "\n")
621         .append("whitelist:" + GetEffiResApplyUid());
622 }
623 
GetEffiResApplyUid()624 std::string WorkSchedulerService::GetEffiResApplyUid()
625 {
626     std::lock_guard<std::mutex> lock(whitelistMutex_);
627     if (whitelist_.empty()) {
628         return "empty";
629     }
630     std::string res {""};
631     for (auto &it : whitelist_) {
632         res.append(std::to_string(it) + " ");
633     }
634     WS_HILOGD("GetWhiteList  : %{public}s", res.c_str());
635     return res;
636 }
637 
DumpParamSet(std::string & key,std::string & value,std::string & result)638 void WorkSchedulerService::DumpParamSet(std::string &key, std::string &value, std::string &result)
639 {
640     if (key == "-memory") {
641         workPolicyManager_->SetMemoryByDump(std::stoi(value));
642         result.append("Set memory success.");
643     } else if (key == "-watchdog_time") {
644         workPolicyManager_->SetWatchdogTimeByDump(std::stoi(value));
645         result.append("Set watchdog time success.");
646     } else if (key == "-repeat_time_min") {
647         workQueueManager_->SetTimeCycle(std::stoi(value));
648         result.append("Set repeat time min value success.");
649     } else if (key == "-min_interval") {
650         workQueueManager_->SetMinIntervalByDump(std::stoi(value));
651         result.append("Set min interval value success.");
652     } else {
653         result.append("Error params.");
654     }
655 }
656 
RefreshPersistedWorks()657 void WorkSchedulerService::RefreshPersistedWorks()
658 {
659     Json::Value root;
660     for (auto &it : persistedMap_) {
661         auto workInfo = it.second;
662         string data = workInfo->ParseToJsonStr();
663         JSONCPP_STRING errs;
664         Json::Value workJson;
665         Json::CharReaderBuilder readerBuilder;
666         const unique_ptr<Json::CharReader> jsonReader(readerBuilder.newCharReader());
667         bool res = jsonReader->parse(data.c_str(), data.c_str() + data.length(), &workJson, &errs);
668         if (res && errs.empty()) {
669             root[it.first] = workJson;
670         }
671     }
672     Json::StreamWriterBuilder writerBuilder;
673     ostringstream os;
674     unique_ptr<Json::StreamWriter> jsonWriter(writerBuilder.newStreamWriter());
675     jsonWriter->write(root, &os);
676     string result = os.str();
677     WS_HILOGD("Work JSON os result %{public}s", result.c_str());
678     CreateNodeDir(g_persistedPath);
679     CreateNodeFile(g_persistedFilePath);
680     ofstream fout;
681     std::string realPath;
682     if (!WorkSchedUtils::ConvertFullPath(g_persistedFilePath, realPath)) {
683         WS_HILOGE("Get real path failed");
684         return;
685     }
686     WS_HILOGD("Refresh path %{public}s", realPath.c_str());
687     fout.open(realPath, ios::out);
688     fout<<result.c_str()<<endl;
689     fout.close();
690     WS_HILOGD("come out");
691 }
692 
CreateNodeDir(std::string dir)693 int32_t WorkSchedulerService::CreateNodeDir(std::string dir)
694 {
695     WS_HILOGD("Enter");
696     if (access(dir.c_str(), 0) != ERR_OK) {
697         int32_t flag = mkdir(dir.c_str(), S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH);
698         if (flag == ERR_OK) {
699             WS_HILOGD("Create directory successfully.");
700         } else {
701             WS_HILOGE("Fail to create directory, flag: %{public}d", flag);
702             return flag;
703         }
704     } else {
705         WS_HILOGD("This directory already exists.");
706     }
707     return ERR_OK;
708 }
709 
CreateNodeFile(std::string filePath)710 int32_t WorkSchedulerService::CreateNodeFile(std::string filePath)
711 {
712     if (access(filePath.c_str(), 0) != 0) {
713         int32_t fd = open(filePath.c_str(), O_CREAT|O_RDWR, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
714         if (fd < ERR_OK) {
715             WS_HILOGE("Open file fail.");
716             return fd;
717         } else {
718             WS_HILOGE("Open file success.");
719             close(fd);
720         }
721     } else {
722         WS_HILOGE("The file already exists.");
723     }
724     return ERR_OK;
725 }
726 
UpdateEffiResApplyInfo(int32_t uid,bool isAdd)727 void WorkSchedulerService::UpdateEffiResApplyInfo(int32_t uid, bool isAdd)
728 {
729     std::lock_guard<std::mutex> lock(whitelistMutex_);
730     if (isAdd) {
731         whitelist_.emplace(uid);
732     } else {
733         whitelist_.erase(uid);
734     }
735 }
736 
CheckEffiResApplyInfo(int32_t uid)737 bool WorkSchedulerService::CheckEffiResApplyInfo(int32_t uid)
738 {
739     std::lock_guard<std::mutex> lock(whitelistMutex_);
740     return whitelist_.find(uid) != whitelist_.end();
741 }
742 
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)743 void WorkSchedulerService::SystemAbilityStatusChangeListener::OnAddSystemAbility
744     (int32_t systemAbilityId, const std::string& deviceId)
745 {
746 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
747     if (systemAbilityId == DEVICE_USAGE_STATISTICS_SYS_ABILITY_ID) {
748         instance->GroupObserverInit();
749     }
750 #endif
751 }
752 
753 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
GroupObserverInit()754 void WorkSchedulerService::GroupObserverInit()
755 {
756     if (!workQueueManager_) {
757         return;
758     }
759     if (!groupObserver_) {
760         groupObserver_ = new (std::nothrow) WorkBundleGroupChangeCallback(workQueueManager_);
761     }
762     if (groupObserver_ && g_hasGroupObserver != ERR_OK) {
763         g_hasGroupObserver =
764             DeviceUsageStats::BundleActiveClient::GetInstance().RegisterAppGroupCallBack(groupObserver_);
765     }
766 }
767 #endif
768 } // namespace WorkScheduler
769 } // namespace OHOS