1 /*
2  * Copyright (c) 2022 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 "minimize_app.h"
17 
18 #include <ability_manager_client.h>
19 #include "window_manager_hilog.h"
20 #include "window_inner_manager.h"
21 
22 namespace OHOS {
23 namespace Rosen {
24 namespace {
25 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "MinimizeApp"};
26 }
27 
28 std::map<MinimizeReason, std::vector<wptr<WindowNode>>> MinimizeApp::needMinimizeAppNodes_;
29 bool MinimizeApp::isMinimizedByOtherWindow_ = true;
30 std::recursive_mutex MinimizeApp::mutex_;
AddNeedMinimizeApp(const sptr<WindowNode> & node,MinimizeReason reason)31 void MinimizeApp::AddNeedMinimizeApp(const sptr<WindowNode>& node, MinimizeReason reason)
32 {
33     std::lock_guard<std::recursive_mutex> lock(mutex_);
34     if (!EnableMinimize(reason)) {
35         return;
36     }
37     if (!node) {
38         WLOGFE("AddNeedMinimizeApp failed since node is nullptr");
39         return;
40     }
41     wptr<WindowNode> weakNode(node);
42     for (auto& appNodes: needMinimizeAppNodes_) {
43         auto windowId = node->GetWindowId();
44         auto iter = std::find_if(appNodes.second.begin(), appNodes.second.end(),
45             [windowId](wptr<WindowNode> srcNode) {
46                 auto weakSrcNode = srcNode.promote();
47                 if (weakSrcNode == nullptr) {
48                     return false;
49                 }
50                 return weakSrcNode->GetWindowId() == windowId;
51             });
52         if (iter != appNodes.second.end()) {
53             WLOGI("[Minimize] Window %{public}u is already in minimize list", node->GetWindowId());
54             return;
55         }
56     }
57     WLOGI("[Minimize] Add Window %{public}u to minimize list, reason %{public}u", node->GetWindowId(), reason);
58     needMinimizeAppNodes_[reason].emplace_back(weakNode);
59 }
60 
GetNeedMinimizeAppNodesWithReason(MinimizeReason reason)61 std::vector<wptr<WindowNode>> MinimizeApp::GetNeedMinimizeAppNodesWithReason(MinimizeReason reason)
62 {
63     std::lock_guard<std::recursive_mutex> lock(mutex_);
64     std::vector<wptr<WindowNode>> needMinimizeAppNodes;
65     if (needMinimizeAppNodes_.find(reason) != needMinimizeAppNodes_.end()) {
66         for (auto& node : needMinimizeAppNodes_[reason]) {
67             needMinimizeAppNodes.emplace_back(node);
68         }
69     }
70     return needMinimizeAppNodes;
71 }
72 
ExecuteMinimizeAll()73 void MinimizeApp::ExecuteMinimizeAll()
74 {
75     std::lock_guard<std::recursive_mutex> lock(mutex_);
76     for (auto& appNodes: needMinimizeAppNodes_) {
77         bool isFromUser = IsFromUser(appNodes.first);
78         WLOGI("[Minimize] ExecuteMinimizeAll with size: %{public}zu, reason: %{public}u",
79             appNodes.second.size(), appNodes.first);
80         for (auto& node : appNodes.second) {
81             WindowInnerManager::GetInstance().MinimizeAbility(node, isFromUser);
82         }
83         appNodes.second.clear();
84     }
85     needMinimizeAppNodes_.clear();
86 }
87 
ClearNodesWithReason(MinimizeReason reason)88 void MinimizeApp::ClearNodesWithReason(MinimizeReason reason)
89 {
90     WLOGI("[Minimize] ClearNodesWithReason reason %{public}u", reason);
91     std::lock_guard<std::recursive_mutex> lock(mutex_);
92     if (needMinimizeAppNodes_.find(reason) != needMinimizeAppNodes_.end()) {
93         needMinimizeAppNodes_.at(reason).clear();
94     }
95 }
96 
GetRecoverdNodeFromMinimizeList()97 sptr<WindowNode> MinimizeApp::GetRecoverdNodeFromMinimizeList()
98 {
99     WLOGI("[Minimize] RevertMinimizedNodeForTile");
100     std::lock_guard<std::recursive_mutex> lock(mutex_);
101     if (needMinimizeAppNodes_.find(MinimizeReason::LAYOUT_TILE) != needMinimizeAppNodes_.end()) {
102         auto& tileNodesForMinimize = needMinimizeAppNodes_.at(MinimizeReason::LAYOUT_TILE);
103         if (!tileNodesForMinimize.empty()) {
104             auto recoverNode = tileNodesForMinimize.back().promote();
105             tileNodesForMinimize.pop_back();
106             return recoverNode;
107         }
108     }
109     return nullptr;
110 }
111 
IsNodeNeedMinimize(const sptr<WindowNode> & node)112 bool MinimizeApp::IsNodeNeedMinimize(const sptr<WindowNode>& node)
113 {
114     if (node == nullptr) {
115         WLOGFE("[Minimize] node is nullptr");
116         return false;
117     }
118     for (auto iter : needMinimizeAppNodes_) {
119         auto nodes = iter.second;
120         if (std::find(nodes.begin(), nodes.end(), node) != nodes.end()) {
121             return true;
122         }
123     }
124     return false;
125 }
126 
IsNodeNeedMinimizeWithReason(const sptr<WindowNode> & node,MinimizeReason reason)127 bool MinimizeApp::IsNodeNeedMinimizeWithReason(const sptr<WindowNode>& node, MinimizeReason reason)
128 {
129     if (node == nullptr) {
130         WLOGFE("[Minimize] node is nullptr");
131         return false;
132     }
133     if (needMinimizeAppNodes_.find(reason) == needMinimizeAppNodes_.end()) {
134         WLOGFD("[Minimize] no need to minimize with id:%{public}u reason:%{public}u",
135             node->GetWindowId(), reason);
136         return false;
137     }
138     auto nodes = needMinimizeAppNodes_.at(reason);
139     if (std::find(nodes.begin(), nodes.end(), node) != nodes.end()) {
140         WLOGI("[Minimize] id:%{public}u need to minimize with reason:%{public}u",
141             node->GetWindowId(), reason);
142         return true;
143     }
144     return false;
145 }
146 
EnableMinimize(MinimizeReason reason)147 bool MinimizeApp::EnableMinimize(MinimizeReason reason)
148 {
149     bool isFromUser = IsFromUser(reason);
150     if (!isMinimizedByOtherWindow_ && !isFromUser) {
151         return false;
152     }
153     return true;
154 }
155 
ExecuteMinimizeTargetReasons(uint32_t reasons)156 void MinimizeApp::ExecuteMinimizeTargetReasons(uint32_t reasons)
157 {
158     std::lock_guard<std::recursive_mutex> lock(mutex_);
159     while (reasons) {
160         MinimizeReason reason = static_cast<MinimizeReason>(reasons & (~reasons + 1));
161         if (needMinimizeAppNodes_.find(reason) != needMinimizeAppNodes_.end()) {
162             WLOGI("[Minimize] ExecuteMinimizeTargetReason with size: %{public}zu, reason: %{public}u",
163                 needMinimizeAppNodes_.at(reason).size(), reason);
164             bool isFromUser = IsFromUser(reason);
165             for (auto& node : needMinimizeAppNodes_.at(reason)) {
166                 WindowInnerManager::GetInstance().MinimizeAbility(node, isFromUser);
167             }
168             needMinimizeAppNodes_.at(reason).clear();
169         }
170         reasons -= reason;
171     }
172 }
173 
SetMinimizedByOtherConfig(bool isMinimizedByOther)174 void MinimizeApp::SetMinimizedByOtherConfig(bool isMinimizedByOther)
175 {
176     isMinimizedByOtherWindow_ = isMinimizedByOther;
177 }
178 } // Rosen
179 } // OHOS
180