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 std::string StartingWindow::uiType_ = "";
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 WLOGFE("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 WLOGFE("create startingWinSurfaceNode failed");
166 node->leashWinSurfaceNode_ = nullptr;
167 return WMError::WM_ERROR_NULLPTR;
168 }
169 WLOGI("Create leashWinSurfaceNode and startingWinSurfaceNode success with id:%{public}u!", node->GetWindowId());
170 return WMError::WM_OK;
171 }
172
DrawStartingWindow(sptr<WindowNode> & node,std::shared_ptr<Media::PixelMap> pixelMap,uint32_t bkgColor,bool isColdStart)173 WMError StartingWindow::DrawStartingWindow(sptr<WindowNode>& node,
174 std::shared_ptr<Media::PixelMap> pixelMap, uint32_t bkgColor, bool isColdStart)
175 {
176 if (node == nullptr) {
177 return WMError::WM_ERROR_NULLPTR;
178 }
179 // using snapshot to support hot start since node destroy when hide
180 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "wms:DrawStartingWindow(%u)", node->GetWindowId());
181 Rect rect = node->GetWindowRect();
182 if (RemoteAnimation::CheckRemoteAnimationEnabled(node->GetDisplayId()) && node->leashWinSurfaceNode_) {
183 // hides this node until RSProxyNode send valid context alpha/matrix
184 node->leashWinSurfaceNode_->ResetContextAlpha();
185 }
186 if (!isColdStart) {
187 return WMError::WM_OK;
188 }
189 if (node->startingWinSurfaceNode_ == nullptr) {
190 WLOGFE("no starting Window SurfaceNode!");
191 return WMError::WM_ERROR_NULLPTR;
192 }
193 // set window effect
194 WindowSystemEffect::SetWindowEffect(node);
195 if (pixelMap == nullptr) {
196 SurfaceDraw::DrawColor(node->startingWinSurfaceNode_, rect.width_, rect.height_, bkgColor);
197 return WMError::WM_OK;
198 }
199
200 WLOGFD("draw background in sperate");
201 SurfaceDraw::DrawImageRect(node->startingWinSurfaceNode_, rect, pixelMap, bkgColor);
202 return WMError::WM_OK;
203 }
204
SetStartingWindowAnimation(wptr<WindowNode> weak)205 WMError StartingWindow::SetStartingWindowAnimation(wptr<WindowNode> weak)
206 {
207 auto weakNode = weak.promote();
208 if (weakNode == nullptr || !weakNode->startingWinSurfaceNode_) {
209 WLOGFE("windowNode or startingWinSurfaceNode_ is nullptr");
210 return WMError::WM_ERROR_NULLPTR;
211 }
212 StartAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast<int32_t>(TraceTaskId::START_WINDOW_ANIMATION),
213 "StartingWindowAnimate(%u)", weakNode->GetWindowId());
214 weakNode->startingWinSurfaceNode_->SetAlpha(animationConfig_.startWinAnimationConfig_.opacityStart_);
215 auto execute = [weak]() {
216 auto weakNode = weak.promote();
217 if (weakNode == nullptr) {
218 WLOGFE("windowNode is nullptr");
219 return;
220 }
221 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "StartingWindow:ExecuteAnimate(%d)",
222 weakNode->GetWindowId());
223 weakNode->startingWinSurfaceNode_->SetAlpha(animationConfig_.startWinAnimationConfig_.opacityEnd_);
224 };
225
226 auto finish = [weak]() {
227 auto weakNode = weak.promote();
228 if (weakNode == nullptr || weakNode->leashWinSurfaceNode_ == nullptr) {
229 WLOGFE("windowNode or leashWinSurfaceNode_ is nullptr");
230 return;
231 }
232 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "StartingWindow:AnimateFinish(%d)",
233 weakNode->GetWindowId());
234 WLOGFI("StartingWindow::Replace surfaceNode, id: %{public}u", weakNode->GetWindowId());
235 weakNode->leashWinSurfaceNode_->RemoveChild(weakNode->startingWinSurfaceNode_);
236 weakNode->startingWinSurfaceNode_ = nullptr;
237 RSTransaction::FlushImplicitTransaction();
238 FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast<int32_t>(TraceTaskId::START_WINDOW_ANIMATION),
239 "StartingWindowAnimate(%u)", weakNode->GetWindowId());
240 };
241 RSNode::Animate(animationConfig_.startWinAnimationConfig_.timingProtocol_,
242 animationConfig_.startWinAnimationConfig_.timingCurve_, execute, finish);
243 RSTransaction::FlushImplicitTransaction();
244 FinishTrace(HITRACE_TAG_WINDOW_MANAGER);
245 return WMError::WM_OK;
246 }
247
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)248 void StartingWindow::HandleClientWindowCreate(sptr<WindowNode>& node, sptr<IWindow>& window,
249 uint32_t& windowId, const std::shared_ptr<RSSurfaceNode>& surfaceNode, sptr<WindowProperty>& property,
250 int32_t pid, int32_t uid)
251 {
252 if (node == nullptr) {
253 WLOGFE("node is nullptr");
254 return;
255 }
256 node->surfaceNode_ = surfaceNode;
257 node->SetWindowToken(window);
258 node->SetCallingPid(pid);
259 node->SetCallingUid(uid);
260 windowId = node->GetWindowId();
261 // test
262 node->stateMachine_.SetWindowId(windowId);
263 node->stateMachine_.SetWindowType(property->GetWindowType());
264 WLOGI("after set Id:%{public}u, requestRect:[%{public}d, %{public}d, %{public}u, %{public}u]",
265 node->GetWindowId(), node->GetRequestRect().posX_, node->GetRequestRect().posY_,
266 node->GetRequestRect().width_, node->GetRequestRect().height_);
267 // Register FirstFrame Callback to rs, replace startwin
268 wptr<WindowNode> weak = node;
269 auto firstFrameCompleteCallback = [weak]() {
270 auto task = [weak]() {
271 FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast<int32_t>(TraceTaskId::STARTING_WINDOW),
272 "wms:async:ShowStartingWindow");
273 auto weakNode = weak.promote();
274 if (weakNode == nullptr || weakNode->leashWinSurfaceNode_ == nullptr) {
275 WLOGFE("windowNode or leashWinSurfaceNode_ is nullptr");
276 return;
277 }
278 WLOGI("StartingWindow::FirstFrameCallback come, id: %{public}u", weakNode->GetWindowId());
279 if (transAnimateEnable_) {
280 SetStartingWindowAnimation(weakNode);
281 } else {
282 weakNode->leashWinSurfaceNode_->RemoveChild(weakNode->startingWinSurfaceNode_);
283 weakNode->startingWinSurfaceNode_ = nullptr;
284 RSTransaction::FlushImplicitTransaction();
285 WLOGFI("StartingWindow::Replace surfaceNode, id: %{public}u", weakNode->GetWindowId());
286 }
287 WindowInnerManager::GetInstance().CompleteFirstFrameDrawing(weakNode);
288 weakNode->firstFrameAvailable_ = true;
289 };
290 WindowManagerService::GetInstance().PostAsyncTask(task, "firstFrameCompleteCallback");
291 };
292 node->surfaceNode_->SetBufferAvailableCallback(firstFrameCompleteCallback);
293 RSTransaction::FlushImplicitTransaction();
294 }
295
ReleaseStartWinSurfaceNode(sptr<WindowNode> & node)296 void StartingWindow::ReleaseStartWinSurfaceNode(sptr<WindowNode>& node)
297 {
298 std::lock_guard<std::recursive_mutex> lock(mutex_);
299 if (!node->leashWinSurfaceNode_) {
300 WLOGI("cannot release leashwindow since leash is null, id:%{public}u", node->GetWindowId());
301 return;
302 }
303 node->leashWinSurfaceNode_->RemoveChild(node->startingWinSurfaceNode_);
304 node->leashWinSurfaceNode_->RemoveChild(node->closeWinSurfaceNode_);
305 node->leashWinSurfaceNode_->RemoveChild(node->surfaceNode_);
306 node->leashWinSurfaceNode_ = nullptr;
307 node->startingWinSurfaceNode_ = nullptr;
308 node->closeWinSurfaceNode_ = nullptr;
309 WLOGI("Release startwindow surfaceNode end id: %{public}u, [leashWinSurface]: use_count: %{public}ld, \
310 [startWinSurface]: use_count: %{public}ld ", node->GetWindowId(),
311 node->leashWinSurfaceNode_.use_count(), node->startingWinSurfaceNode_.use_count());
312 RSTransaction::FlushImplicitTransaction();
313 }
314
IsWindowFollowParent(WindowType type)315 bool StartingWindow::IsWindowFollowParent(WindowType type)
316 {
317 auto isPhone = uiType_ == UI_TYPE_PHONE;
318 if (!isPhone) {
319 return false;
320 }
321 return WindowHelper::IsWindowFollowParent(type);
322 }
323
AddNodeOnRSTree(sptr<WindowNode> & node,bool isMultiDisplay)324 void StartingWindow::AddNodeOnRSTree(sptr<WindowNode>& node, bool isMultiDisplay)
325 {
326 auto updateRSTreeFunc = [&node, isMultiDisplay]() {
327 UpdateRSTree(node, isMultiDisplay);
328 };
329 wptr<WindowNode> weakNode = node;
330 auto finishCallBack = [weakNode]() {
331 auto weak = weakNode.promote();
332 if (weak == nullptr) {
333 return;
334 }
335 auto winRect = weak->GetWindowRect();
336 WLOGI("before setBounds windowRect: %{public}d, %{public}d, %{public}d, %{public}d",
337 winRect.posX_, winRect.posY_, winRect.width_, winRect.height_);
338 if (weak->leashWinSurfaceNode_) {
339 weak->leashWinSurfaceNode_->SetBounds(winRect.posX_, winRect.posY_, winRect.width_, winRect.height_);
340 weak->leashWinSurfaceNode_->SetAnimationFinished();
341 }
342 RSTransaction::FlushImplicitTransaction();
343 };
344 if (!RemoteAnimation::CheckAnimationController()) {
345 RSNode::Animate(animationConfig_.windowAnimationConfig_.animationTiming_.timingProtocol_,
346 animationConfig_.windowAnimationConfig_.animationTiming_.timingCurve_,
347 updateRSTreeFunc, finishCallBack);
348 } else {
349 // add or remove window without animation
350 updateRSTreeFunc();
351 }
352 }
353
UpdateRSTree(sptr<WindowNode> & node,bool isMultiDisplay)354 void StartingWindow::UpdateRSTree(sptr<WindowNode>& node, bool isMultiDisplay)
355 {
356 auto& dms = DisplayManagerServiceInner::GetInstance();
357 DisplayId displayId = node->GetDisplayId();
358 if (!node->surfaceNode_) { // cold start
359 if (!WindowHelper::IsMainWindow(node->GetWindowType())) {
360 TLOGE(WmsLogTag::WMS_MAIN, "window id: %{public}d type: %{public}u is not Main Window!",
361 node->GetWindowId(), static_cast<uint32_t>(node->GetWindowType()));
362 }
363 dms.UpdateRSTree(displayId, displayId, node->leashWinSurfaceNode_, true, isMultiDisplay);
364 node->leashWinSurfaceNode_->AddChild(node->startingWinSurfaceNode_, -1);
365 TLOGD(WmsLogTag::WMS_MAIN, "Add startingWinSurfaceNode_ to leashWinSurfaceNode_ end during cold start");
366 return;
367 }
368 // hot start
369 const auto& displayIdVec = node->GetShowingDisplays();
370 for (auto& shownDisplayId : displayIdVec) {
371 if (node->leashWinSurfaceNode_) { // to app
372 dms.UpdateRSTree(shownDisplayId, shownDisplayId, node->leashWinSurfaceNode_, true, isMultiDisplay);
373 } else { // to launcher
374 dms.UpdateRSTree(shownDisplayId, shownDisplayId, node->surfaceNode_, true, isMultiDisplay);
375 }
376 for (auto& child : node->children_) {
377 if (IsWindowFollowParent(child->GetWindowType())) {
378 continue;
379 }
380 if (child->currentVisibility_) {
381 dms.UpdateRSTree(shownDisplayId, shownDisplayId, child->surfaceNode_, true, isMultiDisplay);
382 }
383 }
384 }
385 TLOGD(WmsLogTag::WMS_MAIN, "Update RsTree with hot start");
386 }
387
SetDefaultWindowMode(WindowMode defaultMode)388 void StartingWindow::SetDefaultWindowMode(WindowMode defaultMode)
389 {
390 defaultMode_ = defaultMode;
391 }
392
SetAnimationConfig(AnimationConfig config)393 void StartingWindow::SetAnimationConfig(AnimationConfig config)
394 {
395 animationConfig_ = config;
396 }
397 } // Rosen
398 } // OHOS
399