• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "starting_window.h"
17 #include <ability_manager_client.h>
18 #include <common/rs_common_def.h>
19 #include <display_manager_service_inner.h>
20 #include <hitrace_meter.h>
21 #include <transaction/rs_transaction.h>
22 
23 #include "display_group_info.h"
24 #include "remote_animation.h"
25 #include "window_helper.h"
26 #include "window_inner_manager.h"
27 #include "window_manager_hilog.h"
28 #include "window_manager_service.h"
29 #include "window_manager_service_utils.h"
30 #include "window_system_effect.h"
31 
32 namespace OHOS {
33 namespace Rosen {
34 namespace {
35 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "StartingWindow"};
36 }
37 
38 const std::map<OHOS::AppExecFwk::DisplayOrientation, Orientation> ABILITY_TO_WMS_ORIENTATION_MAP {
39     {OHOS::AppExecFwk::DisplayOrientation::UNSPECIFIED, Orientation::UNSPECIFIED},
40     {OHOS::AppExecFwk::DisplayOrientation::LANDSCAPE, Orientation::HORIZONTAL},
41     {OHOS::AppExecFwk::DisplayOrientation::PORTRAIT, Orientation::VERTICAL},
42     {OHOS::AppExecFwk::DisplayOrientation::FOLLOWRECENT, Orientation::LOCKED},
43     {OHOS::AppExecFwk::DisplayOrientation::LANDSCAPE_INVERTED, Orientation::REVERSE_HORIZONTAL},
44     {OHOS::AppExecFwk::DisplayOrientation::PORTRAIT_INVERTED, Orientation::REVERSE_VERTICAL},
45     {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION, Orientation::SENSOR},
46     {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION_LANDSCAPE, Orientation::SENSOR_HORIZONTAL},
47     {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION_PORTRAIT, Orientation::SENSOR_VERTICAL},
48     {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION_RESTRICTED, Orientation::AUTO_ROTATION_RESTRICTED},
49     {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION_LANDSCAPE_RESTRICTED,
50         Orientation::AUTO_ROTATION_LANDSCAPE_RESTRICTED},
51     {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION_PORTRAIT_RESTRICTED,
52         Orientation::AUTO_ROTATION_PORTRAIT_RESTRICTED},
53     {OHOS::AppExecFwk::DisplayOrientation::LOCKED, Orientation::LOCKED},
54 };
55 
56 std::recursive_mutex StartingWindow::mutex_;
57 WindowMode StartingWindow::defaultMode_ = WindowMode::WINDOW_MODE_FULLSCREEN;
58 bool StartingWindow::transAnimateEnable_ = true;
59 WindowUIType StartingWindow::windowUIType_ = WindowUIType::INVALID_WINDOW;
60 AnimationConfig StartingWindow::animationConfig_;
61 
CreateWindowNode(const sptr<WindowTransitionInfo> & info,uint32_t winId)62 sptr<WindowNode> StartingWindow::CreateWindowNode(const sptr<WindowTransitionInfo>& info, uint32_t winId)
63 {
64     sptr<WindowProperty> property = InitializeWindowProperty(info, winId);
65     if (property == nullptr) {
66         return nullptr;
67     }
68 
69     sptr<WindowNode> node = new(std::nothrow) WindowNode(property);
70     if (node == nullptr) {
71         return nullptr;
72     }
73 
74     node->stateMachine_.SetWindowId(winId);
75     node->abilityToken_ = info->GetAbilityToken();
76     node->SetWindowSizeLimits(info->GetWindowSizeLimits());
77     node->abilityInfo_.missionId_ = info->GetMissionId();
78     node->abilityInfo_.bundleName_ = info->GetBundleName();
79     node->abilityInfo_.abilityName_ = info->GetAbilityName();
80     uint32_t windowModeSupportType = WindowHelper::ConvertSupportModesToSupportType(info->GetWindowSupportModes());
81     node->SetWindowModeSupportType(windowModeSupportType);
82 
83     if (CreateLeashAndStartingSurfaceNode(node) != WMError::WM_OK) {
84         return nullptr;
85     }
86     node->stateMachine_.TransitionTo(WindowNodeState::STARTING_CREATED);
87     return node;
88 }
89 
InitializeWindowProperty(const sptr<WindowTransitionInfo> & info,uint32_t winId)90 sptr<WindowProperty> StartingWindow::InitializeWindowProperty(const sptr<WindowTransitionInfo>& info, uint32_t winId)
91 {
92     sptr<WindowProperty> property = new(std::nothrow) WindowProperty();
93     if (property == nullptr || info == nullptr) {
94         return nullptr;
95     }
96 
97     property->SetRequestRect(info->GetWindowRect());
98     if (WindowHelper::IsValidWindowMode(info->GetWindowMode())) {
99         property->SetWindowMode(info->GetWindowMode());
100     } else {
101         property->SetWindowMode(defaultMode_);
102     }
103 
104     AppExecFwk::DisplayOrientation displayOrientation = info->GetOrientation();
105     if (ABILITY_TO_WMS_ORIENTATION_MAP.count(displayOrientation) == 0) {
106         WLOGFE("id:%{public}u Do not support this Orientation type", winId);
107         return nullptr;
108     }
109     Orientation orientation = ABILITY_TO_WMS_ORIENTATION_MAP.at(displayOrientation);
110     if (orientation < Orientation::BEGIN || orientation > Orientation::END) {
111         WLOGFE("Set orientation from ability failed");
112         return nullptr;
113     }
114     property->SetRequestedOrientation(orientation);
115 
116     property->SetDisplayId(info->GetDisplayId());
117     property->SetWindowType(info->GetWindowType());
118 
119     ChangePropertyByApiVersion(info, orientation, property);
120     property->SetApiCompatibleVersion(info->GetApiCompatibleVersion());
121     if (info->GetShowFlagWhenLocked()) {
122         if (property->GetApiCompatibleVersion() < 9 || info->isSystemCalling_) { // 9: api version.
123             property->AddWindowFlag(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED);
124         } else {
125             WLOGFW("Only API 9- or system calling support showing when locked.");
126         }
127     }
128     property->SetWindowId(winId);
129     return property;
130 }
131 
ChangePropertyByApiVersion(const sptr<WindowTransitionInfo> & info,const Orientation orientation,sptr<WindowProperty> & property)132 void StartingWindow::ChangePropertyByApiVersion(const sptr<WindowTransitionInfo>& info,
133     const Orientation orientation, sptr<WindowProperty>& property)
134 {
135     // 10 ArkUI new framework support after API10
136     if (info->GetApiCompatibleVersion() < 10) {
137         auto displayInfo = DisplayGroupInfo::GetInstance().GetDisplayInfo(info->GetDisplayId());
138         if (!(displayInfo && WmsUtils::IsExpectedRotatableWindow(orientation,
139             displayInfo->GetDisplayOrientation(), property->GetWindowMode(), property->GetWindowFlags(), false))) {
140             property->AddWindowFlag(WindowFlag::WINDOW_FLAG_NEED_AVOID);
141         }
142     } else {
143         if (WindowHelper::IsMainWindow(property->GetWindowType())) {
144             SystemBarProperty statusSystemBarProperty(true, 0x00FFFFFF, 0xFF000000);
145             SystemBarProperty navigationSystemBarProperty(true, 0x00FFFFFF, 0xFF000000);
146             property->SetSystemBarProperty(WindowType::WINDOW_TYPE_STATUS_BAR, statusSystemBarProperty);
147             property->SetSystemBarProperty(WindowType::WINDOW_TYPE_NAVIGATION_BAR, navigationSystemBarProperty);
148         }
149     }
150 }
151 
CreateLeashAndStartingSurfaceNode(sptr<WindowNode> & node)152 WMError StartingWindow::CreateLeashAndStartingSurfaceNode(sptr<WindowNode>& node)
153 {
154     struct RSSurfaceNodeConfig rsSurfaceNodeConfig;
155     rsSurfaceNodeConfig.SurfaceNodeName = "leashWindow" + std::to_string(node->GetWindowId());
156     node->leashWinSurfaceNode_ = RSSurfaceNode::Create(rsSurfaceNodeConfig, RSSurfaceNodeType::LEASH_WINDOW_NODE);
157     if (node->leashWinSurfaceNode_ == nullptr) {
158         TLOGE(WmsLogTag::WMS_STARTUP_PAGE, "create leashWinSurfaceNode failed");
159         return WMError::WM_ERROR_NULLPTR;
160     }
161 
162     rsSurfaceNodeConfig.SurfaceNodeName = "startingWindow" + std::to_string(node->GetWindowId());
163     node->startingWinSurfaceNode_ = RSSurfaceNode::Create(rsSurfaceNodeConfig, RSSurfaceNodeType::STARTING_WINDOW_NODE);
164     if (node->startingWinSurfaceNode_ == nullptr) {
165         TLOGE(WmsLogTag::WMS_STARTUP_PAGE, "create startingWinSurfaceNode failed");
166         node->leashWinSurfaceNode_ = nullptr;
167         return WMError::WM_ERROR_NULLPTR;
168     }
169     TLOGI(WmsLogTag::WMS_STARTUP_PAGE,
170         "Create leashWinSurfaceNode and startingWinSurfaceNode success with id:%{public}u!",
171         node->GetWindowId());
172     return WMError::WM_OK;
173 }
174 
DrawStartingWindow(sptr<WindowNode> & node,std::shared_ptr<Media::PixelMap> pixelMap,uint32_t bkgColor,bool isColdStart)175 WMError StartingWindow::DrawStartingWindow(sptr<WindowNode>& node,
176     std::shared_ptr<Media::PixelMap> pixelMap, uint32_t bkgColor, bool isColdStart)
177 {
178     if (node == nullptr) {
179         return WMError::WM_ERROR_NULLPTR;
180     }
181     // using snapshot to support hot start since node destroy when hide
182     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "wms:DrawStartingWindow(%u)", node->GetWindowId());
183     Rect rect = node->GetWindowRect();
184     if (RemoteAnimation::CheckRemoteAnimationEnabled(node->GetDisplayId()) && node->leashWinSurfaceNode_) {
185         // hides this node until RSProxyNode send valid context alpha/matrix
186         node->leashWinSurfaceNode_->ResetContextAlpha();
187     }
188     if (!isColdStart) {
189         return WMError::WM_OK;
190     }
191     if (node->startingWinSurfaceNode_ == nullptr) {
192         TLOGE(WmsLogTag::WMS_STARTUP_PAGE, "no starting Window SurfaceNode!");
193         return WMError::WM_ERROR_NULLPTR;
194     }
195     // set window effect
196     WindowSystemEffect::SetWindowEffect(node);
197     if (pixelMap == nullptr) {
198         SurfaceDraw::DrawColor(node->startingWinSurfaceNode_, rect.width_, rect.height_, bkgColor);
199         return WMError::WM_OK;
200     }
201 
202     TLOGD(WmsLogTag::WMS_STARTUP_PAGE, "draw background in sperate");
203     SurfaceDraw::DrawImageRect(node->startingWinSurfaceNode_, rect, pixelMap, bkgColor);
204     return WMError::WM_OK;
205 }
206 
SetStartingWindowAnimation(wptr<WindowNode> weak)207 WMError StartingWindow::SetStartingWindowAnimation(wptr<WindowNode> weak)
208 {
209     auto weakNode = weak.promote();
210     if (weakNode == nullptr || !weakNode->startingWinSurfaceNode_) {
211         TLOGE(WmsLogTag::WMS_STARTUP_PAGE, "windowNode or startingWinSurfaceNode_ is nullptr");
212         return WMError::WM_ERROR_NULLPTR;
213     }
214     StartAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast<int32_t>(TraceTaskId::START_WINDOW_ANIMATION),
215         "StartingWindowAnimate(%u)", weakNode->GetWindowId());
216     weakNode->startingWinSurfaceNode_->SetAlpha(animationConfig_.startWinAnimationConfig_.opacityStart_);
217     auto execute = [weak]() {
218         auto weakNode = weak.promote();
219         if (weakNode == nullptr) {
220             TLOGNE(WmsLogTag::WMS_STARTUP_PAGE, "windowNode is nullptr");
221             return;
222         }
223         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "StartingWindow:ExecuteAnimate(%d)",
224             weakNode->GetWindowId());
225         weakNode->startingWinSurfaceNode_->SetAlpha(animationConfig_.startWinAnimationConfig_.opacityEnd_);
226     };
227 
228     auto finish = [weak]() {
229         auto weakNode = weak.promote();
230         if (weakNode == nullptr || weakNode->leashWinSurfaceNode_ == nullptr) {
231             TLOGE(WmsLogTag::WMS_STARTUP_PAGE, "windowNode or leashWinSurfaceNode_ is nullptr");
232             return;
233         }
234         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "StartingWindow:AnimateFinish(%d)",
235             weakNode->GetWindowId());
236         TLOGNI(WmsLogTag::WMS_STARTUP_PAGE, "StartingWindow::Replace surfaceNode, id: %{public}u",
237             weakNode->GetWindowId());
238         weakNode->leashWinSurfaceNode_->RemoveChild(weakNode->startingWinSurfaceNode_);
239         weakNode->startingWinSurfaceNode_ = nullptr;
240         RSTransaction::FlushImplicitTransaction();
241         FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast<int32_t>(TraceTaskId::START_WINDOW_ANIMATION),
242             "StartingWindowAnimate(%u)", weakNode->GetWindowId());
243     };
244     RSNode::Animate(animationConfig_.startWinAnimationConfig_.timingProtocol_,
245         animationConfig_.startWinAnimationConfig_.timingCurve_, execute, finish);
246     RSTransaction::FlushImplicitTransaction();
247     FinishTrace(HITRACE_TAG_WINDOW_MANAGER);
248     return WMError::WM_OK;
249 }
250 
HandleClientWindowCreate(sptr<WindowNode> & node,sptr<IWindow> & window,uint32_t & windowId,const std::shared_ptr<RSSurfaceNode> & surfaceNode,sptr<WindowProperty> & property,int32_t pid,int32_t uid)251 void StartingWindow::HandleClientWindowCreate(sptr<WindowNode>& node, sptr<IWindow>& window,
252     uint32_t& windowId, const std::shared_ptr<RSSurfaceNode>& surfaceNode, sptr<WindowProperty>& property,
253     int32_t pid, int32_t uid)
254 {
255     if (node == nullptr) {
256         TLOGE(WmsLogTag::WMS_STARTUP_PAGE, "node is nullptr");
257         return;
258     }
259     node->surfaceNode_ = surfaceNode;
260     node->SetWindowToken(window);
261     node->SetCallingPid(pid);
262     node->SetCallingUid(uid);
263     windowId = node->GetWindowId();
264     // test
265     node->stateMachine_.SetWindowId(windowId);
266     node->stateMachine_.SetWindowType(property->GetWindowType());
267     TLOGI(WmsLogTag::WMS_STARTUP_PAGE, "after set Id:%{public}u, "
268         "requestRect:[%{public}d, %{public}d, %{public}u, %{public}u]",
269         node->GetWindowId(), node->GetRequestRect().posX_, node->GetRequestRect().posY_,
270         node->GetRequestRect().width_, node->GetRequestRect().height_);
271     // Register FirstFrame Callback to rs, replace startwin
272     wptr<WindowNode> weak = node;
273     auto firstFrameCompleteCallback = [weak]() {
274         auto task = [weak]() {
275             FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast<int32_t>(TraceTaskId::STARTING_WINDOW),
276                 "wms:async:ShowStartingWindow");
277             auto weakNode = weak.promote();
278             if (weakNode == nullptr || weakNode->leashWinSurfaceNode_ == nullptr) {
279                 TLOGNE(WmsLogTag::WMS_STARTUP_PAGE, "windowNode or leashWinSurfaceNode_ is nullptr");
280                 return;
281             }
282             TLOGNI(WmsLogTag::WMS_STARTUP_PAGE, "StartingWindow::FirstFrameCallback come, id: %{public}u",
283                 weakNode->GetWindowId());
284             if (transAnimateEnable_) {
285                 SetStartingWindowAnimation(weakNode);
286             } else {
287                 weakNode->leashWinSurfaceNode_->RemoveChild(weakNode->startingWinSurfaceNode_);
288                 weakNode->startingWinSurfaceNode_ = nullptr;
289                 RSTransaction::FlushImplicitTransaction();
290                 TLOGNI(WmsLogTag::WMS_STARTUP_PAGE, "StartingWindow::Replace surfaceNode, id: %{public}u",
291                     weakNode->GetWindowId());
292             }
293             WindowInnerManager::GetInstance().CompleteFirstFrameDrawing(weakNode);
294             weakNode->firstFrameAvailable_ = true;
295         };
296         WindowManagerService::GetInstance().PostAsyncTask(task, "firstFrameCompleteCallback");
297     };
298     node->surfaceNode_->SetBufferAvailableCallback(firstFrameCompleteCallback);
299     RSTransaction::FlushImplicitTransaction();
300 }
301 
ReleaseStartWinSurfaceNode(sptr<WindowNode> & node)302 void StartingWindow::ReleaseStartWinSurfaceNode(sptr<WindowNode>& node)
303 {
304     std::lock_guard<std::recursive_mutex> lock(mutex_);
305     if (!node->leashWinSurfaceNode_) {
306         TLOGI(WmsLogTag::WMS_STARTUP_PAGE, "cannot release leashwindow since leash is null, id:%{public}u",
307             node->GetWindowId());
308         return;
309     }
310     node->leashWinSurfaceNode_->RemoveChild(node->startingWinSurfaceNode_);
311     node->leashWinSurfaceNode_->RemoveChild(node->closeWinSurfaceNode_);
312     node->leashWinSurfaceNode_->RemoveChild(node->surfaceNode_);
313     node->leashWinSurfaceNode_ = nullptr;
314     node->startingWinSurfaceNode_ = nullptr;
315     node->closeWinSurfaceNode_ = nullptr;
316     TLOGI(WmsLogTag::WMS_STARTUP_PAGE, "Release startwindow surfaceNode end id: %{public}u, "
317         "[leashWinSurface]: use_count: %{public}ld, [startWinSurface]: use_count: %{public}ld ",
318         node->GetWindowId(), node->leashWinSurfaceNode_.use_count(),
319         node->startingWinSurfaceNode_.use_count());
320     RSTransaction::FlushImplicitTransaction();
321 }
322 
IsWindowFollowParent(WindowType type)323 bool StartingWindow::IsWindowFollowParent(WindowType type)
324 {
325     if (windowUIType_ != WindowUIType::PHONE_WINDOW) {
326         return false;
327     }
328     return WindowHelper::IsWindowFollowParent(type);
329 }
330 
AddNodeOnRSTree(sptr<WindowNode> & node,bool isMultiDisplay)331 void StartingWindow::AddNodeOnRSTree(sptr<WindowNode>& node, bool isMultiDisplay)
332 {
333     auto updateRSTreeFunc = [&node, isMultiDisplay]() {
334         UpdateRSTree(node, isMultiDisplay);
335     };
336     wptr<WindowNode> weakNode = node;
337     auto finishCallBack = [weakNode]() {
338         auto weak = weakNode.promote();
339         if (weak == nullptr) {
340             return;
341         }
342         auto winRect = weak->GetWindowRect();
343         TLOGI(WmsLogTag::WMS_STARTUP_PAGE,
344             "before setBounds windowRect: %{public}d, %{public}d, %{public}d, %{public}d",
345             winRect.posX_, winRect.posY_, winRect.width_, winRect.height_);
346         if (weak->leashWinSurfaceNode_) {
347             weak->leashWinSurfaceNode_->SetBounds(winRect.posX_, winRect.posY_, winRect.width_, winRect.height_);
348             weak->leashWinSurfaceNode_->SetAnimationFinished();
349         }
350         RSTransaction::FlushImplicitTransaction();
351     };
352     if (!RemoteAnimation::CheckAnimationController()) {
353         RSNode::Animate(animationConfig_.windowAnimationConfig_.animationTiming_.timingProtocol_,
354             animationConfig_.windowAnimationConfig_.animationTiming_.timingCurve_,
355             updateRSTreeFunc, finishCallBack);
356     } else {
357         // add or remove window without animation
358         updateRSTreeFunc();
359     }
360 }
361 
UpdateRSTree(sptr<WindowNode> & node,bool isMultiDisplay)362 void StartingWindow::UpdateRSTree(sptr<WindowNode>& node, bool isMultiDisplay)
363 {
364     auto& dms = DisplayManagerServiceInner::GetInstance();
365     DisplayId displayId = node->GetDisplayId();
366     if (!node->surfaceNode_) { // cold start
367         if (!WindowHelper::IsMainWindow(node->GetWindowType())) {
368             TLOGE(WmsLogTag::WMS_MAIN, "window id: %{public}d type: %{public}u is not Main Window!",
369                 node->GetWindowId(), static_cast<uint32_t>(node->GetWindowType()));
370         }
371         dms.UpdateRSTree(displayId, displayId, node->leashWinSurfaceNode_, true, isMultiDisplay);
372         node->leashWinSurfaceNode_->AddChild(node->startingWinSurfaceNode_, -1);
373         TLOGD(WmsLogTag::WMS_MAIN, "Add startingWinSurfaceNode_ to leashWinSurfaceNode_ end during cold start");
374         return;
375     }
376     // hot start
377     const auto& displayIdVec = node->GetShowingDisplays();
378     for (auto& shownDisplayId : displayIdVec) {
379         if (node->leashWinSurfaceNode_) { // to app
380             dms.UpdateRSTree(shownDisplayId, shownDisplayId, node->leashWinSurfaceNode_, true, isMultiDisplay);
381         } else { // to launcher
382             dms.UpdateRSTree(shownDisplayId, shownDisplayId, node->surfaceNode_, true, isMultiDisplay);
383         }
384         for (auto& child : node->children_) {
385             if (IsWindowFollowParent(child->GetWindowType())) {
386                 continue;
387             }
388             if (child->currentVisibility_) {
389                 dms.UpdateRSTree(shownDisplayId, shownDisplayId, child->surfaceNode_, true, isMultiDisplay);
390             }
391         }
392     }
393     TLOGD(WmsLogTag::WMS_MAIN, "Update RsTree with hot start");
394 }
395 
SetDefaultWindowMode(WindowMode defaultMode)396 void StartingWindow::SetDefaultWindowMode(WindowMode defaultMode)
397 {
398     defaultMode_ = defaultMode;
399 }
400 
SetAnimationConfig(AnimationConfig config)401 void StartingWindow::SetAnimationConfig(AnimationConfig config)
402 {
403     animationConfig_ = config;
404 }
405 } // Rosen
406 } // OHOS
407