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