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 std::function<void()> UpdateWindowVisibilityPriorityInnerFunc =
58 std::bind(&WindowVisibilityObserver::UpdateWindowVisibilityPriorityInner, this, MemMgrWindowInfo);
59 handler_->PostImmediateTask(UpdateWindowVisibilityPriorityInnerFunc);
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(std::bind(&WindowVisibilityObserver::CheckMapSize, this, 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 request.pid = pair.first;
114 request.uid = info.uid;
115 request.bundleName = "";
116 request.reason = AppStateUpdateReason::VISIBLE;
117 ReclaimPriorityManager::GetInstance().UpdateReclaimPriority(request);
118 } else if (info.visibleWindowIds.size() == 0) {
119 if (info.visible == true) {
120 info.visible = false;
121 request.pid = pair.first;
122 request.uid = info.uid;
123 request.bundleName = "";
124 request.reason = AppStateUpdateReason::UN_VISIBLE;
125 ReclaimPriorityManager::GetInstance().UpdateReclaimPriority(request);
126 }
127 toBeDeleted.push_back(pair.first);
128 }
129 HILOGD("ProcessWindowVisibilityInfo[pid=%{public}d, uid=%{public}d, vWins=%{public}zu,"
130 "visible=%{public}d]", pair.first, info.uid, info.visibleWindowIds.size(), info.visible);
131 }
132 for (auto pid : toBeDeleted) {
133 windowVisibleMap_.erase(pid);
134 }
135 }
136
SetTimer()137 void WindowVisibilityObserver::SetTimer()
138 {
139 std::function<void()> timerFunc_ = std::bind(&WindowVisibilityObserver::CheckMapSize, this, TRIGGER_BY_TIME);
140 //set timer and call CheckMapSize each TIMER_PEROID_MIN min.
141 handler_->PostTask(timerFunc_, TIMER_PEROID_MS, AppExecFwk::EventQueue::Priority::HIGH);
142 HILOGD("set timer after %{public}d mins", TIMER_PEROID_MIN);
143 }
144
CheckMapSize(int type)145 void WindowVisibilityObserver::CheckMapSize(int type)
146 {
147 HILOGD("called");
148
149 std::vector<unsigned int> alivePids;
150 if (!KernelInterface::GetInstance().GetAllProcPids(alivePids)) {
151 return;
152 }
153
154 std::vector<unsigned int> toBeDeleted;
155 std::lock_guard<std::mutex> lock(mutex_);
156 for (auto &pair : windowVisibleMap_) {
157 auto pid = pair.first;
158 if (std::find(alivePids.begin(), alivePids.end(), pid) == alivePids.end()) {
159 toBeDeleted.push_back(pid);
160 }
161 }
162
163 for (auto pid : toBeDeleted) {
164 windowVisibleMap_.erase(pid);
165 }
166
167 if (type == TRIGGER_BY_TIME) {
168 SetTimer();
169 }
170 }
171 } // namespace Memory
172 } // namespace OHOS
173