1 /*
2  * Copyright (c) 2023 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 
16 #include "running_lock_strategy.h"
17 #include <algorithm>
18 #include "standby_service_log.h"
19 #include "system_ability_definition.h"
20 
21 #include "ability_manager_helper.h"
22 #ifdef ENABLE_BACKGROUND_TASK_MGR
23 #include "background_task_helper.h"
24 #endif
25 #include "app_mgr_helper.h"
26 #include "standby_service.h"
27 #ifdef STANDBY_POWER_MANAGER_ENABLE
28 #include "power_mgr_client.h"
29 #endif
30 #ifdef STANDBY_RSS_WORK_SCHEDULER_ENABLE
31 #include "workscheduler_srv_client.h"
32 #endif
33 #include "allow_type.h"
34 #include "standby_state.h"
35 #include "bundle_manager_helper.h"
36 #include "standby_service_impl.h"
37 #include "common_constant.h"
38 
39 namespace OHOS {
40 namespace DevStandbyMgr {
41 namespace {
42 const std::map<std::string, uint8_t> BGTASK_EXEMPTION_FLAG_MAP {
43     {CONTINUOUS_TASK, ExemptionTypeFlag::CONTINUOUS_TASK},
44     {TRANSIENT_TASK, ExemptionTypeFlag::TRANSIENT_TASK},
45     {WORK_SCHEDULER, ExemptionTypeFlag::WORK_SCHEDULER},
46 };
47 }
48 
HandleEvent(const StandbyMessage & message)49 void RunningLockStrategy::HandleEvent(const StandbyMessage& message)
50 {
51     STANDBYSERVICE_LOGD("RunningLockStrategy revceived message %{public}u, action: %{public}s",
52         message.eventId_, message.action_.c_str());
53     switch (message.eventId_) {
54         case StandbyMessageType::ALLOW_LIST_CHANGED:
55             UpdateExemptionList(message);
56             break;
57         case StandbyMessageType::RES_CTRL_CONDITION_CHANGED:
58             UpdateResourceConfig(message);
59             break;
60         case StandbyMessageType::PHASE_TRANSIT:
61             StartProxy(message);
62             break;
63         case StandbyMessageType::STATE_TRANSIT:
64             StopProxy(message);
65             break;
66         case StandbyMessageType::BG_TASK_STATUS_CHANGE:
67             UpdateBgTaskAppStatus(message);
68             break;
69         case StandbyMessageType::PROCESS_STATE_CHANGED:
70             HandleProcessStatusChanged(message);
71             break;
72         case StandbyMessageType::SYS_ABILITY_STATUS_CHANGED:
73             ResetProxyStatus(message);
74             break;
75         default:
76             break;
77     }
78 }
79 
OnCreated()80 ErrCode RunningLockStrategy::OnCreated()
81 {
82     #ifdef STANDBY_POWER_MANAGER_ENABLE
83     PowerMgr::PowerMgrClient::GetInstance().ResetRunningLocks();
84     #endif
85     return ERR_OK;
86 }
87 
OnDestroy()88 ErrCode RunningLockStrategy::OnDestroy()
89 {
90     if (isProxied_ && !isIdleMaintence_) {
91         ProxyAppAndProcess(false);
92     }
93     isProxied_ = false;
94     isIdleMaintence_ = false;
95     return ERR_OK;
96 }
97 
UpdateExemptionList(const StandbyMessage & message)98 ErrCode RunningLockStrategy::UpdateExemptionList(const StandbyMessage& message)
99 {
100     uint32_t allowType = static_cast<uint32_t>(message.want_->GetIntParam("allowType", 0));
101     if ((allowType & AllowType::RUNNING_LOCK) == 0) {
102         STANDBYSERVICE_LOGD("allowType is not running lock, currentType is %{public}d", allowType);
103         return ERR_STANDBY_STRATEGY_NOT_MATCH;
104     }
105     if (!isProxied_) {
106         STANDBYSERVICE_LOGD("current state is not sleep or maintenance, ignore exemption");
107         return ERR_STANDBY_CURRENT_STATE_NOT_MATCH;
108     }
109 
110     // according to message, add flag or remove flag
111     STANDBYSERVICE_LOGI("RunningLockStrategy start update allow list");
112     std::string processName = message.want_->GetStringParam("name");
113     bool added = message.want_->GetBoolParam("added", false);
114     int32_t uid = message.want_->GetIntParam("uid", -1);
115     STANDBYSERVICE_LOGD("%{public}s apply allow, added is %{public}d", processName.c_str(), added);
116     if (added) {
117         AddExemptionFlag(uid, processName, ExemptionTypeFlag::EXEMPTION);
118     } else {
119         RemoveExemptionFlag(uid, processName, ExemptionTypeFlag::EXEMPTION);
120     }
121     return ERR_OK;
122 }
123 
UpdateResourceConfig(const StandbyMessage & message)124 ErrCode RunningLockStrategy::UpdateResourceConfig(const StandbyMessage& message)
125 {
126     StopProxyInner();
127     StartProxyInner();
128     return ERR_OK;
129 }
130 
StartProxy(const StandbyMessage & message)131 ErrCode RunningLockStrategy::StartProxy(const StandbyMessage& message)
132 {
133     if (isProxied_) {
134         STANDBYSERVICE_LOGD("now is proxied, do not need StartProxy, repeat process");
135         return ERR_STANDBY_STRATEGY_STATE_REPEAT;
136     }
137     uint32_t curPhase = static_cast<uint32_t>(message.want_->GetIntParam(CURRENT_PHASE, 0));
138     uint32_t curState = static_cast<uint32_t>(message.want_->GetIntParam(CURRENT_STATE, 0));
139     if ((curState != StandbyState::SLEEP) || (curPhase != SleepStatePhase::APP_RES_DEEP)) {
140         return ERR_STANDBY_CURRENT_STATE_NOT_MATCH;
141     }
142     STANDBYSERVICE_LOGD("start proxy running lock, current state is %{public}d, current phase is %{public}d",
143         curPhase, curPhase);
144     // if enter sleep state and app_res_deep phase, start proxy running lock of applications.
145     if (auto ret = StartProxyInner(); ret != ERR_OK) {
146         return ret;
147     }
148     isProxied_ = true;
149     isIdleMaintence_ = false;
150     return ERR_OK;
151 }
152 
StartProxyInner()153 ErrCode RunningLockStrategy::StartProxyInner()
154 {
155     ClearProxyRecord();
156     if (InitProxiedAppInfo() != ERR_OK || InitNativeProcInfo() != ERR_OK) {
157         STANDBYSERVICE_LOGW("calculate proxied app or native process failed");
158         ClearProxyRecord();
159         return ERR_STRATEGY_DEPENDS_SA_NOT_AVAILABLE;
160     }
161     ProxyAppAndProcess(true);
162     return ERR_OK;
163 }
164 
InitProxiedAppInfo()165 ErrCode RunningLockStrategy::InitProxiedAppInfo()
166 {
167     if (GetAllAppInfos() != ERR_OK || GetAllRunningAppInfo() != ERR_OK) {
168         STANDBYSERVICE_LOGW("failed to get all app info");
169         return ERR_STRATEGY_DEPENDS_SA_NOT_AVAILABLE;
170     }
171     if (GetForegroundApplications() !=ERR_OK || GetBackgroundTaskApp() != ERR_OK ||
172         GetWorkSchedulerTask() != ERR_OK || GetExemptionConfig() != ERR_OK) {
173         return ERR_STRATEGY_DEPENDS_SA_NOT_AVAILABLE;
174     }
175     uidBundleNmeMap_.clear();
176     return ERR_OK;
177 }
178 
GetAllAppInfos()179 ErrCode RunningLockStrategy::GetAllAppInfos()
180 {
181     // get all app and set UNRESTRICTED flag to system app.
182     std::vector<AppExecFwk::ApplicationInfo> applicationInfos {};
183     if (!BundleManagerHelper::GetInstance()->GetApplicationInfos(
184         AppExecFwk::ApplicationFlag::GET_BASIC_APPLICATION_INFO,
185         AppExecFwk::Constants::ALL_USERID, applicationInfos)) {
186         STANDBYSERVICE_LOGW("failed to get all applicationInfos");
187         return ERR_STRATEGY_DEPENDS_SA_NOT_AVAILABLE;
188     }
189     STANDBYSERVICE_LOGD("succeed GetApplicationInfos, size is %{public}d",
190         static_cast<int32_t>(applicationInfos.size()));
191     for (const auto& info : applicationInfos) {
192         uidBundleNmeMap_.emplace(info.uid, info.name);
193         std::string key = std::to_string(info.uid) + "_" + info.name;
194         proxiedAppInfo_.emplace(key, ProxiedProcInfo {info.name, info.uid});
195         // system app have exemption
196         if (info.isSystemApp) {
197             proxiedAppInfo_[key].appExemptionFlag_ |= ExemptionTypeFlag::UNRESTRICTED;
198         }
199     }
200     return ERR_OK;
201 }
202 
GetAllRunningAppInfo()203 ErrCode RunningLockStrategy::GetAllRunningAppInfo()
204 {
205     std::vector<AppExecFwk::RunningProcessInfo> allAppProcessInfos {};
206     if (!AppMgrHelper::GetInstance()->GetAllRunningProcesses(allAppProcessInfos)) {
207         STANDBYSERVICE_LOGE("connect to app manager service failed");
208         return ERR_STRATEGY_DEPENDS_SA_NOT_AVAILABLE;
209     }
210     // get all running proc of app, add them to proxiedAppInfo_.
211     STANDBYSERVICE_LOGI("current running processes size %{public}d", static_cast<int32_t>(allAppProcessInfos.size()));
212     std::set<int> runningUids {};
213     for (const auto& info : allAppProcessInfos) {
214         if (uidBundleNmeMap_.find(info.uid_) == uidBundleNmeMap_.end()) {
215             continue;
216         }
217         runningUids.emplace(info.uid_);
218         std::string key = std::to_string(info.uid_) + "_" + uidBundleNmeMap_[info.uid_];
219         auto iter = proxiedAppInfo_.find(key);
220         if (iter == proxiedAppInfo_.end()) {
221             std::tie(iter, std::ignore) = proxiedAppInfo_.emplace(key,
222                 ProxiedProcInfo {info.processName_, info.uid_});
223         }
224         iter->second.pids_.emplace(info.pid_);
225     }
226     // if app is not running, delete its info from proxiedAppInfo_.
227     for (auto appInfoIter = proxiedAppInfo_.begin(); appInfoIter != proxiedAppInfo_.end();) {
228         if (runningUids.find(appInfoIter->second.uid_) == runningUids.end()) {
229             appInfoIter = proxiedAppInfo_.erase(appInfoIter);
230         } else {
231             ++appInfoIter;
232         }
233     }
234     return ERR_OK;
235 }
236 
GetWorkSchedulerTask()237 ErrCode RunningLockStrategy::GetWorkSchedulerTask()
238 {
239     #ifdef STANDBY_RSS_WORK_SCHEDULER_ENABLE
240     std::list<std::shared_ptr<WorkScheduler::WorkInfo>> workInfos;
241     if (WorkScheduler::WorkSchedulerSrvClient::GetInstance().GetAllRunningWorks(workInfos) != ERR_OK) {
242         return ERR_STRATEGY_DEPENDS_SA_NOT_AVAILABLE;
243     }
244 
245     STANDBYSERVICE_LOGD("GetWorkSchedulerTask succeed, size is %{public}d", static_cast<int32_t>(workInfos.size()));
246     for (const auto& task : workInfos) {
247         std::string key = std::to_string(task->GetUid()) + "_" + task->GetBundleName();
248         if (auto iter = proxiedAppInfo_.find(key); iter != proxiedAppInfo_.end()) {
249             iter->second.appExemptionFlag_ |= ExemptionTypeFlag::WORK_SCHEDULER;
250         }
251     }
252     #endif
253     return ERR_OK;
254 }
255 
GetForegroundApplications()256 ErrCode RunningLockStrategy::GetForegroundApplications()
257 {
258     std::vector<AppExecFwk::AppStateData> fgApps {};
259     if (!AppMgrHelper::GetInstance()->GetForegroundApplications(fgApps)) {
260         STANDBYSERVICE_LOGW("get foreground app failed");
261         return ERR_STRATEGY_DEPENDS_SA_NOT_AVAILABLE;
262     }
263     // add foreground flag to app
264     for (const auto& appInfo : fgApps) {
265         std::string key = std::to_string(appInfo.uid) + "_" + appInfo.bundleName;
266         if (auto iter = proxiedAppInfo_.find(key); iter != proxiedAppInfo_.end()) {
267             iter->second.appExemptionFlag_ |= ExemptionTypeFlag::FOREGROUND_APP;
268         }
269     }
270     return ERR_OK;
271 }
272 
GetBackgroundTaskApp()273 ErrCode RunningLockStrategy::GetBackgroundTaskApp()
274 {
275     #ifdef ENABLE_BACKGROUND_TASK_MGR
276     std::vector<std::shared_ptr<ContinuousTaskCallbackInfo>> continuousTaskList;
277     if (!BackgroundTaskHelper::GetInstance()->GetContinuousTaskApps(continuousTaskList)) {
278         STANDBYSERVICE_LOGE("get continuous task app failed");
279         return ERR_STRATEGY_DEPENDS_SA_NOT_AVAILABLE;
280     }
281     STANDBYSERVICE_LOGD("succeed GetContinuousTaskApps, size is %{public}d",
282         static_cast<int32_t>(continuousTaskList.size()));
283     std::vector<std::shared_ptr<TransientTaskAppInfo>> transientTaskList;
284     if (!BackgroundTaskHelper::GetInstance()->GetTransientTaskApps(transientTaskList)) {
285         STANDBYSERVICE_LOGE("get transient task app failed");
286         return ERR_STRATEGY_DEPENDS_SA_NOT_AVAILABLE;
287     }
288     // add continuous exemption flag for app with continuous task
289     STANDBYSERVICE_LOGD("succeed GetTransientTaskApps, size is %{public}d",
290         static_cast<int32_t>(transientTaskList.size()));
291     for (const auto& task : continuousTaskList) {
292         auto iter = uidBundleNmeMap_.find(task->GetCreatorUid());
293         if (iter == uidBundleNmeMap_.end()) {
294             continue;
295         }
296         std::string key = std::to_string(task->GetCreatorUid()) + "_" + iter->second;
297         if (auto infoIter = proxiedAppInfo_.find(key); infoIter == proxiedAppInfo_.end()) {
298             continue;
299         } else {
300             infoIter->second.appExemptionFlag_ |= ExemptionTypeFlag::CONTINUOUS_TASK;
301         }
302     }
303     // add transient exemption flag for app with transient task
304     for (const auto& task : transientTaskList) {
305         std::string key = std::to_string(task->GetUid()) + "_" + task->GetPackageName();
306         if (auto iter = proxiedAppInfo_.find(key); iter == proxiedAppInfo_.end()) {
307             continue;
308         } else {
309             iter->second.appExemptionFlag_ |= ExemptionTypeFlag::TRANSIENT_TASK;
310         }
311     }
312     #endif
313     return ERR_OK;
314 }
315 
GetExemptionConfig()316 ErrCode RunningLockStrategy::GetExemptionConfig()
317 {
318     // if app in exemption list, add its exemption flag
319     std::vector<AllowInfo> allowInfoList {};
320     StandbyServiceImpl::GetInstance()->GetAllowListInner(AllowType::RUNNING_LOCK, allowInfoList,
321         ReasonCodeEnum::REASON_APP_API);
322     std::set<std::string> allowNameList {};
323     for (const auto& info : allowInfoList) {
324         allowNameList.emplace(info.GetName());
325     }
326     for (auto& [key, value] : proxiedAppInfo_) {
327         if (allowNameList.find(value.name_) == allowNameList.end()) {
328             continue;
329         }
330         value.appExemptionFlag_ |= ExemptionTypeFlag::EXEMPTION;
331     }
332 
333     // if app in restrict list, add retricted flag
334     std::set<std::string> restrictBundleName {};
335     StandbyServiceImpl::GetInstance()->GetEligiableRestrictSet(AllowType::RUNNING_LOCK, "RUNNING_LOCK",
336         ReasonCodeEnum::REASON_APP_API, restrictBundleName);
337     STANDBYSERVICE_LOGI("running lock restrict app list, size is %{public}d",
338         static_cast<int32_t>(restrictBundleName.size()));
339     for (auto& [key, value] : proxiedAppInfo_) {
340         if (restrictBundleName.find(value.name_) == restrictBundleName.end()) {
341             continue;
342         }
343         value.appExemptionFlag_ |= ExemptionTypeFlag::RESTRICTED;
344     }
345     return ERR_OK;
346 }
347 
InitNativeProcInfo()348 ErrCode RunningLockStrategy::InitNativeProcInfo()
349 {
350     return ERR_OK;
351 }
352 
ProxyAppAndProcess(bool isProxied)353 ErrCode RunningLockStrategy::ProxyAppAndProcess(bool isProxied)
354 {
355     std::vector<std::pair<int32_t, int32_t>> proxiedAppList;
356     for (const auto& [key, value] : proxiedAppInfo_) {
357         if (ExemptionTypeFlag::IsExempted(value.appExemptionFlag_)) {
358             continue;
359         }
360         SetProxiedAppList(proxiedAppList, value);
361     }
362     STANDBYSERVICE_LOGD("proxied app size: %{public}d", static_cast<int32_t>(proxiedAppList.size()));
363     ProxyRunningLockList(isProxied, proxiedAppList);
364     return ERR_OK;
365 }
366 
StopProxy(const StandbyMessage & message)367 ErrCode RunningLockStrategy::StopProxy(const StandbyMessage& message)
368 {
369     if (!isProxied_) {
370         return ERR_STANDBY_CURRENT_STATE_NOT_MATCH;
371     }
372     uint32_t preState = static_cast<uint32_t>(message.want_->GetIntParam(PREVIOUS_STATE, 0));
373     uint32_t curState = static_cast<uint32_t>(message.want_->GetIntParam(CURRENT_STATE, 0));
374     if ((curState == StandbyState::MAINTENANCE) && (preState == StandbyState::SLEEP)) {
375         // enter maintenance, stop proxy
376         ProxyAppAndProcess(false);
377         isIdleMaintence_ = true;
378     } else if ((curState == StandbyState::SLEEP) && (preState == StandbyState::MAINTENANCE)) {
379         isIdleMaintence_ = false;
380         // exit maintenance, enter sleep, start proxy
381         ProxyAppAndProcess(true);
382     } else if (preState == StandbyState::SLEEP || preState == StandbyState::MAINTENANCE) {
383         StopProxyInner();
384         isProxied_ = false;
385         isIdleMaintence_ = false;
386     }
387     return ERR_OK;
388 }
389 
StopProxyInner()390 ErrCode RunningLockStrategy::StopProxyInner()
391 {
392     ProxyAppAndProcess(false);
393     ClearProxyRecord();
394     return ERR_OK;
395 }
396 
UpdateBgTaskAppStatus(const StandbyMessage & message)397 ErrCode RunningLockStrategy::UpdateBgTaskAppStatus(const StandbyMessage& message)
398 {
399     std::string type = message.want_->GetStringParam(BG_TASK_TYPE);
400     bool started = message.want_->GetBoolParam(BG_TASK_STATUS, false);
401     int32_t uid = message.want_->GetIntParam(BG_TASK_UID, 0);
402     std::string bundleName = message.want_->GetStringParam(BG_TASK_BUNDLE_NAME);
403 
404     STANDBYSERVICE_LOGD("received bgtask status changed, type: %{public}s, isstarted: %{public}d, uid: %{public}d",
405         type.c_str(), started, uid);
406     if (BGTASK_EXEMPTION_FLAG_MAP.find(type) == BGTASK_EXEMPTION_FLAG_MAP.end()) {
407         return ERR_STANDBY_KEY_INFO_NOT_MATCH;
408     }
409 
410     if (bundleName.empty()) {
411         bundleName = BundleManagerHelper::GetInstance()->GetClientBundleName(uid);
412     }
413     if (started) {
414         AddExemptionFlag(uid, bundleName, BGTASK_EXEMPTION_FLAG_MAP.at(type));
415     } else {
416         RemoveExemptionFlag(uid, bundleName, BGTASK_EXEMPTION_FLAG_MAP.at(type));
417     }
418     return ERR_OK;
419 }
420 
421 // when bgtask or work_scheduler service crash, reset proxy status
ResetProxyStatus(const StandbyMessage & message)422 void RunningLockStrategy::ResetProxyStatus(const StandbyMessage& message)
423 {
424     if (!isProxied_ || isIdleMaintence_) {
425         return;
426     }
427     bool isAdded = message.want_->GetBoolParam(SA_STATUS, false);
428     if (isAdded) {
429         return;
430     }
431     int32_t saId = message.want_->GetIntParam(SA_ID, 0);
432     if (saId != WORK_SCHEDULE_SERVICE_ID && saId != BACKGROUND_TASK_MANAGER_SERVICE_ID) {
433         return;
434     }
435     const uint8_t bgTaskFlag = (ExemptionTypeFlag::TRANSIENT_TASK | ExemptionTypeFlag::WORK_SCHEDULER);
436     for (const auto& [key, value] : proxiedAppInfo_) {
437         if ((value.appExemptionFlag_ & bgTaskFlag) == 0) {
438             continue;
439         }
440         RemoveExemptionFlag(value.uid_, value.name_, (value.appExemptionFlag_ & bgTaskFlag));
441     }
442     return;
443 }
444 
AddExemptionFlag(int32_t uid,const std::string & name,uint8_t flag)445 void RunningLockStrategy::AddExemptionFlag(int32_t uid, const std::string& name, uint8_t flag)
446 {
447     if (!isProxied_) {
448         return;
449     }
450     std::string mapKey = std::to_string(uid) + "_" + name;
451     // if last appExemptionFlag is not exempted, current appExemptionFlag is exempted, unproxy running lock
452     if (auto iter = proxiedAppInfo_.find(mapKey); iter != proxiedAppInfo_.end()) {
453         auto lastAppExemptionFlag = iter->second.appExemptionFlag_;
454         iter->second.appExemptionFlag_ |= flag;
455         if (!ExemptionTypeFlag::IsExempted(lastAppExemptionFlag) &&
456             ExemptionTypeFlag::IsExempted(iter->second.appExemptionFlag_)) {
457             std::vector<std::pair<int32_t, int32_t>> proxiedAppList;
458             SetProxiedAppList(proxiedAppList, iter->second);
459             ProxyRunningLockList(false, proxiedAppList);
460         }
461     }
462 }
463 
RemoveExemptionFlag(int32_t uid,const std::string & name,uint8_t flag)464 void RunningLockStrategy::RemoveExemptionFlag(int32_t uid, const std::string& name, uint8_t flag)
465 {
466     std::string mapKey = std::to_string(uid) + "_" + name;
467     auto iter = proxiedAppInfo_.find(mapKey);
468     if (iter == proxiedAppInfo_.end()) {
469         return;
470     }
471 
472     // if last appExemptionFlag is exempted, current appExemptionFlag is unexempted, proxy running lock
473     auto lastAppExemptionFlag = iter->second.appExemptionFlag_;
474     iter->second.appExemptionFlag_ &= (~flag);
475     if (ExemptionTypeFlag::IsExempted(iter->second.appExemptionFlag_) ||
476         !ExemptionTypeFlag::IsExempted(lastAppExemptionFlag)) {
477         return;
478     }
479 
480     std::vector<std::pair<int32_t, int32_t>> proxiedAppList;
481     SetProxiedAppList(proxiedAppList, iter->second);
482     ProxyRunningLockList(true, proxiedAppList);
483 }
484 
ClearProxyRecord()485 void RunningLockStrategy::ClearProxyRecord()
486 {
487     proxiedAppInfo_.clear();
488     uidBundleNmeMap_.clear();
489 }
490 
491 // when app is created, add app info to cache
GetAndCreateAppInfo(uint32_t uid,uint32_t pid,const std::string & bundleName)492 void RunningLockStrategy::GetAndCreateAppInfo(uint32_t uid, uint32_t pid, const std::string& bundleName)
493 {
494     const std::string mapKey = std::to_string(uid) + "_" + bundleName;
495     auto iter = proxiedAppInfo_.find(mapKey);
496     if (iter != proxiedAppInfo_.end()) {
497         iter->second.pids_.emplace(pid);
498         return;
499     }
500 
501     std::tie(iter, std::ignore) = proxiedAppInfo_.emplace(mapKey, ProxiedProcInfo {bundleName, uid});
502     iter->second.pids_.emplace(pid);
503 
504     bool isSystemApp {false};
505     if (BundleManagerHelper::GetInstance()->CheckIsSystemAppByUid(uid, isSystemApp) && isSystemApp) {
506         iter->second.appExemptionFlag_ |= ExemptionTypeFlag::UNRESTRICTED;
507     }
508     GetExemptionConfigForApp(iter->second, bundleName);
509 }
510 
GetExemptionConfigForApp(ProxiedProcInfo & appInfo,const std::string & bundleName)511 ErrCode RunningLockStrategy::GetExemptionConfigForApp(ProxiedProcInfo& appInfo, const std::string& bundleName)
512 {
513     // if app in exemption list, add exemption flag
514     std::vector<AllowInfo> allowInfoList {};
515     StandbyServiceImpl::GetInstance()->GetAllowListInner(AllowType::NETWORK, allowInfoList,
516         ReasonCodeEnum::REASON_APP_API);
517     std::set<std::string> allowNameList {};
518     for (const auto& info : allowInfoList) {
519         if (info.GetName() != bundleName) {
520             continue;
521         }
522         appInfo.appExemptionFlag_ |= ExemptionTypeFlag::EXEMPTION;
523     }
524 
525     // if app in restricted list, add retricted flag
526     std::set<std::string> restrictNameList {};
527     StandbyServiceImpl::GetInstance()->GetEligiableRestrictSet(AllowType::NETWORK, "NETWORK",
528         ReasonCodeEnum::REASON_APP_API, restrictNameList);
529     if (restrictNameList.find(bundleName) != restrictNameList.end()) {
530         appInfo.appExemptionFlag_ |= ExemptionTypeFlag::RESTRICTED;
531     }
532     return ERR_OK;
533 }
534 
SetProxiedAppList(std::vector<std::pair<int32_t,int32_t>> & proxiedAppList,const ProxiedProcInfo & info)535 void RunningLockStrategy::SetProxiedAppList(std::vector<std::pair<int32_t, int32_t>>& proxiedAppList,
536     const ProxiedProcInfo& info)
537 {
538     for (auto& pid : info.pids_) {
539         proxiedAppList.emplace_back(std::make_pair(pid, info.uid_));
540     }
541 }
542 
ProxyRunningLockList(bool isProxied,const std::vector<std::pair<int32_t,int32_t>> & proxiedAppList)543 void RunningLockStrategy::ProxyRunningLockList(bool isProxied,
544     const std::vector<std::pair<int32_t, int32_t>>& proxiedAppList)
545 {
546     if (proxiedAppList.empty()) {
547         return;
548     }
549     // in maintenance state, disallow proxy running lock
550     if (isIdleMaintence_) {
551         STANDBYSERVICE_LOGI("current is idle maintenance, can not proxy running lock");
552         return;
553     }
554     #ifdef STANDBY_POWER_MANAGER_ENABLE
555     if (!PowerMgr::PowerMgrClient::GetInstance().ProxyRunningLocks(isProxied, proxiedAppList)) {
556         STANDBYSERVICE_LOGW("failed to ProxyRunningLockList");
557     }
558     #endif
559 }
560 
HandleProcessStatusChanged(const StandbyMessage & message)561 void RunningLockStrategy::HandleProcessStatusChanged(const StandbyMessage& message)
562 {
563     if (!isProxied_) {
564         STANDBYSERVICE_LOGD("RunningLockStrategy is not in proxy, do not need process");
565         return;
566     }
567     int32_t uid = message.want_->GetIntParam("uid", -1);
568     int32_t pid = message.want_->GetIntParam("pid", -1);
569     std::string bundleName = message.want_->GetStringParam("name");
570     bool isCreated = message.want_->GetBoolParam("isCreated", false);
571 
572     auto key = std::to_string(uid) + "_" + bundleName;
573     if (isCreated) {
574         // if process is created
575         GetAndCreateAppInfo(uid, pid, bundleName);
576         if (!ExemptionTypeFlag::IsExempted(proxiedAppInfo_[key].appExemptionFlag_)) {
577             ProxyRunningLockList(true, {std::make_pair(pid, uid)});
578         }
579     } else {
580         auto iter = proxiedAppInfo_.find(key);
581         if (iter == proxiedAppInfo_.end()) {
582             return;
583         }
584         if (!ExemptionTypeFlag::IsExempted(proxiedAppInfo_[key].appExemptionFlag_)) {
585             ProxyRunningLockList(false, {std::make_pair(pid, uid)});
586         }
587         iter->second.pids_.erase(pid);
588         if (iter->second.pids_.empty()) {
589             proxiedAppInfo_.erase(iter);
590         }
591     }
592 }
593 
ShellDump(const std::vector<std::string> & argsInStr,std::string & result)594 void RunningLockStrategy::ShellDump(const std::vector<std::string>& argsInStr, std::string& result)
595 {
596     if (argsInStr[DUMP_FIRST_PARAM] == DUMP_DETAIL_INFO &&
597         argsInStr[DUMP_SECOND_PARAM] == DUMP_STRATGY_DETAIL) {
598         DumpShowDetailInfo(argsInStr, result);
599     }
600 }
601 
602 // dump detail info of running lock strategy
DumpShowDetailInfo(const std::vector<std::string> & argsInStr,std::string & result)603 void RunningLockStrategy::DumpShowDetailInfo(const std::vector<std::string>& argsInStr, std::string& result)
604 {
605     result.append("=================RunningLock======================\n");
606     result.append("Running Lock Strategy:\n").append("isProxied: " + std::to_string(isProxied_))
607         .append(" isIdleMaintence: " + std::to_string(isIdleMaintence_)).append("\n");
608     result.append("proxied app info: \n");
609     for (const auto& [key, value] : proxiedAppInfo_) {
610         result.append("key: ").append(key).append(" name: ").append(value.name_).append(" uid: ")
611             .append(std::to_string(value.uid_)).append(" pid_size: ")
612             .append(std::to_string(value.pids_.size())).append(" exemption flag: ")
613             .append(std::to_string(value.appExemptionFlag_)).append("\n");
614         if (value.pids_.empty()) {
615             continue;
616         }
617         result.append("pids list: ");
618         for (const auto pid : value.pids_) {
619             result.append(" ").append(std::to_string(pid));
620         }
621         result.append("\n");
622     }
623 }
624 }  // namespace DevStandbyMgr
625 }  // namespace OHOS