1 /*
2 * Copyright (c) 2022-2025 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 <ability_manager_client.h>
17 #include <common/rs_common_def.h>
18 #include <display_manager_service_inner.h>
19 #include <hitrace_meter.h>
20 #include <res_config.h>
21 #include <transaction/rs_transaction.h>
22
23 #include "display_group_info.h"
24 #include "remote_animation.h"
25 #include "rs_adapter.h"
26 #include "starting_window.h"
27 #include "window_helper.h"
28 #include "window_inner_manager.h"
29 #include "window_manager_hilog.h"
30 #include "window_manager_service.h"
31 #include "window_manager_service_utils.h"
32 #include "window_system_effect.h"
33
34 namespace OHOS {
35 namespace Rosen {
36 namespace {
37 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "StartingWindow"};
38 constexpr int32_t DEFAULT_GIF_DELAY = 100; //default delay time for gif
39 }
40
41 const std::map<OHOS::AppExecFwk::DisplayOrientation, Orientation> ABILITY_TO_WMS_ORIENTATION_MAP {
42 {OHOS::AppExecFwk::DisplayOrientation::UNSPECIFIED, Orientation::UNSPECIFIED},
43 {OHOS::AppExecFwk::DisplayOrientation::LANDSCAPE, Orientation::HORIZONTAL},
44 {OHOS::AppExecFwk::DisplayOrientation::PORTRAIT, Orientation::VERTICAL},
45 {OHOS::AppExecFwk::DisplayOrientation::FOLLOWRECENT, Orientation::LOCKED},
46 {OHOS::AppExecFwk::DisplayOrientation::LANDSCAPE_INVERTED, Orientation::REVERSE_HORIZONTAL},
47 {OHOS::AppExecFwk::DisplayOrientation::PORTRAIT_INVERTED, Orientation::REVERSE_VERTICAL},
48 {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION, Orientation::SENSOR},
49 {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION_LANDSCAPE, Orientation::SENSOR_HORIZONTAL},
50 {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION_PORTRAIT, Orientation::SENSOR_VERTICAL},
51 {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION_RESTRICTED, Orientation::AUTO_ROTATION_RESTRICTED},
52 {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION_LANDSCAPE_RESTRICTED,
53 Orientation::AUTO_ROTATION_LANDSCAPE_RESTRICTED},
54 {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION_PORTRAIT_RESTRICTED,
55 Orientation::AUTO_ROTATION_PORTRAIT_RESTRICTED},
56 {OHOS::AppExecFwk::DisplayOrientation::LOCKED, Orientation::LOCKED},
57 };
58
59 std::recursive_mutex StartingWindow::mutex_;
60 WindowMode StartingWindow::defaultMode_ = WindowMode::WINDOW_MODE_FULLSCREEN;
61 bool StartingWindow::transAnimateEnable_ = true;
62 WindowUIType StartingWindow::windowUIType_ = WindowUIType::INVALID_WINDOW;
63 AnimationConfig StartingWindow::animationConfig_;
64 StartingWindowShowInfo StartingWindow::startingWindowShowInfo_;
65 std::atomic<bool> StartingWindow::startingWindowShowRunning_{false};
66 std::thread StartingWindow::startingWindowShowThread_;
67 std::mutex StartingWindow::firstFrameMutex_;
68 std::condition_variable StartingWindow::firstFrameCondition_;
69 std::atomic<bool> StartingWindow::firstFrameCompleted_ = false;
70
RegisterStartingWindowShowInfo(const sptr<WindowNode> & node,const Rect & rect,const std::shared_ptr<Rosen::StartingWindowPageDrawInfo> & info,float vpRatio)71 void StartingWindow::RegisterStartingWindowShowInfo(const sptr<WindowNode>& node, const Rect& rect,
72 const std::shared_ptr<Rosen::StartingWindowPageDrawInfo>& info, float vpRatio)
73 {
74 StartingWindowShowInfo startingWindowShowInfo { node, rect, info, vpRatio };
75 std::array<std::weak_ptr<Rosen::ResourceInfo>, size_t(StartWindowResType::Count)> resources = {
76 info->appIcon, info->illustration, info->branding, info->bgImage
77 };
78 auto now = std::chrono::steady_clock::now();
79 for (size_t i = 0; i < resources.size(); ++i) {
80 auto resInfo = resources[i].lock();
81 auto& state = startingWindowShowInfo.resStates[i];
82 if (!resInfo) {
83 TLOGE(WmsLogTag::WMS_PATTERN, "null resource to record frame index.");
84 state.frameCount = 0;
85 continue;
86 }
87 state.delay = (!resInfo->delayTimes.empty()) ? resInfo->delayTimes : std::vector<int32_t>{ INT32_MAX };
88 if (std::all_of(state.delay.begin(), state.delay.end(), [](int32_t delay) { return delay == 0; })) {
89 for (auto& delay : state.delay) {
90 TLOGD(WmsLogTag::WMS_PATTERN, "Invalid delay time: %{public}d", delay);
91 delay = DEFAULT_GIF_DELAY;
92 }
93 }
94 state.frameCount = (resInfo->pixelMaps.size() > 1) ? resInfo->pixelMaps.size() : 1;
95 state.next = now;
96 }
97 startingWindowShowInfo_ = std::move(startingWindowShowInfo);
98 }
99
UnRegisterStartingWindowShowInfo()100 void StartingWindow::UnRegisterStartingWindowShowInfo()
101 {
102 auto cleanResource = [](std::shared_ptr<Rosen::ResourceInfo>& resInfo) {
103 if (resInfo) {
104 for (auto& pixelMap : resInfo->pixelMaps) {
105 pixelMap->FreePixelMap();
106 }
107 resInfo->pixelMaps.clear();
108 resInfo->delayTimes.clear();
109 resInfo.reset();
110 }
111 };
112 if (startingWindowShowInfo_.info) {
113 cleanResource(startingWindowShowInfo_.info->appIcon);
114 cleanResource(startingWindowShowInfo_.info->bgImage);
115 cleanResource(startingWindowShowInfo_.info->illustration);
116 cleanResource(startingWindowShowInfo_.info->branding);
117 }
118 startingWindowShowInfo_.info.reset();
119 TLOGE(WmsLogTag::WMS_PATTERN, "starting window draw resource cleaned.");
120 }
121
UpdateWindowShowInfo(StartingWindowShowInfo & startingWindowShowInfo,bool & needRedraw)122 void StartingWindow::UpdateWindowShowInfo(StartingWindowShowInfo& startingWindowShowInfo, bool& needRedraw)
123 {
124 for (size_t i = 0; i < startingWindowShowInfo.resStates.size(); ++i) {
125 auto& state = startingWindowShowInfo.resStates[i];
126 auto now = std::chrono::steady_clock::now();
127 if (state.frameCount == 0 || now < state.next) {
128 TLOGD(WmsLogTag::WMS_PATTERN, "null resource or not time yet");
129 continue;
130 }
131 state.frameIdx = (state.frameIdx + 1) % state.frameCount;
132 state.next = now + std::chrono::milliseconds(state.delay[state.frameIdx]);
133 startingWindowShowInfo.frameIndex[i] = state.frameIdx;
134 needRedraw = true;
135 }
136 }
137
DrawStartingWindowShowInfo()138 void StartingWindow::DrawStartingWindowShowInfo()
139 {
140 startingWindowShowRunning_ = true;
141 int32_t minDelay(DEFAULT_GIF_DELAY);
142 for (const auto& state : startingWindowShowInfo_.resStates) {
143 for (int32_t delay : state.delay) {
144 if (delay > 0 && delay < minDelay) {
145 minDelay = delay;
146 }
147 }
148 }
149 auto drawTask = [minDelay]() {
150 bool firstDraw = true;
151 while (startingWindowShowRunning_.load()) {
152 bool needRedraw = false;
153 UpdateWindowShowInfo(startingWindowShowInfo_, needRedraw);
154 if (!needRedraw) {
155 TLOGD(WmsLogTag::WMS_PATTERN, "no resource updated need to draw.");
156 continue;
157 }
158 bool ret = SurfaceDraw::DrawCustomStartingWindow(
159 startingWindowShowInfo_.node.promote()->startingWinSurfaceNode_,
160 startingWindowShowInfo_.rect,
161 startingWindowShowInfo_.info,
162 startingWindowShowInfo_.vpRatio,
163 startingWindowShowInfo_.frameIndex);
164 if (firstDraw && !ret) {
165 std::unique_lock<std::mutex> lock(firstFrameMutex_);
166 startingWindowShowRunning_ = false;
167 firstFrameCompleted_ = true;
168 firstFrameCondition_.notify_one();
169 TLOGE(WmsLogTag::WMS_PATTERN, "Failed to draw first frame of StartingWindow.");
170 break;
171 }
172 if (firstDraw) {
173 std::unique_lock<std::mutex> lock(firstFrameMutex_);
174 firstFrameCompleted_ = true;
175 firstFrameCondition_.notify_one();
176 firstDraw = false;
177 }
178 std::this_thread::sleep_for(std::chrono::milliseconds(minDelay));
179 }
180 };
181 startingWindowShowThread_ = std::thread(drawTask);
182 }
183
CreateWindowNode(const sptr<WindowTransitionInfo> & info,uint32_t winId)184 sptr<WindowNode> StartingWindow::CreateWindowNode(const sptr<WindowTransitionInfo>& info, uint32_t winId)
185 {
186 sptr<WindowProperty> property = InitializeWindowProperty(info, winId);
187 if (property == nullptr) {
188 return nullptr;
189 }
190
191 sptr<WindowNode> node = new(std::nothrow) WindowNode(property);
192 if (node == nullptr) {
193 return nullptr;
194 }
195
196 node->stateMachine_.SetWindowId(winId);
197 node->abilityToken_ = info->GetAbilityToken();
198 node->SetWindowSizeLimits(info->GetWindowSizeLimits());
199 node->abilityInfo_.missionId_ = info->GetMissionId();
200 node->abilityInfo_.bundleName_ = info->GetBundleName();
201 node->abilityInfo_.abilityName_ = info->GetAbilityName();
202 uint32_t windowModeSupportType = WindowHelper::ConvertSupportModesToSupportType(info->GetWindowSupportModes());
203 node->SetWindowModeSupportType(windowModeSupportType);
204
205 if (CreateLeashAndStartingSurfaceNode(node) != WMError::WM_OK) {
206 return nullptr;
207 }
208 node->stateMachine_.TransitionTo(WindowNodeState::STARTING_CREATED);
209 return node;
210 }
211
InitializeWindowProperty(const sptr<WindowTransitionInfo> & info,uint32_t winId)212 sptr<WindowProperty> StartingWindow::InitializeWindowProperty(const sptr<WindowTransitionInfo>& info, uint32_t winId)
213 {
214 sptr<WindowProperty> property = new(std::nothrow) WindowProperty();
215 if (property == nullptr || info == nullptr) {
216 return nullptr;
217 }
218
219 property->SetRequestRect(info->GetWindowRect());
220 if (WindowHelper::IsValidWindowMode(info->GetWindowMode())) {
221 property->SetWindowMode(info->GetWindowMode());
222 } else {
223 property->SetWindowMode(defaultMode_);
224 }
225
226 AppExecFwk::DisplayOrientation displayOrientation = info->GetOrientation();
227 if (ABILITY_TO_WMS_ORIENTATION_MAP.count(displayOrientation) == 0) {
228 WLOGFE("id:%{public}u Do not support this Orientation type", winId);
229 return nullptr;
230 }
231 Orientation orientation = ABILITY_TO_WMS_ORIENTATION_MAP.at(displayOrientation);
232 if (orientation < Orientation::BEGIN || orientation > Orientation::END) {
233 WLOGFE("Set orientation from ability failed");
234 return nullptr;
235 }
236 property->SetRequestedOrientation(orientation);
237
238 property->SetDisplayId(info->GetDisplayId());
239 property->SetWindowType(info->GetWindowType());
240
241 ChangePropertyByApiVersion(info, orientation, property);
242 property->SetApiCompatibleVersion(info->GetApiCompatibleVersion());
243 if (info->GetShowFlagWhenLocked()) {
244 if (property->GetApiCompatibleVersion() < 9 || info->isSystemCalling_) { // 9: api version.
245 property->AddWindowFlag(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED);
246 } else {
247 WLOGFW("Only API 9- or system calling support showing when locked.");
248 }
249 }
250 property->SetWindowId(winId);
251 return property;
252 }
253
ChangePropertyByApiVersion(const sptr<WindowTransitionInfo> & info,const Orientation orientation,sptr<WindowProperty> & property)254 void StartingWindow::ChangePropertyByApiVersion(const sptr<WindowTransitionInfo>& info,
255 const Orientation orientation, sptr<WindowProperty>& property)
256 {
257 // 10 ArkUI new framework support after API10
258 if (info->GetApiCompatibleVersion() < 10) {
259 auto displayInfo = DisplayGroupInfo::GetInstance().GetDisplayInfo(info->GetDisplayId());
260 if (!(displayInfo && WmsUtils::IsExpectedRotatableWindow(orientation,
261 displayInfo->GetDisplayOrientation(), property->GetWindowMode(), property->GetWindowFlags(), false))) {
262 property->AddWindowFlag(WindowFlag::WINDOW_FLAG_NEED_AVOID);
263 }
264 } else {
265 if (WindowHelper::IsMainWindow(property->GetWindowType())) {
266 SystemBarProperty statusSystemBarProperty(true, 0x00FFFFFF, 0xFF000000);
267 SystemBarProperty navigationSystemBarProperty(true, 0x00FFFFFF, 0xFF000000);
268 property->SetSystemBarProperty(WindowType::WINDOW_TYPE_STATUS_BAR, statusSystemBarProperty);
269 property->SetSystemBarProperty(WindowType::WINDOW_TYPE_NAVIGATION_BAR, navigationSystemBarProperty);
270 }
271 }
272 }
273
CreateLeashAndStartingSurfaceNode(sptr<WindowNode> & node)274 WMError StartingWindow::CreateLeashAndStartingSurfaceNode(sptr<WindowNode>& node)
275 {
276 struct RSSurfaceNodeConfig rsSurfaceNodeConfig;
277 rsSurfaceNodeConfig.SurfaceNodeName = "leashWindow" + std::to_string(node->GetWindowId());
278 auto rsUIContext = node->GetRSUIContext();
279 node->leashWinSurfaceNode_ = RSSurfaceNode::Create(
280 rsSurfaceNodeConfig, RSSurfaceNodeType::LEASH_WINDOW_NODE, true, false, rsUIContext);
281 if (node->leashWinSurfaceNode_ == nullptr) {
282 TLOGE(WmsLogTag::WMS_STARTUP_PAGE, "create leashWinSurfaceNode failed");
283 return WMError::WM_ERROR_NULLPTR;
284 }
285 RSAdapterUtil::SetSkipCheckInMultiInstance(node->leashWinSurfaceNode_, true);
286 TLOGD(WmsLogTag::WMS_SCB, "Create RSSurfaceNode: %{public}s, name: %{public}s",
287 RSAdapterUtil::RSNodeToStr(node->leashWinSurfaceNode_).c_str(),
288 rsSurfaceNodeConfig.SurfaceNodeName.c_str());
289
290 rsSurfaceNodeConfig.SurfaceNodeName = "startingWindow" + std::to_string(node->GetWindowId());
291 node->startingWinSurfaceNode_ = RSSurfaceNode::Create(
292 rsSurfaceNodeConfig, RSSurfaceNodeType::STARTING_WINDOW_NODE, true, false, rsUIContext);
293 if (node->startingWinSurfaceNode_ == nullptr) {
294 TLOGE(WmsLogTag::WMS_STARTUP_PAGE, "create startingWinSurfaceNode failed");
295 node->leashWinSurfaceNode_ = nullptr;
296 return WMError::WM_ERROR_NULLPTR;
297 }
298 RSAdapterUtil::SetSkipCheckInMultiInstance(node->startingWinSurfaceNode_, true);
299 TLOGD(WmsLogTag::WMS_SCB, "Create RSSurfaceNode: %{public}s, name: %{public}s",
300 RSAdapterUtil::RSNodeToStr(node->startingWinSurfaceNode_).c_str(),
301 rsSurfaceNodeConfig.SurfaceNodeName.c_str());
302 TLOGI(WmsLogTag::WMS_STARTUP_PAGE,
303 "Create leashWinSurfaceNode and startingWinSurfaceNode success with id:%{public}u!",
304 node->GetWindowId());
305 return WMError::WM_OK;
306 }
307
DrawStartingWindow(sptr<WindowNode> & node,std::shared_ptr<Media::PixelMap> pixelMap,uint32_t bkgColor,bool isColdStart)308 WMError StartingWindow::DrawStartingWindow(sptr<WindowNode>& node,
309 std::shared_ptr<Media::PixelMap> pixelMap, uint32_t bkgColor, bool isColdStart)
310 {
311 if (node == nullptr) {
312 return WMError::WM_ERROR_NULLPTR;
313 }
314 // using snapshot to support hot start since node destroy when hide
315 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "wms:DrawStartingWindow(%u)", node->GetWindowId());
316 Rect rect = node->GetWindowRect();
317 if (RemoteAnimation::CheckRemoteAnimationEnabled(node->GetDisplayId()) && node->leashWinSurfaceNode_) {
318 // hides this node until RSProxyNode send valid context alpha/matrix
319 node->leashWinSurfaceNode_->ResetContextAlpha();
320 }
321 if (!isColdStart) {
322 return WMError::WM_OK;
323 }
324 if (node->startingWinSurfaceNode_ == nullptr) {
325 TLOGE(WmsLogTag::WMS_STARTUP_PAGE, "no starting Window SurfaceNode!");
326 return WMError::WM_ERROR_NULLPTR;
327 }
328 auto staringWindowPageDrawInfo = GetCustomStartingWindowInfo(node, GetBundleManager());
329 if (staringWindowPageDrawInfo) {
330 if (DrawStartingWindow(staringWindowPageDrawInfo, node, rect) == WMError::WM_OK) {
331 return WMError::WM_OK;
332 }
333 }
334 // set window effect
335 WindowSystemEffect::SetWindowEffect(node);
336 if (pixelMap == nullptr) {
337 SurfaceDraw::DrawColor(node->startingWinSurfaceNode_, rect.width_, rect.height_, bkgColor);
338 return WMError::WM_OK;
339 }
340
341 TLOGD(WmsLogTag::WMS_STARTUP_PAGE, "draw background in sperate");
342 SurfaceDraw::DrawImageRect(node->startingWinSurfaceNode_, rect, pixelMap, bkgColor);
343 return WMError::WM_OK;
344 }
345
SetStartingWindowAnimation(wptr<WindowNode> weak)346 WMError StartingWindow::SetStartingWindowAnimation(wptr<WindowNode> weak)
347 {
348 auto weakNode = weak.promote();
349 if (weakNode == nullptr || !weakNode->startingWinSurfaceNode_) {
350 TLOGE(WmsLogTag::WMS_STARTUP_PAGE, "windowNode or startingWinSurfaceNode_ is nullptr");
351 return WMError::WM_ERROR_NULLPTR;
352 }
353 StartAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast<int32_t>(TraceTaskId::START_WINDOW_ANIMATION),
354 "StartingWindowAnimate(%u)", weakNode->GetWindowId());
355 weakNode->startingWinSurfaceNode_->SetAlpha(animationConfig_.startWinAnimationConfig_.opacityStart_);
356 auto execute = [weak]() {
357 auto weakNode = weak.promote();
358 if (weakNode == nullptr) {
359 TLOGNE(WmsLogTag::WMS_STARTUP_PAGE, "windowNode is nullptr");
360 return;
361 }
362 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "StartingWindow:ExecuteAnimate(%d)",
363 weakNode->GetWindowId());
364 weakNode->startingWinSurfaceNode_->SetAlpha(animationConfig_.startWinAnimationConfig_.opacityEnd_);
365 };
366
367 auto finish = [weak]() {
368 auto weakNode = weak.promote();
369 if (weakNode == nullptr || weakNode->leashWinSurfaceNode_ == nullptr) {
370 TLOGE(WmsLogTag::WMS_STARTUP_PAGE, "windowNode or leashWinSurfaceNode_ is nullptr");
371 return;
372 }
373 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "StartingWindow:AnimateFinish(%d)",
374 weakNode->GetWindowId());
375 TLOGNI(WmsLogTag::WMS_STARTUP_PAGE, "StartingWindow::Replace surfaceNode, id: %{public}u",
376 weakNode->GetWindowId());
377 weakNode->leashWinSurfaceNode_->RemoveChild(weakNode->startingWinSurfaceNode_);
378 weakNode->startingWinSurfaceNode_ = nullptr;
379 RSTransactionAdapter::FlushImplicitTransaction(weakNode->leashWinSurfaceNode_);
380 FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast<int32_t>(TraceTaskId::START_WINDOW_ANIMATION),
381 "StartingWindowAnimate(%u)", weakNode->GetWindowId());
382 };
383 auto rsUIContext = weakNode->startingWinSurfaceNode_->GetRSUIContext();
384 RSNode::Animate(rsUIContext, animationConfig_.startWinAnimationConfig_.timingProtocol_,
385 animationConfig_.startWinAnimationConfig_.timingCurve_, execute, finish);
386 RSTransactionAdapter::FlushImplicitTransaction(rsUIContext);
387 FinishTrace(HITRACE_TAG_WINDOW_MANAGER);
388 return WMError::WM_OK;
389 }
390
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)391 void StartingWindow::HandleClientWindowCreate(sptr<WindowNode>& node, sptr<IWindow>& window,
392 uint32_t& windowId, const std::shared_ptr<RSSurfaceNode>& surfaceNode, sptr<WindowProperty>& property,
393 int32_t pid, int32_t uid)
394 {
395 if (node == nullptr) {
396 TLOGE(WmsLogTag::WMS_STARTUP_PAGE, "node is nullptr");
397 return;
398 }
399 node->surfaceNode_ = surfaceNode;
400 node->SetWindowToken(window);
401 node->SetCallingPid(pid);
402 node->SetCallingUid(uid);
403 windowId = node->GetWindowId();
404 // test
405 node->stateMachine_.SetWindowId(windowId);
406 node->stateMachine_.SetWindowType(property->GetWindowType());
407 TLOGI(WmsLogTag::WMS_STARTUP_PAGE, "after set Id:%{public}u, "
408 "requestRect:[%{public}d, %{public}d, %{public}u, %{public}u]",
409 node->GetWindowId(), node->GetRequestRect().posX_, node->GetRequestRect().posY_,
410 node->GetRequestRect().width_, node->GetRequestRect().height_);
411 // Register FirstFrame Callback to rs, replace startwin
412 wptr<WindowNode> weak = node;
413 auto firstFrameCompleteCallback = [weak]() {
414 auto task = [weak]() {
415 FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast<int32_t>(TraceTaskId::STARTING_WINDOW),
416 "wms:async:ShowStartingWindow");
417 auto weakNode = weak.promote();
418 if (weakNode == nullptr || weakNode->leashWinSurfaceNode_ == nullptr) {
419 TLOGNE(WmsLogTag::WMS_STARTUP_PAGE, "windowNode or leashWinSurfaceNode_ is nullptr");
420 return;
421 }
422 TLOGNI(WmsLogTag::WMS_STARTUP_PAGE, "StartingWindow::FirstFrameCallback come, id: %{public}u",
423 weakNode->GetWindowId());
424 if (transAnimateEnable_) {
425 SetStartingWindowAnimation(weakNode);
426 } else {
427 weakNode->leashWinSurfaceNode_->RemoveChild(weakNode->startingWinSurfaceNode_);
428 weakNode->startingWinSurfaceNode_ = nullptr;
429 RSTransactionAdapter::FlushImplicitTransaction(weakNode->leashWinSurfaceNode_);
430 TLOGNI(WmsLogTag::WMS_STARTUP_PAGE, "StartingWindow::Replace surfaceNode, id: %{public}u",
431 weakNode->GetWindowId());
432 }
433 WindowInnerManager::GetInstance().CompleteFirstFrameDrawing(weakNode);
434 weakNode->firstFrameAvailable_ = true;
435 startingWindowShowRunning_ = false;
436 if (startingWindowShowThread_.joinable()) {
437 startingWindowShowThread_.join();
438 }
439 UnRegisterStartingWindowShowInfo();
440 };
441 WindowManagerService::GetInstance().PostAsyncTask(task, "firstFrameCompleteCallback");
442 };
443 node->surfaceNode_->SetBufferAvailableCallback(firstFrameCompleteCallback);
444 RSTransactionAdapter::FlushImplicitTransaction(node->surfaceNode_);
445 }
446
ReleaseStartWinSurfaceNode(sptr<WindowNode> & node)447 void StartingWindow::ReleaseStartWinSurfaceNode(sptr<WindowNode>& node)
448 {
449 std::lock_guard<std::recursive_mutex> lock(mutex_);
450 if (!node->leashWinSurfaceNode_) {
451 TLOGI(WmsLogTag::WMS_STARTUP_PAGE, "cannot release leashwindow since leash is null, id:%{public}u",
452 node->GetWindowId());
453 return;
454 }
455 if (startingWindowShowRunning_.load()) {
456 startingWindowShowRunning_ = false;
457 if (startingWindowShowThread_.joinable()) {
458 startingWindowShowThread_.join();
459 }
460 UnRegisterStartingWindowShowInfo();
461 }
462 node->leashWinSurfaceNode_->RemoveChild(node->startingWinSurfaceNode_);
463 node->leashWinSurfaceNode_->RemoveChild(node->closeWinSurfaceNode_);
464 node->leashWinSurfaceNode_->RemoveChild(node->surfaceNode_);
465 RSTransactionAdapter::FlushImplicitTransaction(node->leashWinSurfaceNode_);
466 node->leashWinSurfaceNode_ = nullptr;
467 node->startingWinSurfaceNode_ = nullptr;
468 node->closeWinSurfaceNode_ = nullptr;
469 TLOGI(WmsLogTag::WMS_STARTUP_PAGE, "Release startwindow surfaceNode end id: %{public}u, "
470 "[leashWinSurface]: use_count: %{public}ld, [startWinSurface]: use_count: %{public}ld ",
471 node->GetWindowId(), node->leashWinSurfaceNode_.use_count(),
472 node->startingWinSurfaceNode_.use_count());
473 }
474
IsWindowFollowParent(WindowType type)475 bool StartingWindow::IsWindowFollowParent(WindowType type)
476 {
477 if (windowUIType_ != WindowUIType::PHONE_WINDOW) {
478 return false;
479 }
480 return WindowHelper::IsWindowFollowParent(type);
481 }
482
AddNodeOnRSTree(sptr<WindowNode> & node,bool isMultiDisplay)483 void StartingWindow::AddNodeOnRSTree(sptr<WindowNode>& node, bool isMultiDisplay)
484 {
485 auto updateRSTreeFunc = [&node, isMultiDisplay]() {
486 UpdateRSTree(node, isMultiDisplay);
487 };
488 wptr<WindowNode> weakNode = node;
489 auto finishCallBack = [weakNode]() {
490 auto weak = weakNode.promote();
491 if (weak == nullptr) {
492 return;
493 }
494 auto winRect = weak->GetWindowRect();
495 TLOGI(WmsLogTag::WMS_STARTUP_PAGE,
496 "before setBounds windowRect: %{public}d, %{public}d, %{public}d, %{public}d",
497 winRect.posX_, winRect.posY_, winRect.width_, winRect.height_);
498 if (weak->leashWinSurfaceNode_) {
499 weak->leashWinSurfaceNode_->SetBounds(winRect.posX_, winRect.posY_, winRect.width_, winRect.height_);
500 weak->leashWinSurfaceNode_->SetAnimationFinished();
501 }
502 RSTransactionAdapter::FlushImplicitTransaction(weak->leashWinSurfaceNode_);
503 };
504 if (!RemoteAnimation::CheckAnimationController()) {
505 std::shared_ptr<RSUIContext> rsUIContext;
506 if (node->leashWinSurfaceNode_) {
507 rsUIContext = node->leashWinSurfaceNode_->GetRSUIContext();
508 }
509 RSNode::Animate(rsUIContext, animationConfig_.windowAnimationConfig_.animationTiming_.timingProtocol_,
510 animationConfig_.windowAnimationConfig_.animationTiming_.timingCurve_,
511 updateRSTreeFunc, finishCallBack);
512 } else {
513 // add or remove window without animation
514 updateRSTreeFunc();
515 }
516 }
517
UpdateRSTree(sptr<WindowNode> & node,bool isMultiDisplay)518 void StartingWindow::UpdateRSTree(sptr<WindowNode>& node, bool isMultiDisplay)
519 {
520 auto& dms = DisplayManagerServiceInner::GetInstance();
521 DisplayId displayId = node->GetDisplayId();
522 if (!node->surfaceNode_) { // cold start
523 if (!WindowHelper::IsMainWindow(node->GetWindowType())) {
524 TLOGE(WmsLogTag::WMS_MAIN, "window id: %{public}d type: %{public}u is not Main Window!",
525 node->GetWindowId(), static_cast<uint32_t>(node->GetWindowType()));
526 }
527 dms.UpdateRSTree(displayId, displayId, node->leashWinSurfaceNode_, true, isMultiDisplay);
528 node->leashWinSurfaceNode_->AddChild(node->startingWinSurfaceNode_, -1);
529 TLOGD(WmsLogTag::WMS_MAIN, "Add startingWinSurfaceNode_ to leashWinSurfaceNode_ end during cold start");
530 return;
531 }
532 // hot start
533 const auto& displayIdVec = node->GetShowingDisplays();
534 for (auto& shownDisplayId : displayIdVec) {
535 if (node->leashWinSurfaceNode_) { // to app
536 dms.UpdateRSTree(shownDisplayId, shownDisplayId, node->leashWinSurfaceNode_, true, isMultiDisplay);
537 } else { // to launcher
538 dms.UpdateRSTree(shownDisplayId, shownDisplayId, node->surfaceNode_, true, isMultiDisplay);
539 }
540 for (auto& child : node->children_) {
541 if (IsWindowFollowParent(child->GetWindowType())) {
542 continue;
543 }
544 if (child->currentVisibility_) {
545 dms.UpdateRSTree(shownDisplayId, shownDisplayId, child->surfaceNode_, true, isMultiDisplay);
546 }
547 }
548 }
549 TLOGD(WmsLogTag::WMS_MAIN, "Update RsTree with hot start");
550 }
551
SetDefaultWindowMode(WindowMode defaultMode)552 void StartingWindow::SetDefaultWindowMode(WindowMode defaultMode)
553 {
554 defaultMode_ = defaultMode;
555 }
556
SetAnimationConfig(AnimationConfig config)557 void StartingWindow::SetAnimationConfig(AnimationConfig config)
558 {
559 animationConfig_ = config;
560 }
561
GetBundleManager()562 sptr<AppExecFwk::IBundleMgr> StartingWindow::GetBundleManager()
563 {
564 auto systemAbilityMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
565 if (systemAbilityMgr == nullptr) {
566 TLOGE(WmsLogTag::WMS_PATTERN, "Failed to get SystemAbilityManager.");
567 return nullptr;
568 }
569 auto bmsProxy = systemAbilityMgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
570 if (bmsProxy == nullptr) {
571 TLOGE(WmsLogTag::WMS_PATTERN, "Failed to get BundleManagerService.");
572 return nullptr;
573 }
574 return iface_cast<AppExecFwk::IBundleMgr>(bmsProxy);
575 }
576
GetAbilityInfoFromBMS(const sptr<WindowNode> & node,const sptr<AppExecFwk::IBundleMgr> & bundleMgr)577 std::shared_ptr<AppExecFwk::AbilityInfo> StartingWindow::GetAbilityInfoFromBMS(const sptr<WindowNode>& node,
578 const sptr<AppExecFwk::IBundleMgr>& bundleMgr)
579 {
580 if (node == nullptr || bundleMgr == nullptr) {
581 TLOGE(WmsLogTag::WMS_PATTERN, "node or bundleMgr is nullptr.");
582 return nullptr;
583 }
584 AAFwk::Want want;
585 AppExecFwk::AbilityInfo abilityInfo;
586 want.SetElementName("", node->abilityInfo_.bundleName_, node->abilityInfo_.abilityName_, "");
587 if (!bundleMgr->QueryAbilityInfo(
588 want, AppExecFwk::GET_ABILITY_INFO_DEFAULT, AppExecFwk::Constants::ANY_USERID, abilityInfo)) {
589 TLOGE(WmsLogTag::WMS_PATTERN, "Get ability info from BMS failed!");
590 return nullptr;
591 }
592 return std::make_shared<AppExecFwk::AbilityInfo>(std::move(abilityInfo));
593 }
594
CreateResourceManager(const std::shared_ptr<AppExecFwk::AbilityInfo> & abilityInfo)595 std::shared_ptr<Global::Resource::ResourceManager> StartingWindow::CreateResourceManager(
596 const std::shared_ptr<AppExecFwk::AbilityInfo>& abilityInfo)
597 {
598 if (abilityInfo == nullptr) {
599 TLOGE(WmsLogTag::WMS_PATTERN, "abilityInfo is nullptr.");
600 return nullptr;
601 }
602 std::unique_ptr<Global::Resource::ResConfig> resConfig(Global::Resource::CreateResConfig());
603 if (resConfig == nullptr) {
604 TLOGE(WmsLogTag::WMS_PATTERN, "resConfig is nullptr.");
605 return nullptr;
606 }
607 std::shared_ptr<Global::Resource::ResourceManager> resourceMgr(Global::Resource::CreateResourceManager(
608 abilityInfo->bundleName, abilityInfo->moduleName, "", {}, *resConfig));
609 if (resourceMgr == nullptr) {
610 TLOGE(WmsLogTag::WMS_PATTERN, "resourceMgr is nullptr.");
611 return nullptr;
612 }
613
614 std::string loadPath = abilityInfo->hapPath.empty() ? abilityInfo->resourcePath : abilityInfo->hapPath;
615 if (!resourceMgr->AddResource(loadPath.c_str(), Global::Resource::SELECT_COLOR | Global::Resource::SELECT_MEDIA)) {
616 TLOGE(WmsLogTag::WMS_PATTERN, "Add resource %{private}s failed.", loadPath.c_str());
617 }
618 return resourceMgr;
619 }
620
GetPixelMapListInfo(uint32_t mediaDataId,const std::shared_ptr<Global::Resource::ResourceManager> & resourceMgr,const std::shared_ptr<AppExecFwk::AbilityInfo> & abilityInfo)621 std::shared_ptr<Rosen::ResourceInfo> StartingWindow::GetPixelMapListInfo(uint32_t mediaDataId,
622 const std::shared_ptr<Global::Resource::ResourceManager>& resourceMgr,
623 const std::shared_ptr<AppExecFwk::AbilityInfo>& abilityInfo)
624 {
625 if (mediaDataId <= 0 || resourceMgr == nullptr || abilityInfo == nullptr) {
626 TLOGE(WmsLogTag::WMS_PATTERN, "invalid mediaDataId or null resourceMgr and abilityInfo.");
627 return nullptr;
628 }
629 Media::SourceOptions opts;
630 uint32_t errorCode = 0;
631 std::unique_ptr<Media::ImageSource> imageSource;
632 if (!abilityInfo->hapPath.empty()) {
633 size_t len = 0;
634 std::unique_ptr<uint8_t[]> dataOut;
635 if (resourceMgr->GetMediaDataById(mediaDataId, len, dataOut) != Global::Resource::RState::SUCCESS) {
636 return nullptr;
637 }
638 imageSource = Media::ImageSource::CreateImageSource(dataOut.get(), len, opts, errorCode);
639 } else {
640 std::string dataPath;
641 if (resourceMgr->GetMediaById(mediaDataId, dataPath) != Global::Resource::RState::SUCCESS) {
642 return nullptr;
643 }
644 imageSource = Media::ImageSource::CreateImageSource(dataPath, opts, errorCode);
645 }
646 if (errorCode != 0 || imageSource == nullptr) {
647 TLOGE(WmsLogTag::WMS_PATTERN, "imageSource failed, id %{public}u err %{public}u", mediaDataId, errorCode);
648 return nullptr;
649 }
650 Media::DecodeOptions decodeOpts;
651 auto pixelMapList = imageSource->CreatePixelMapList(decodeOpts, errorCode);
652 if (errorCode != 0) {
653 TLOGE(WmsLogTag::WMS_PATTERN, "pixelMapList failed, id %{public}u err %{public}u", mediaDataId, errorCode);
654 return nullptr;
655 }
656 auto info = std::make_shared<Rosen::ResourceInfo>();
657 std::transform(pixelMapList->begin(), pixelMapList->end(), std::back_inserter(info->pixelMaps),
658 [](auto& ptr) { return std::move(ptr); });
659 if (info->pixelMaps.size() > 1) { // multi frames
660 auto delaytimes = imageSource->GetDelayTime(errorCode);
661 if (errorCode != 0) {
662 TLOGE(WmsLogTag::WMS_PATTERN, "delaytimes failed, id %{public}u err %{public}u", mediaDataId, errorCode);
663 return nullptr;
664 }
665 info->delayTimes = std::move(*delaytimes);
666 }
667 return info;
668 }
669
GetCustomStartingWindowInfo(const sptr<WindowNode> & node,const sptr<AppExecFwk::IBundleMgr> & bundleMgr)670 std::shared_ptr<Rosen::StartingWindowPageDrawInfo> StartingWindow::GetCustomStartingWindowInfo(
671 const sptr<WindowNode>& node, const sptr<AppExecFwk::IBundleMgr>& bundleMgr)
672 {
673 if (node == nullptr || bundleMgr == nullptr) {
674 TLOGE(WmsLogTag::WMS_PATTERN, "node or bundleMgr is nullptr.");
675 return nullptr;
676 }
677 auto abilityInfo = GetAbilityInfoFromBMS(node, bundleMgr);
678 if (abilityInfo == nullptr) {
679 TLOGE(WmsLogTag::WMS_PATTERN, "Failed to retrieve abilityinfo from BMS");
680 return nullptr;
681 }
682 auto resourceMgr = CreateResourceManager(abilityInfo);
683 if (resourceMgr == nullptr) {
684 TLOGE(WmsLogTag::WMS_PATTERN, "Failed to create resource manager");
685 return nullptr;
686 }
687 return DoGetCustomStartingWindowInfo(abilityInfo, resourceMgr);
688 }
689
DoGetCustomStartingWindowInfo(const std::shared_ptr<AppExecFwk::AbilityInfo> & abilityInfo,const std::shared_ptr<Global::Resource::ResourceManager> & resourceMgr)690 std::shared_ptr<Rosen::StartingWindowPageDrawInfo> StartingWindow::DoGetCustomStartingWindowInfo(
691 const std::shared_ptr<AppExecFwk::AbilityInfo>& abilityInfo,
692 const std::shared_ptr<Global::Resource::ResourceManager>& resourceMgr)
693 {
694 if (resourceMgr == nullptr || abilityInfo == nullptr) {
695 TLOGE(WmsLogTag::WMS_PATTERN, "resourMgr or abilityInfo is nullptr.");
696 return nullptr;
697 }
698
699 const auto& startWindowRes = abilityInfo->startWindowResource;
700 auto loadPixelMap = [&](uint32_t resId) {
701 return GetPixelMapListInfo(resId, resourceMgr, abilityInfo);
702 };
703
704 auto info = std::make_shared<Rosen::StartingWindowPageDrawInfo>();
705 if (resourceMgr->GetColorById(startWindowRes.startWindowBackgroundColorId, info->bgColor) ==
706 Global::Resource::RState::SUCCESS) {
707 info->bgImage = loadPixelMap(startWindowRes.startWindowBackgroundImageId);
708 info->branding = loadPixelMap(startWindowRes.startWindowBrandingImageId);
709 info->startWindowBackgroundImageFit = startWindowRes.startWindowBackgroundImageFit;
710 info->appIcon = loadPixelMap(startWindowRes.startWindowAppIconId);
711 if (info->appIcon == nullptr) {
712 info->illustration = loadPixelMap(startWindowRes.startWindowIllustrationId);
713 }
714 return info;
715 }
716 TLOGE(WmsLogTag::WMS_PATTERN, "Failed to load custom startingwindow color.");
717 return nullptr;
718 }
719
DrawStartingWindow(const std::shared_ptr<Rosen::StartingWindowPageDrawInfo> & info,const sptr<WindowNode> & node,const Rect & rect)720 WMError StartingWindow::DrawStartingWindow(const std::shared_ptr<Rosen::StartingWindowPageDrawInfo>& info,
721 const sptr<WindowNode>& node, const Rect& rect)
722 {
723 if (startingWindowShowRunning_.load()) {
724 startingWindowShowRunning_ = false;
725 if (startingWindowShowThread_.joinable()) {
726 startingWindowShowThread_.join();
727 }
728 firstFrameCompleted_ = false;
729 UnRegisterStartingWindowShowInfo();
730 }
731
732 if (info == nullptr) {
733 TLOGE(WmsLogTag::WMS_PATTERN, "startingWindowPageDrawInfo is nullptr.");
734 return WMError::WM_ERROR_NULLPTR;
735 }
736
737 const float vpRatio = DisplayGroupInfo::GetInstance().GetDisplayVirtualPixelRatio(node->GetDisplayId());
738 RegisterStartingWindowShowInfo(node, rect, info, vpRatio);
739 const auto& resInfo = startingWindowShowInfo_.info;
740 if (resInfo && !resInfo->appIcon && !resInfo->bgImage && !resInfo->branding && !resInfo->illustration) {
741 if (!(SurfaceDraw::DrawCustomStartingWindow(node->startingWinSurfaceNode_, rect, resInfo, vpRatio,
742 startingWindowShowInfo_.frameIndex))) {
743 TLOGE(WmsLogTag::WMS_PATTERN, "Failed to draw Custom starting window.");
744 return WMError::WM_ERROR_INVALID_PARAM;
745 }
746 return WMError::WM_OK;
747 }
748
749 DrawStartingWindowShowInfo();
750 std::unique_lock<std::mutex> lock(firstFrameMutex_);
751 firstFrameCondition_.wait(lock, []() { return firstFrameCompleted_ == true; });
752 if (!startingWindowShowRunning_.load()) {
753 TLOGE(WmsLogTag::WMS_PATTERN, "Failed to start Custom starting window show.");
754 if (startingWindowShowThread_.joinable()) {
755 startingWindowShowThread_.join();
756 }
757 UnRegisterStartingWindowShowInfo();
758 return WMError::WM_ERROR_INVALID_PARAM;
759 }
760 return WMError::WM_OK;
761 }
762 } // Rosen
763 } // OHOS