1 /*
2 * Copyright (c) 2022-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_inner_manager.h"
17
18 #include "ability_manager_client.h"
19 #include "memory_guard.h"
20 #include "window.h"
21 #include "window_manager_hilog.h"
22 #include "xcollie/watchdog.h"
23 #include "perform_reporter.h"
24
25 namespace OHOS {
26 namespace Rosen {
27 namespace {
28 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "InnerManager"};
29 }
WM_IMPLEMENT_SINGLE_INSTANCE(WindowInnerManager)30 WM_IMPLEMENT_SINGLE_INSTANCE(WindowInnerManager)
31
32 WindowInnerManager::WindowInnerManager() : eventHandler_(nullptr), eventLoop_(nullptr),
33 state_(InnerWMRunningState::STATE_NOT_START)
34 {
35 }
36
~WindowInnerManager()37 WindowInnerManager::~WindowInnerManager()
38 {
39 Stop();
40 }
41
Init()42 bool WindowInnerManager::Init()
43 {
44 // create handler for inner command at server
45 eventLoop_ = AppExecFwk::EventRunner::Create(INNER_WM_THREAD_NAME);
46 if (eventLoop_ == nullptr) {
47 return false;
48 }
49 eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(eventLoop_);
50 if (eventHandler_ == nullptr) {
51 return false;
52 }
53 int ret = HiviewDFX::Watchdog::GetInstance().AddThread(INNER_WM_THREAD_NAME, eventHandler_);
54 if (ret != 0) {
55 WLOGFE("Add watchdog thread failed");
56 }
57 eventHandler_->PostTask([]() { MemoryGuard cacheGuard; }, AppExecFwk::EventQueue::Priority::IMMEDIATE);
58 moveDragController_ = new MoveDragController();
59 if (!moveDragController_->Init()) {
60 WLOGFE("Init window drag controller failed");
61 return false;
62 }
63
64 WLOGI("init window inner manager service success.");
65 return true;
66 }
67
Start(bool enableRecentholder)68 void WindowInnerManager::Start(bool enableRecentholder)
69 {
70 isRecentHolderEnable_ = enableRecentholder;
71 if (state_ == InnerWMRunningState::STATE_RUNNING) {
72 WLOGI("window inner manager service has already started.");
73 }
74 if (!Init()) {
75 WLOGI("failed to init window inner manager service.");
76 return;
77 }
78 state_ = InnerWMRunningState::STATE_RUNNING;
79 eventLoop_->Run();
80
81 pid_ = getpid();
82 WLOGI("window inner manager service start success.");
83 }
84
Stop()85 void WindowInnerManager::Stop()
86 {
87 WLOGI("stop window inner manager service.");
88 if (eventLoop_ != nullptr) {
89 eventLoop_->Stop();
90 eventLoop_.reset();
91 }
92 if (eventHandler_ != nullptr) {
93 eventHandler_.reset();
94 }
95 if (moveDragController_ != nullptr) {
96 moveDragController_->Stop();
97 }
98 state_ = InnerWMRunningState::STATE_NOT_START;
99 }
100
CreateInnerWindow(std::string name,DisplayId displayId,Rect rect,WindowType type,WindowMode mode)101 void WindowInnerManager::CreateInnerWindow(std::string name, DisplayId displayId, Rect rect,
102 WindowType type, WindowMode mode)
103 {
104 bool recentHolderWindowFlag = isRecentHolderEnable_;
105 auto task = [name, displayId, rect, mode, type, recentHolderWindowFlag]() {
106 if (type == WindowType::WINDOW_TYPE_PLACEHOLDER && recentHolderWindowFlag) {
107 PlaceHolderWindow::GetInstance().Create(name, displayId, rect, mode);
108 }
109 };
110 PostTask(task, "CreateInnerWindow");
111 return;
112 }
113
DestroyInnerWindow(DisplayId displayId,WindowType type)114 void WindowInnerManager::DestroyInnerWindow(DisplayId displayId, WindowType type)
115 {
116 bool recentHolderWindowFlag = isRecentHolderEnable_;
117 auto task = [type, recentHolderWindowFlag]() {
118 if (type == WindowType::WINDOW_TYPE_PLACEHOLDER && recentHolderWindowFlag) {
119 PlaceHolderWindow::GetInstance().Destroy();
120 }
121 };
122 PostTask(task, "DestroyInnerWindow");
123 return;
124 }
125
UpdateInnerWindow(DisplayId displayId,WindowType type,uint32_t width,uint32_t height)126 void WindowInnerManager::UpdateInnerWindow(DisplayId displayId, WindowType type, uint32_t width, uint32_t height)
127 {
128 bool recentHolderWindowFlag = isRecentHolderEnable_;
129 auto task = [type, width, height, recentHolderWindowFlag]() {
130 if (type == WindowType::WINDOW_TYPE_PLACEHOLDER && recentHolderWindowFlag) {
131 PlaceHolderWindow::GetInstance().Update(width, height);
132 }
133 };
134 PostTask(task, "UpdateInnerWindow");
135 return;
136 }
137
MinimizeAbility(const wptr<WindowNode> & node,bool isFromUser)138 void WindowInnerManager::MinimizeAbility(const wptr<WindowNode> &node, bool isFromUser)
139 {
140 // asynchronously calls the MinimizeAbility of AbilityManager
141 auto weakNode = node.promote();
142 if (weakNode == nullptr) {
143 WLOGFE("minimize ability failed.");
144 return;
145 }
146 wptr<IRemoteObject> weakToken(weakNode->abilityToken_);
147 WLOGFD("minimize window %{public}u, isfromuser: %{public}d", weakNode->GetWindowId(), isFromUser);
148 auto task = [weakToken, isFromUser]() {
149 auto token = weakToken.promote();
150 if (token == nullptr) {
151 WLOGE("minimize ability failed, because window token is nullptr.");
152 return;
153 }
154 AAFwk::AbilityManagerClient::GetInstance()->MinimizeAbility(token, isFromUser);
155 };
156 PostTask(task, "MinimizeAbility");
157 }
158
TerminateAbility(const wptr<WindowNode> & node)159 void WindowInnerManager::TerminateAbility(const wptr<WindowNode> &node)
160 {
161 // asynchronously calls the TerminateAbility of AbilityManager
162 auto weakNode = node.promote();
163 if (weakNode == nullptr) {
164 WLOGFE("terminate ability failed.");
165 return;
166 }
167 wptr<IRemoteObject> weakToken(weakNode->abilityToken_);
168 WLOGFD("terminate window %{public}u", weakNode->GetWindowId());
169 auto task = [weakToken]() {
170 auto token = weakToken.promote();
171 if (token == nullptr) {
172 WLOGE("terminate ability failed, because window token is nullptr.");
173 return;
174 }
175 AAFwk::Want resultWant;
176 AAFwk::AbilityManagerClient::GetInstance()->TerminateAbility(token, -1, &resultWant);
177 };
178 PostTask(task, "TerminateAbility");
179 }
180
CloseAbility(const wptr<WindowNode> & node)181 void WindowInnerManager::CloseAbility(const wptr<WindowNode> &node)
182 {
183 // asynchronously calls the CloseAbility of AbilityManager
184 auto weakNode = node.promote();
185 if (weakNode == nullptr) {
186 WLOGFE("close ability failed.");
187 return;
188 }
189 wptr<IRemoteObject> weakToken(weakNode->abilityToken_);
190 WLOGFD("close window %{public}u", weakNode->GetWindowId());
191 auto task = [weakToken]() {
192 auto token = weakToken.promote();
193 if (token == nullptr) {
194 WLOGE("close ability failed, because window token is nullptr.");
195 return;
196 }
197 AAFwk::Want resultWant;
198 AAFwk::AbilityManagerClient::GetInstance()->CloseAbility(token);
199 };
200 PostTask(task, "CloseAbility");
201 }
202
CompleteFirstFrameDrawing(const wptr<WindowNode> & node)203 void WindowInnerManager::CompleteFirstFrameDrawing(const wptr<WindowNode> &node)
204 {
205 // asynchronously calls the CloseAbility of AbilityManager
206 auto weakNode = node.promote();
207 if (weakNode == nullptr) {
208 WLOGFE("CompleteFirstFrameDrawing failed.");
209 return;
210 }
211 wptr<IRemoteObject> weakToken(weakNode->abilityToken_);
212 WLOGFD("CompleteFirstFrameDrawing %{public}u", weakNode->GetWindowId());
213 auto task = [weakToken]() {
214 auto token = weakToken.promote();
215 if (token == nullptr) {
216 WLOGE("CompleteFirstFrameDrawing failed, because window token is nullptr.");
217 return;
218 }
219 AAFwk::AbilityManagerClient::GetInstance()->CompleteFirstFrameDrawing(token);
220 };
221 PostTask(task, "CompleteFirstFrameDrawing");
222 }
223
UpdateMissionSnapShot(const wptr<WindowNode> & node,std::shared_ptr<Media::PixelMap> pixelMap)224 void WindowInnerManager::UpdateMissionSnapShot(const wptr<WindowNode> &node, std::shared_ptr<Media::PixelMap> pixelMap)
225 {
226 // asynchronously calls the UpdateMissionSnapShot of AbilityManager
227 auto weakNode = node.promote();
228 if (weakNode == nullptr) {
229 WLOGFE("UpdateMissionSnapShot failed.");
230 return;
231 }
232 wptr<IRemoteObject> weakToken(weakNode->abilityToken_);
233 WLOGFD("Update id %{public}u", weakNode->GetWindowId());
234 auto task = [weakToken, pixelMap]() {
235 auto token = weakToken.promote();
236 if (token == nullptr) {
237 WLOGE("UpdateMissionSnapShot failed, because window token is nullptr.");
238 return;
239 }
240 if (pixelMap == nullptr) {
241 WLOGE("UpdateMissionSnapShot failed, because pixelMap is nullptr.");
242 return;
243 }
244 AAFwk::AbilityManagerClient::GetInstance()->UpdateMissionSnapShot(token, pixelMap);
245 };
246 PostTask(task, "UpdateMissionSnapShot");
247 }
248
PostTask(InnerTask && task,std::string name,EventPriority priority)249 void WindowInnerManager::PostTask(InnerTask &&task, std::string name, EventPriority priority)
250 {
251 if (eventHandler_ == nullptr) {
252 WLOGFE("listener handler is nullptr");
253 return;
254 }
255 bool ret = eventHandler_->PostTask(task, name, 0, priority); // 0 is task delay time
256 if (!ret) {
257 WLOGFE("post listener callback task failed.");
258 return;
259 }
260 return;
261 }
262
GetPid()263 pid_t WindowInnerManager::GetPid()
264 {
265 return pid_;
266 }
267
SetInputEventConsumer()268 void WindowInnerManager::SetInputEventConsumer()
269 {
270 if (moveDragController_ == nullptr) {
271 return;
272 }
273 moveDragController_->SetInputEventConsumer();
274 }
275
NotifyDisplayLimitRectChange(const std::map<DisplayId,Rect> & limitRectMap)276 void WindowInnerManager::NotifyDisplayLimitRectChange(const std::map<DisplayId, Rect>& limitRectMap)
277 {
278 if (moveDragController_ == nullptr) {
279 return;
280 }
281 moveDragController_->HandleDisplayLimitRectChange(limitRectMap);
282 }
283
NotifyServerReadyToMoveOrDrag(uint32_t windowId,sptr<WindowProperty> & windowProperty,sptr<MoveDragProperty> & moveDragProperty)284 bool WindowInnerManager::NotifyServerReadyToMoveOrDrag(uint32_t windowId, sptr<WindowProperty>& windowProperty,
285 sptr<MoveDragProperty>& moveDragProperty)
286 {
287 if (moveDragController_->GetActiveWindowId() != INVALID_WINDOW_ID) {
288 WLOGFW("Is already in dragging or moving state, invalid operation");
289 return false;
290 }
291 moveDragController_->HandleReadyToMoveOrDrag(windowId, windowProperty, moveDragProperty);
292 WLOGI("NotifyServerReadyToMoveOrDrag, windowId: %{public}u", windowId);
293 return true;
294 }
295
NotifyWindowEndUpMovingOrDragging(uint32_t windowId)296 void WindowInnerManager::NotifyWindowEndUpMovingOrDragging(uint32_t windowId)
297 {
298 if (moveDragController_->GetActiveWindowId() != windowId) {
299 return;
300 }
301 moveDragController_->HandleEndUpMovingOrDragging(windowId);
302 WLOGI("NotifyWindowEndUpMovingOrDragging, windowId: %{public}u", windowId);
303 }
304
NotifyWindowRemovedOrDestroyed(uint32_t windowId)305 void WindowInnerManager::NotifyWindowRemovedOrDestroyed(uint32_t windowId)
306 {
307 if (moveDragController_->GetActiveWindowId() != windowId) {
308 return;
309 }
310 moveDragController_->HandleWindowRemovedOrDestroyed(windowId);
311 WLOGI("NotifyWindowRemovedOrDestroyed, windowId: %{public}u", windowId);
312 }
313
ConsumePointerEvent(const std::shared_ptr<MMI::PointerEvent> & pointerEvent)314 void WindowInnerManager::ConsumePointerEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
315 {
316 uint32_t windowId = static_cast<uint32_t>(pointerEvent->GetAgentWindowId());
317 if (moveDragController_->GetActiveWindowId() != windowId ||
318 moveDragController_->GetActiveWindowId() == INVALID_WINDOW_ID) {
319 WLOGFE("active winId or inputEvent winId is invalid, windowId: %{public}u, activeWinId: %{public}u",
320 windowId, moveDragController_->GetActiveWindowId());
321 return;
322 }
323 moveDragController_->ConsumePointerEvent(pointerEvent);
324 }
325
StartWindowInfoReportLoop()326 void WindowInnerManager::StartWindowInfoReportLoop()
327 {
328 if (isReportTaskStart_ || eventHandler_ == nullptr) {
329 return;
330 }
331 auto task = [this]() {
332 WindowInfoReporter::GetInstance().ReportRecordedInfos();
333 isReportTaskStart_ = false;
334 StartWindowInfoReportLoop();
335 };
336 int64_t delayTime = 1000 * 60 * 60; // an hour.
337 bool ret = eventHandler_->PostTask(task, "WindowInfoReport", delayTime);
338 if (!ret) {
339 WLOGFE("post listener callback task failed. the task name is WindowInfoReport");
340 return;
341 }
342 isReportTaskStart_ = true;
343 }
344 } // Rosen
345 } // OHOS