1ba5c3796Sopenharmony_ci/*
2ba5c3796Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3ba5c3796Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4ba5c3796Sopenharmony_ci * you may not use this file except in compliance with the License.
5ba5c3796Sopenharmony_ci * You may obtain a copy of the License at
6ba5c3796Sopenharmony_ci *
7ba5c3796Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8ba5c3796Sopenharmony_ci *
9ba5c3796Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10ba5c3796Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11ba5c3796Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12ba5c3796Sopenharmony_ci * See the License for the specific language governing permissions and
13ba5c3796Sopenharmony_ci * limitations under the License.
14ba5c3796Sopenharmony_ci */
15ba5c3796Sopenharmony_ci
16ba5c3796Sopenharmony_ci#include "window_visibility_observer.h"
17ba5c3796Sopenharmony_ci
18ba5c3796Sopenharmony_ci#include "event_handler.h"
19ba5c3796Sopenharmony_ci#include "memmgr_log.h"
20ba5c3796Sopenharmony_ci#include "memmgr_ptr_util.h"
21ba5c3796Sopenharmony_ci#include "singleton.h"
22ba5c3796Sopenharmony_ci
23ba5c3796Sopenharmony_cinamespace OHOS {
24ba5c3796Sopenharmony_cinamespace Memory {
25ba5c3796Sopenharmony_cinamespace {
26ba5c3796Sopenharmony_ciconst std::string TAG = "WindowVisibilityObserver";
27ba5c3796Sopenharmony_ciconst std::string WINDOW_OBSERVER_HANDLER = "WindowVisibilityObserverHandler";
28ba5c3796Sopenharmony_ciconstexpr int TIMER_PEROID_MIN = 5;
29ba5c3796Sopenharmony_ciconstexpr int TIMER_PEROID_MS = TIMER_PEROID_MIN * 60 * 1000;
30ba5c3796Sopenharmony_ciconstexpr int TRIGGER_BY_TIME = 1;
31ba5c3796Sopenharmony_ciconstexpr int TRIGGER_BY_SIZE = 2;
32ba5c3796Sopenharmony_ci}
33ba5c3796Sopenharmony_ci
34ba5c3796Sopenharmony_ciIMPLEMENT_SINGLE_INSTANCE(WindowVisibilityObserver);
35ba5c3796Sopenharmony_ci
36ba5c3796Sopenharmony_ciWindowVisibilityObserver::WindowVisibilityObserver()
37ba5c3796Sopenharmony_ci{
38ba5c3796Sopenharmony_ci    if (!handler_) {
39ba5c3796Sopenharmony_ci        MAKE_POINTER(handler_, shared, AppExecFwk::EventHandler, "failed to create event handler", return,
40ba5c3796Sopenharmony_ci                     AppExecFwk::EventRunner::Create());
41ba5c3796Sopenharmony_ci    }
42ba5c3796Sopenharmony_ci    SetTimer();
43ba5c3796Sopenharmony_ci}
44ba5c3796Sopenharmony_ci
45ba5c3796Sopenharmony_civoid WindowVisibilityObserver::OnProcessDied(int pid)
46ba5c3796Sopenharmony_ci{
47ba5c3796Sopenharmony_ci    HILOGD("called");
48ba5c3796Sopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
49ba5c3796Sopenharmony_ci    windowVisibleMap_.erase(pid);
50ba5c3796Sopenharmony_ci    HILOGD("remove pid=%{public}d from WindowVisibilityObserver", pid);
51ba5c3796Sopenharmony_ci}
52ba5c3796Sopenharmony_ci
53ba5c3796Sopenharmony_civoid WindowVisibilityObserver::UpdateWindowVisibilityPriority(
54ba5c3796Sopenharmony_ci    const std::vector<sptr<MemMgrWindowInfo>> &memMgrWindowInfo)
55ba5c3796Sopenharmony_ci{
56ba5c3796Sopenharmony_ci    HILOGD("called");
57ba5c3796Sopenharmony_ci    handler_->PostImmediateTask([this, memMgrWindowInfo] {
58ba5c3796Sopenharmony_ci        this->UpdateWindowVisibilityPriorityInner(memMgrWindowInfo);
59ba5c3796Sopenharmony_ci    });
60ba5c3796Sopenharmony_ci}
61ba5c3796Sopenharmony_ci
62ba5c3796Sopenharmony_civoid WindowVisibilityObserver::UpdateWindowVisibilityPriorityInner(
63ba5c3796Sopenharmony_ci    const std::vector<sptr<MemMgrWindowInfo>> &MemMgrWindowInfo)
64ba5c3796Sopenharmony_ci{
65ba5c3796Sopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
66ba5c3796Sopenharmony_ci    for (auto &info : MemMgrWindowInfo) {
67ba5c3796Sopenharmony_ci        if (!info) {
68ba5c3796Sopenharmony_ci            continue;
69ba5c3796Sopenharmony_ci        }
70ba5c3796Sopenharmony_ci        auto windowId = info->windowId_;
71ba5c3796Sopenharmony_ci        auto isVisible = info->isVisible_;
72ba5c3796Sopenharmony_ci        auto pid = info->pid_;
73ba5c3796Sopenharmony_ci        auto uid = info->uid_;
74ba5c3796Sopenharmony_ci        HILOGI("MemMgrWindowInfo[pid=%{public}d, uid=%{public}d, winId=%{public}d, visible=%{public}d]",
75ba5c3796Sopenharmony_ci            pid, uid, windowId, isVisible);
76ba5c3796Sopenharmony_ci        if (isVisible) {
77ba5c3796Sopenharmony_ci            auto windowInfoPtr = windowVisibleMap_.find(pid);
78ba5c3796Sopenharmony_ci            if (windowInfoPtr != windowVisibleMap_.end()) {
79ba5c3796Sopenharmony_ci                windowInfoPtr->second.visibleWindowIds.insert(windowId);
80ba5c3796Sopenharmony_ci            } else {
81ba5c3796Sopenharmony_ci                ProcessWindowVisibilityInfo info;
82ba5c3796Sopenharmony_ci                info.uid = uid;
83ba5c3796Sopenharmony_ci                info.visible = false;
84ba5c3796Sopenharmony_ci                info.visibleWindowIds.insert(windowId);
85ba5c3796Sopenharmony_ci                windowVisibleMap_.insert(std::make_pair(pid, info));
86ba5c3796Sopenharmony_ci            }
87ba5c3796Sopenharmony_ci        } else {
88ba5c3796Sopenharmony_ci            auto windowInfoPtr = windowVisibleMap_.find(pid);
89ba5c3796Sopenharmony_ci            if (windowInfoPtr != windowVisibleMap_.end()) {
90ba5c3796Sopenharmony_ci                windowInfoPtr->second.visibleWindowIds.erase(windowId);
91ba5c3796Sopenharmony_ci            }
92ba5c3796Sopenharmony_ci        }
93ba5c3796Sopenharmony_ci    }
94ba5c3796Sopenharmony_ci
95ba5c3796Sopenharmony_ci    HILOGI("windowVisibleMap_size=%{public}zu", windowVisibleMap_.size());
96ba5c3796Sopenharmony_ci    UpdatePriorityForVisible(windowVisibleMap_);
97ba5c3796Sopenharmony_ci    if (windowVisibleMap_.size() >= 2048) { //2048: max process num
98ba5c3796Sopenharmony_ci        if (handler_) {
99ba5c3796Sopenharmony_ci            handler_->PostImmediateTask([this] { this->CheckMapSize(TRIGGER_BY_SIZE); });
100ba5c3796Sopenharmony_ci        }
101ba5c3796Sopenharmony_ci    }
102ba5c3796Sopenharmony_ci}
103ba5c3796Sopenharmony_ci
104ba5c3796Sopenharmony_civoid WindowVisibilityObserver::UpdatePriorityForVisible(
105ba5c3796Sopenharmony_ci    std::map<int32_t, ProcessWindowVisibilityInfo> &windowVisibleMap_)
106ba5c3796Sopenharmony_ci{
107ba5c3796Sopenharmony_ci    std::vector<unsigned int> toBeDeleted;
108ba5c3796Sopenharmony_ci    ReclaimHandleRequest request;
109ba5c3796Sopenharmony_ci    for (auto &pair : windowVisibleMap_) {
110ba5c3796Sopenharmony_ci        ProcessWindowVisibilityInfo &info = pair.second;
111ba5c3796Sopenharmony_ci        if (info.visibleWindowIds.size() > 0 && info.visible == false) {
112ba5c3796Sopenharmony_ci            info.visible = true;
113ba5c3796Sopenharmony_ci            ReclaimPriorityManager::GetInstance().UpdateReclaimPriority(
114ba5c3796Sopenharmony_ci                SingleRequest({pair.first, info.uid, "", ""}, AppStateUpdateReason::VISIBLE));
115ba5c3796Sopenharmony_ci        } else if (info.visibleWindowIds.size() == 0) {
116ba5c3796Sopenharmony_ci            if (info.visible == true) {
117ba5c3796Sopenharmony_ci                info.visible = false;
118ba5c3796Sopenharmony_ci                ReclaimPriorityManager::GetInstance().UpdateReclaimPriority(
119ba5c3796Sopenharmony_ci                    SingleRequest({pair.first, info.uid, "", ""}, AppStateUpdateReason::UN_VISIBLE));
120ba5c3796Sopenharmony_ci            }
121ba5c3796Sopenharmony_ci            toBeDeleted.push_back(pair.first);
122ba5c3796Sopenharmony_ci        }
123ba5c3796Sopenharmony_ci        HILOGD("ProcessWindowVisibilityInfo[pid=%{public}d, uid=%{public}d, vWins=%{public}zu,"
124ba5c3796Sopenharmony_ci            "visible=%{public}d]", pair.first, info.uid, info.visibleWindowIds.size(), info.visible);
125ba5c3796Sopenharmony_ci    }
126ba5c3796Sopenharmony_ci    for (auto pid : toBeDeleted) {
127ba5c3796Sopenharmony_ci        windowVisibleMap_.erase(pid);
128ba5c3796Sopenharmony_ci    }
129ba5c3796Sopenharmony_ci}
130ba5c3796Sopenharmony_ci
131ba5c3796Sopenharmony_civoid WindowVisibilityObserver::SetTimer()
132ba5c3796Sopenharmony_ci{
133ba5c3796Sopenharmony_ci    //set timer and call CheckMapSize each TIMER_PEROID_MIN min.
134ba5c3796Sopenharmony_ci    handler_->PostTask([this] { this->CheckMapSize(TRIGGER_BY_TIME); },
135ba5c3796Sopenharmony_ci        TIMER_PEROID_MS, AppExecFwk::EventQueue::Priority::HIGH);
136ba5c3796Sopenharmony_ci    HILOGD("set timer after %{public}d mins", TIMER_PEROID_MIN);
137ba5c3796Sopenharmony_ci}
138ba5c3796Sopenharmony_ci
139ba5c3796Sopenharmony_civoid WindowVisibilityObserver::CheckMapSize(int type)
140ba5c3796Sopenharmony_ci{
141ba5c3796Sopenharmony_ci    HILOGD("called");
142ba5c3796Sopenharmony_ci
143ba5c3796Sopenharmony_ci    std::vector<unsigned int> alivePids;
144ba5c3796Sopenharmony_ci    if (!KernelInterface::GetInstance().GetAllProcPids(alivePids)) {
145ba5c3796Sopenharmony_ci        return;
146ba5c3796Sopenharmony_ci    }
147ba5c3796Sopenharmony_ci
148ba5c3796Sopenharmony_ci    std::vector<unsigned int> toBeDeleted;
149ba5c3796Sopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
150ba5c3796Sopenharmony_ci    for (auto &pair : windowVisibleMap_) {
151ba5c3796Sopenharmony_ci        auto pid = pair.first;
152ba5c3796Sopenharmony_ci        if (std::find(alivePids.begin(), alivePids.end(), pid) == alivePids.end()) {
153ba5c3796Sopenharmony_ci            toBeDeleted.push_back(pid);
154ba5c3796Sopenharmony_ci        }
155ba5c3796Sopenharmony_ci    }
156ba5c3796Sopenharmony_ci
157ba5c3796Sopenharmony_ci    for (auto pid : toBeDeleted) {
158ba5c3796Sopenharmony_ci        windowVisibleMap_.erase(pid);
159ba5c3796Sopenharmony_ci    }
160ba5c3796Sopenharmony_ci
161ba5c3796Sopenharmony_ci    if (type == TRIGGER_BY_TIME) {
162ba5c3796Sopenharmony_ci        SetTimer();
163ba5c3796Sopenharmony_ci    }
164ba5c3796Sopenharmony_ci}
165ba5c3796Sopenharmony_ci} // namespace Memory
166ba5c3796Sopenharmony_ci} // namespace OHOS
167