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