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