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