• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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