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