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