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 "window_visibility_observer.h"
17 
18 #include "event_handler.h"
19 #include "memmgr_log.h"
20 #include "memmgr_ptr_util.h"
21 #include "singleton.h"
22 
23 namespace OHOS {
24 namespace Memory {
25 namespace {
26 const std::string TAG = "WindowVisibilityObserver";
27 const std::string WINDOW_OBSERVER_HANDLER = "WindowVisibilityObserverHandler";
28 constexpr int TIMER_PEROID_MIN = 5;
29 constexpr int TIMER_PEROID_MS = TIMER_PEROID_MIN * 60 * 1000;
30 constexpr int TRIGGER_BY_TIME = 1;
31 constexpr int TRIGGER_BY_SIZE = 2;
32 }
33 
34 IMPLEMENT_SINGLE_INSTANCE(WindowVisibilityObserver);
35 
WindowVisibilityObserver()36 WindowVisibilityObserver::WindowVisibilityObserver()
37 {
38     if (!handler_) {
39         MAKE_POINTER(handler_, shared, AppExecFwk::EventHandler, "failed to create event handler", return,
40                      AppExecFwk::EventRunner::Create());
41     }
42     SetTimer();
43 }
44 
OnProcessDied(int pid)45 void WindowVisibilityObserver::OnProcessDied(int pid)
46 {
47     HILOGD("called");
48     std::lock_guard<std::mutex> lock(mutex_);
49     windowVisibleMap_.erase(pid);
50     HILOGD("remove pid=%{public}d from WindowVisibilityObserver", pid);
51 }
52 
UpdateWindowVisibilityPriority(const std::vector<sptr<MemMgrWindowInfo>> & memMgrWindowInfo)53 void WindowVisibilityObserver::UpdateWindowVisibilityPriority(
54     const std::vector<sptr<MemMgrWindowInfo>> &memMgrWindowInfo)
55 {
56     HILOGD("called");
57     handler_->PostImmediateTask([this, memMgrWindowInfo] {
58         this->UpdateWindowVisibilityPriorityInner(memMgrWindowInfo);
59     });
60 }
61 
UpdateWindowVisibilityPriorityInner(const std::vector<sptr<MemMgrWindowInfo>> & MemMgrWindowInfo)62 void WindowVisibilityObserver::UpdateWindowVisibilityPriorityInner(
63     const std::vector<sptr<MemMgrWindowInfo>> &MemMgrWindowInfo)
64 {
65     std::lock_guard<std::mutex> lock(mutex_);
66     for (auto &info : MemMgrWindowInfo) {
67         if (!info) {
68             continue;
69         }
70         auto windowId = info->windowId_;
71         auto isVisible = info->isVisible_;
72         auto pid = info->pid_;
73         auto uid = info->uid_;
74         HILOGI("MemMgrWindowInfo[pid=%{public}d, uid=%{public}d, winId=%{public}d, visible=%{public}d]",
75             pid, uid, windowId, isVisible);
76         if (isVisible) {
77             auto windowInfoPtr = windowVisibleMap_.find(pid);
78             if (windowInfoPtr != windowVisibleMap_.end()) {
79                 windowInfoPtr->second.visibleWindowIds.insert(windowId);
80             } else {
81                 ProcessWindowVisibilityInfo info;
82                 info.uid = uid;
83                 info.visible = false;
84                 info.visibleWindowIds.insert(windowId);
85                 windowVisibleMap_.insert(std::make_pair(pid, info));
86             }
87         } else {
88             auto windowInfoPtr = windowVisibleMap_.find(pid);
89             if (windowInfoPtr != windowVisibleMap_.end()) {
90                 windowInfoPtr->second.visibleWindowIds.erase(windowId);
91             }
92         }
93     }
94 
95     HILOGI("windowVisibleMap_size=%{public}zu", windowVisibleMap_.size());
96     UpdatePriorityForVisible(windowVisibleMap_);
97     if (windowVisibleMap_.size() >= 2048) { //2048: max process num
98         if (handler_) {
99             handler_->PostImmediateTask([this] { this->CheckMapSize(TRIGGER_BY_SIZE); });
100         }
101     }
102 }
103 
UpdatePriorityForVisible(std::map<int32_t,ProcessWindowVisibilityInfo> & windowVisibleMap_)104 void WindowVisibilityObserver::UpdatePriorityForVisible(
105     std::map<int32_t, ProcessWindowVisibilityInfo> &windowVisibleMap_)
106 {
107     std::vector<unsigned int> toBeDeleted;
108     ReclaimHandleRequest request;
109     for (auto &pair : windowVisibleMap_) {
110         ProcessWindowVisibilityInfo &info = pair.second;
111         if (info.visibleWindowIds.size() > 0 && info.visible == false) {
112             info.visible = true;
113             ReclaimPriorityManager::GetInstance().UpdateReclaimPriority(
114                 SingleRequest({pair.first, info.uid, "", ""}, AppStateUpdateReason::VISIBLE));
115         } else if (info.visibleWindowIds.size() == 0) {
116             if (info.visible == true) {
117                 info.visible = false;
118                 ReclaimPriorityManager::GetInstance().UpdateReclaimPriority(
119                     SingleRequest({pair.first, info.uid, "", ""}, AppStateUpdateReason::UN_VISIBLE));
120             }
121             toBeDeleted.push_back(pair.first);
122         }
123         HILOGD("ProcessWindowVisibilityInfo[pid=%{public}d, uid=%{public}d, vWins=%{public}zu,"
124             "visible=%{public}d]", pair.first, info.uid, info.visibleWindowIds.size(), info.visible);
125     }
126     for (auto pid : toBeDeleted) {
127         windowVisibleMap_.erase(pid);
128     }
129 }
130 
SetTimer()131 void WindowVisibilityObserver::SetTimer()
132 {
133     //set timer and call CheckMapSize each TIMER_PEROID_MIN min.
134     handler_->PostTask([this] { this->CheckMapSize(TRIGGER_BY_TIME); },
135         TIMER_PEROID_MS, AppExecFwk::EventQueue::Priority::HIGH);
136     HILOGD("set timer after %{public}d mins", TIMER_PEROID_MIN);
137 }
138 
CheckMapSize(int type)139 void WindowVisibilityObserver::CheckMapSize(int type)
140 {
141     HILOGD("called");
142 
143     std::vector<unsigned int> alivePids;
144     if (!KernelInterface::GetInstance().GetAllProcPids(alivePids)) {
145         return;
146     }
147 
148     std::vector<unsigned int> toBeDeleted;
149     std::lock_guard<std::mutex> lock(mutex_);
150     for (auto &pair : windowVisibleMap_) {
151         auto pid = pair.first;
152         if (std::find(alivePids.begin(), alivePids.end(), pid) == alivePids.end()) {
153             toBeDeleted.push_back(pid);
154         }
155     }
156 
157     for (auto pid : toBeDeleted) {
158         windowVisibleMap_.erase(pid);
159     }
160 
161     if (type == TRIGGER_BY_TIME) {
162         SetTimer();
163     }
164 }
165 } // namespace Memory
166 } // namespace OHOS
167