1 /*
2 * Copyright (c) 2022-2023 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 "core/pipeline/pipeline_base.h"
17
18 #include "base/log/ace_tracker.h"
19 #include "base/log/dump_log.h"
20 #include "base/log/event_report.h"
21 #include "base/subwindow/subwindow_manager.h"
22 #include "core/common/ace_engine.h"
23 #include "core/common/font_manager.h"
24 #include "core/common/manager_interface.h"
25 #include "core/common/window.h"
26 #include "core/components/common/layout/constants.h"
27 #include "core/components/container_modal/container_modal_constants.h"
28 #include "core/components/custom_paint/render_custom_paint.h"
29 #include "core/components_ng/render/animation_utils.h"
30 #include "core/image/image_provider.h"
31
32 #ifdef PLUGIN_COMPONENT_SUPPORTED
33 #include "core/common/plugin_manager.h"
34 #endif
35
36 namespace OHOS::Ace {
37
38 constexpr int32_t DEFAULT_VIEW_SCALE = 1;
39
PipelineBase(std::shared_ptr<Window> window,RefPtr<TaskExecutor> taskExecutor,RefPtr<AssetManager> assetManager,const RefPtr<Frontend> & frontend,int32_t instanceId)40 PipelineBase::PipelineBase(std::shared_ptr<Window> window, RefPtr<TaskExecutor> taskExecutor,
41 RefPtr<AssetManager> assetManager, const RefPtr<Frontend>& frontend, int32_t instanceId)
42 : window_(window), taskExecutor_(std::move(taskExecutor)), assetManager_(std::move(assetManager)),
43 weakFrontend_(frontend), instanceId_(instanceId)
44 {
45 CHECK_NULL_VOID(frontend);
46 frontendType_ = frontend->GetType();
47 eventManager_ = AceType::MakeRefPtr<EventManager>();
48 windowManager_ = AceType::MakeRefPtr<WindowManager>();
49 eventManager_->SetInstanceId(instanceId);
50 imageCache_ = ImageCache::Create();
51 fontManager_ = FontManager::Create();
52 auto&& vsyncCallback = [weak = AceType::WeakClaim(this), instanceId](
53 const uint64_t nanoTimestamp, const uint32_t frameCount) {
54 ContainerScope scope(instanceId);
55 auto context = weak.Upgrade();
56 if (context) {
57 context->OnVsyncEvent(nanoTimestamp, frameCount);
58 }
59 };
60 ACE_DCHECK(window_);
61 window_->SetVsyncCallback(vsyncCallback);
62 }
63
PipelineBase(std::shared_ptr<Window> window,RefPtr<TaskExecutor> taskExecutor,RefPtr<AssetManager> assetManager,const RefPtr<Frontend> & frontend,int32_t instanceId,RefPtr<PlatformResRegister> platformResRegister)64 PipelineBase::PipelineBase(std::shared_ptr<Window> window, RefPtr<TaskExecutor> taskExecutor,
65 RefPtr<AssetManager> assetManager, const RefPtr<Frontend>& frontend, int32_t instanceId,
66 RefPtr<PlatformResRegister> platformResRegister)
67 : window_(window), taskExecutor_(std::move(taskExecutor)), assetManager_(std::move(assetManager)),
68 weakFrontend_(frontend), instanceId_(instanceId), platformResRegister_(std::move(platformResRegister))
69 {
70 CHECK_NULL_VOID(frontend);
71 frontendType_ = frontend->GetType();
72 eventManager_ = AceType::MakeRefPtr<EventManager>();
73 windowManager_ = AceType::MakeRefPtr<WindowManager>();
74 eventManager_->SetInstanceId(instanceId);
75 imageCache_ = ImageCache::Create();
76 fontManager_ = FontManager::Create();
77 auto&& vsyncCallback = [weak = AceType::WeakClaim(this), instanceId](
78 const uint64_t nanoTimestamp, const uint32_t frameCount) {
79 ContainerScope scope(instanceId);
80 auto context = weak.Upgrade();
81 if (context) {
82 context->OnVsyncEvent(nanoTimestamp, frameCount);
83 }
84 };
85 ACE_DCHECK(window_);
86 window_->SetVsyncCallback(vsyncCallback);
87 }
88
~PipelineBase()89 PipelineBase::~PipelineBase()
90 {
91 std::lock_guard lock(destructMutex_);
92 LOGI("PipelineBase destroyed");
93 }
94
SetCallBackNode(const WeakPtr<NG::FrameNode> & node)95 void PipelineBase::SetCallBackNode(const WeakPtr<NG::FrameNode>& node)
96 {
97 auto pipelineContext = PipelineContext::GetCurrentContext();
98 CHECK_NULL_VOID(pipelineContext);
99 pipelineContext->UpdateCurrentActiveNode(node);
100 }
101
GetCurrentContext()102 RefPtr<PipelineBase> PipelineBase::GetCurrentContext()
103 {
104 auto currentContainer = Container::Current();
105 CHECK_NULL_RETURN(currentContainer, nullptr);
106 return currentContainer->GetPipelineContext();
107 }
108
GetCurrentContextSafely()109 RefPtr<PipelineBase> PipelineBase::GetCurrentContextSafely()
110 {
111 auto currentContainer = Container::CurrentSafely();
112 CHECK_NULL_RETURN(currentContainer, nullptr);
113 return currentContainer->GetPipelineContext();
114 }
115
GetCurrentContextSafelyWithCheck()116 RefPtr<PipelineBase> PipelineBase::GetCurrentContextSafelyWithCheck()
117 {
118 auto currentContainer = Container::CurrentSafelyWithCheck();
119 CHECK_NULL_RETURN(currentContainer, nullptr);
120 return currentContainer->GetPipelineContext();
121 }
122
GetCurrentDensity()123 double PipelineBase::GetCurrentDensity()
124 {
125 auto pipelineContext = PipelineContext::GetCurrentContextSafely();
126 if (!pipelineContext) {
127 auto container = Container::GetActive();
128 pipelineContext = container ? container->GetPipelineContext() : nullptr;
129 }
130 CHECK_NULL_RETURN(pipelineContext, SystemProperties::GetDefaultResolution());
131 double wmDensity = pipelineContext->GetWindowDensity();
132 if (GreatNotEqual(wmDensity, 1.0)) {
133 return wmDensity;
134 }
135 return pipelineContext->GetDensity();
136 }
137
GetCurrentColorMode()138 ColorMode PipelineBase::GetCurrentColorMode()
139 {
140 auto currentContainer = Container::CurrentSafely();
141 CHECK_NULL_RETURN(currentContainer, ColorMode::LIGHT);
142 return currentContainer->GetColorMode();
143 }
144
Px2VpWithCurrentDensity(double px)145 double PipelineBase::Px2VpWithCurrentDensity(double px)
146 {
147 double density = PipelineBase::GetCurrentDensity();
148 return px / density;
149 }
150
Vp2PxWithCurrentDensity(double vp)151 double PipelineBase::Vp2PxWithCurrentDensity(double vp)
152 {
153 double density = PipelineBase::GetCurrentDensity();
154 return vp * density;
155 }
156
GetMainPipelineContext()157 RefPtr<PipelineBase> PipelineBase::GetMainPipelineContext()
158 {
159 auto containerId = Container::CurrentId();
160 RefPtr<PipelineBase> context;
161 if (containerId >= MIN_SUBCONTAINER_ID) {
162 auto parentContainerId = SubwindowManager::GetInstance()->GetParentContainerId(containerId);
163 auto parentContainer = AceEngine::Get().GetContainer(parentContainerId);
164 CHECK_NULL_RETURN(parentContainer, nullptr);
165 context = parentContainer->GetPipelineContext();
166 } else {
167 context = PipelineBase::GetCurrentContext();
168 }
169 return context;
170 }
171
CurrentThemeManager()172 RefPtr<ThemeManager> PipelineBase::CurrentThemeManager()
173 {
174 auto pipelineContext = OHOS::Ace::PipelineBase::GetCurrentContext();
175 #ifdef PLUGIN_COMPONENT_SUPPORTED
176 if (Container::CurrentId() >= MIN_PLUGIN_SUBCONTAINER_ID) {
177 auto pluginContainer = PluginManager::GetInstance().GetPluginSubContainer(Container::CurrentId());
178 CHECK_NULL_RETURN(pluginContainer, nullptr);
179 pipelineContext = pluginContainer->GetPipelineContext();
180 }
181 #endif
182 CHECK_NULL_RETURN(pipelineContext, nullptr);
183 return pipelineContext->GetThemeManager();
184 }
185
GetTimeFromExternalTimer()186 uint64_t PipelineBase::GetTimeFromExternalTimer()
187 {
188 static const int64_t secToNanosec = 1000000000;
189 struct timespec ts;
190 clock_gettime(CLOCK_MONOTONIC, &ts);
191 return (ts.tv_sec * secToNanosec + ts.tv_nsec);
192 }
193
RequestFrame()194 void PipelineBase::RequestFrame()
195 {
196 if (window_) {
197 window_->RequestFrame();
198 }
199 }
200
GetFrontend() const201 RefPtr<Frontend> PipelineBase::GetFrontend() const
202 {
203 return weakFrontend_.Upgrade();
204 }
205
ClearImageCache()206 void PipelineBase::ClearImageCache()
207 {
208 std::lock_guard<std::shared_mutex> lock(imageMtx_);
209 if (imageCache_) {
210 imageCache_->Clear();
211 }
212 }
213
SetImageCache(const RefPtr<ImageCache> & imageCache)214 void PipelineBase::SetImageCache(const RefPtr<ImageCache>& imageCache)
215 {
216 std::lock_guard<std::shared_mutex> lock(imageMtx_);
217 if (imageCache) {
218 imageCache_ = imageCache;
219 }
220 }
221
GetImageCache() const222 RefPtr<ImageCache> PipelineBase::GetImageCache() const
223 {
224 std::shared_lock<std::shared_mutex> lock(imageMtx_);
225 return imageCache_;
226 }
227
SetRootSize(double density,float width,float height)228 void PipelineBase::SetRootSize(double density, float width, float height)
229 {
230 ACE_SCOPED_TRACE("SetRootSize(%lf, %f, %f)", density, width, height);
231 density_ = density;
232 auto task = [weak = AceType::WeakClaim(this), width, height]() {
233 auto context = weak.Upgrade();
234 if (!context) {
235 return;
236 }
237 context->SetRootRect(width, height);
238 };
239
240 if (taskExecutor_->WillRunOnCurrentThread(TaskExecutor::TaskType::UI)) {
241 task();
242 } else {
243 taskExecutor_->PostTask(task, TaskExecutor::TaskType::UI, "ArkUISetRootSize");
244 }
245 }
246
SetFontScale(float fontScale)247 void PipelineBase::SetFontScale(float fontScale)
248 {
249 const static float CARD_MAX_FONT_SCALE = 1.3f;
250 if (!NearEqual(fontScale_, fontScale)) {
251 fontScale_ = fontScale;
252 if ((isJsCard_ || (isFormRender_ && !isDynamicRender_)) && GreatOrEqual(fontScale_, CARD_MAX_FONT_SCALE)) {
253 fontScale_ = CARD_MAX_FONT_SCALE;
254 }
255 auto pipelineContext = PipelineContext::GetCurrentContext();
256 CHECK_NULL_VOID(pipelineContext);
257 pipelineContext->RebuildFontNode();
258 }
259 }
260
NeedTouchInterpolation()261 bool PipelineBase::NeedTouchInterpolation()
262 {
263 if (!IsFocusWindowIdSetted()) {
264 return true;
265 }
266 auto container = Container::GetContainer(instanceId_);
267 CHECK_NULL_RETURN(container, false);
268 auto uIContentType = container->GetUIContentType();
269 return SystemProperties::IsNeedResampleTouchPoints() &&
270 (uIContentType == UIContentType::SECURITY_UI_EXTENSION ||
271 uIContentType == UIContentType::MODAL_UI_EXTENSION);
272 }
273
SetFontWeightScale(float fontWeightScale)274 void PipelineBase::SetFontWeightScale(float fontWeightScale)
275 {
276 const static float CARD_MAX_FONT_WEIGHT_SCALE = 1.25f;
277 if (!NearEqual(fontWeightScale_, fontWeightScale)) {
278 fontWeightScale_ = fontWeightScale;
279 if (isJsCard_ && GreatOrEqual(fontWeightScale_, CARD_MAX_FONT_WEIGHT_SCALE)) {
280 fontWeightScale_ = CARD_MAX_FONT_WEIGHT_SCALE;
281 }
282 auto pipelineContext = PipelineContext::GetCurrentContext();
283 CHECK_NULL_VOID(pipelineContext);
284 pipelineContext->RebuildFontNode();
285 }
286 }
287
NormalizeToPx(const Dimension & dimension) const288 double PipelineBase::NormalizeToPx(const Dimension& dimension) const
289 {
290 if ((dimension.Unit() == DimensionUnit::VP) || (dimension.Unit() == DimensionUnit::FP)) {
291 return (dimension.Value() * dipScale_);
292 } else if (dimension.Unit() == DimensionUnit::LPX) {
293 return (dimension.Value() * designWidthScale_);
294 }
295 return dimension.Value();
296 }
297
ConvertPxToVp(const Dimension & dimension) const298 double PipelineBase::ConvertPxToVp(const Dimension& dimension) const
299 {
300 if (dimension.Unit() == DimensionUnit::PX) {
301 return dimension.Value() / dipScale_;
302 }
303 return dimension.Value();
304 }
305
UpdateFontWeightScale()306 void PipelineBase::UpdateFontWeightScale()
307 {
308 if (fontManager_) {
309 fontManager_->UpdateFontWeightScale();
310 }
311 }
312
SetTextFieldManager(const RefPtr<ManagerInterface> & manager)313 void PipelineBase::SetTextFieldManager(const RefPtr<ManagerInterface>& manager)
314 {
315 textFieldManager_ = manager;
316 }
317
RegisterFont(const std::string & familyName,const std::string & familySrc,const std::string & bundleName,const std::string & moduleName)318 void PipelineBase::RegisterFont(const std::string& familyName, const std::string& familySrc,
319 const std::string& bundleName, const std::string& moduleName)
320 {
321 if (fontManager_) {
322 fontManager_->RegisterFont(familyName, familySrc, AceType::Claim(this), bundleName, moduleName);
323 }
324 }
325
GetSystemFontList(std::vector<std::string> & fontList)326 void PipelineBase::GetSystemFontList(std::vector<std::string>& fontList)
327 {
328 if (fontManager_) {
329 fontManager_->GetSystemFontList(fontList);
330 }
331 }
332
GetSystemFont(const std::string & fontName,FontInfo & fontInfo)333 bool PipelineBase::GetSystemFont(const std::string& fontName, FontInfo& fontInfo)
334 {
335 if (fontManager_) {
336 return fontManager_->GetSystemFont(fontName, fontInfo);
337 }
338 return false;
339 }
340
GetUIFontConfig(FontConfigJsonInfo & fontConfigJsonInfo)341 void PipelineBase::GetUIFontConfig(FontConfigJsonInfo& fontConfigJsonInfo)
342 {
343 if (fontManager_) {
344 fontManager_->GetUIFontConfig(fontConfigJsonInfo);
345 }
346 }
347
HyperlinkStartAbility(const std::string & address) const348 void PipelineBase::HyperlinkStartAbility(const std::string& address) const
349 {
350 CHECK_RUN_ON(UI);
351 if (startAbilityHandler_) {
352 startAbilityHandler_(address);
353 }
354 }
355
StartAbilityOnQuery(const std::string & queryWord) const356 void PipelineBase::StartAbilityOnQuery(const std::string& queryWord) const
357 {
358 CHECK_RUN_ON(UI);
359 if (startAbilityOnQueryHandler_) {
360 startAbilityOnQueryHandler_(queryWord);
361 }
362 }
363
NotifyStatusBarBgColor(const Color & color) const364 void PipelineBase::NotifyStatusBarBgColor(const Color& color) const
365 {
366 CHECK_RUN_ON(UI);
367 if (statusBarBgColorEventHandler_) {
368 statusBarBgColorEventHandler_(color);
369 }
370 }
371
NotifyPopupDismiss() const372 void PipelineBase::NotifyPopupDismiss() const
373 {
374 CHECK_RUN_ON(UI);
375 if (popupEventHandler_) {
376 popupEventHandler_();
377 }
378 }
379
NotifyMenuDismiss() const380 void PipelineBase::NotifyMenuDismiss() const
381 {
382 CHECK_RUN_ON(UI);
383 if (menuEventHandler_) {
384 menuEventHandler_();
385 }
386 }
387
NotifyContextMenuDismiss() const388 void PipelineBase::NotifyContextMenuDismiss() const
389 {
390 CHECK_RUN_ON(UI);
391 if (contextMenuEventHandler_) {
392 contextMenuEventHandler_();
393 }
394 }
395
NotifyRouterBackDismiss() const396 void PipelineBase::NotifyRouterBackDismiss() const
397 {
398 CHECK_RUN_ON(UI);
399 if (routerBackEventHandler_) {
400 routerBackEventHandler_();
401 }
402 }
403
NotifyPopPageSuccessDismiss(const std::string & pageUrl,const int32_t pageId) const404 void PipelineBase::NotifyPopPageSuccessDismiss(const std::string& pageUrl, const int32_t pageId) const
405 {
406 CHECK_RUN_ON(UI);
407 for (auto& iterPopSuccessHander : popPageSuccessEventHandler_) {
408 if (iterPopSuccessHander) {
409 iterPopSuccessHander(pageUrl, pageId);
410 }
411 }
412 }
413
NotifyIsPagePathInvalidDismiss(bool isPageInvalid) const414 void PipelineBase::NotifyIsPagePathInvalidDismiss(bool isPageInvalid) const
415 {
416 CHECK_RUN_ON(UI);
417 for (auto& iterPathInvalidHandler : isPagePathInvalidEventHandler_) {
418 if (iterPathInvalidHandler) {
419 iterPathInvalidHandler(isPageInvalid);
420 }
421 }
422 }
423
NotifyDestroyEventDismiss() const424 void PipelineBase::NotifyDestroyEventDismiss() const
425 {
426 CHECK_RUN_ON(UI);
427 for (auto& iterDestroyEventHander : destroyEventHandler_) {
428 if (iterDestroyEventHander) {
429 iterDestroyEventHander();
430 }
431 }
432 }
433
NotifyDispatchTouchEventDismiss(const TouchEvent & event) const434 void PipelineBase::NotifyDispatchTouchEventDismiss(const TouchEvent& event) const
435 {
436 CHECK_RUN_ON(UI);
437 for (auto& iterDispatchTouchEventHandler : dispatchTouchEventHandler_) {
438 if (iterDispatchTouchEventHandler) {
439 iterDispatchTouchEventHandler(event);
440 }
441 }
442 }
443
OnActionEvent(const std::string & action)444 void PipelineBase::OnActionEvent(const std::string& action)
445 {
446 CHECK_RUN_ON(UI);
447 if (actionEventHandler_) {
448 actionEventHandler_(action);
449 }
450 }
451
onRouterChange(const std::string & url)452 void PipelineBase::onRouterChange(const std::string& url)
453 {
454 if (onRouterChangeCallback_ != nullptr) {
455 onRouterChangeCallback_(url);
456 }
457 }
458
TryLoadImageInfo(const std::string & src,std::function<void (bool,int32_t,int32_t)> && loadCallback)459 void PipelineBase::TryLoadImageInfo(const std::string& src, std::function<void(bool, int32_t, int32_t)>&& loadCallback)
460 {
461 ImageProvider::TryLoadImageInfo(AceType::Claim(this), src, std::move(loadCallback));
462 }
463
CreateOffscreenCanvas(int32_t width,int32_t height)464 RefPtr<OffscreenCanvas> PipelineBase::CreateOffscreenCanvas(int32_t width, int32_t height)
465 {
466 return RenderOffscreenCanvas::Create(AceType::WeakClaim(this), width, height);
467 }
468
PostAsyncEvent(TaskExecutor::Task && task,const std::string & name,TaskExecutor::TaskType type)469 void PipelineBase::PostAsyncEvent(TaskExecutor::Task&& task, const std::string& name, TaskExecutor::TaskType type)
470 {
471 if (taskExecutor_) {
472 taskExecutor_->PostTask(std::move(task), type, name);
473 }
474 }
475
PostAsyncEvent(const TaskExecutor::Task & task,const std::string & name,TaskExecutor::TaskType type)476 void PipelineBase::PostAsyncEvent(const TaskExecutor::Task& task, const std::string& name, TaskExecutor::TaskType type)
477 {
478 if (taskExecutor_) {
479 taskExecutor_->PostTask(task, type, name);
480 }
481 }
482
PostSyncEvent(const TaskExecutor::Task & task,const std::string & name,TaskExecutor::TaskType type)483 void PipelineBase::PostSyncEvent(const TaskExecutor::Task& task, const std::string& name, TaskExecutor::TaskType type)
484 {
485 if (taskExecutor_) {
486 taskExecutor_->PostSyncTask(task, type, name);
487 }
488 }
489
UpdateRootSizeAndScale(int32_t width,int32_t height)490 void PipelineBase::UpdateRootSizeAndScale(int32_t width, int32_t height)
491 {
492 auto frontend = weakFrontend_.Upgrade();
493 CHECK_NULL_VOID(frontend);
494 auto lock = frontend->GetLock();
495 auto& windowConfig = frontend->GetWindowConfig();
496 if (windowConfig.designWidth <= 0) {
497 return;
498 }
499 if (GetIsDeclarative()) {
500 viewScale_ = DEFAULT_VIEW_SCALE;
501 double pageWidth = width;
502 if (IsContainerModalVisible()) {
503 pageWidth -= 2 * (CONTAINER_BORDER_WIDTH + CONTENT_PADDING).ConvertToPx();
504 }
505 designWidthScale_ =
506 windowConfig.autoDesignWidth ? density_ : pageWidth / windowConfig.designWidth;
507 windowConfig.designWidthScale = designWidthScale_;
508 } else {
509 viewScale_ = windowConfig.autoDesignWidth ? density_ : static_cast<double>(width) / windowConfig.designWidth;
510 }
511 if (NearZero(viewScale_)) {
512 return;
513 }
514 dipScale_ = density_ / viewScale_;
515 rootHeight_ = height / viewScale_;
516 rootWidth_ = width / viewScale_;
517 }
518
DumpFrontend() const519 void PipelineBase::DumpFrontend() const
520 {
521 auto frontend = weakFrontend_.Upgrade();
522 CHECK_NULL_VOID(frontend);
523 auto lock = frontend->GetLock();
524 frontend->DumpFrontend();
525 }
526
Dump(const std::vector<std::string> & params) const527 bool PipelineBase::Dump(const std::vector<std::string>& params) const
528 {
529 if (params.empty()) {
530 return false;
531 }
532 // the first param is the key word of dump.
533 if (params[0] == "-memory") {
534 MemoryMonitor::GetInstance().Dump();
535 DumpUIExt();
536 return true;
537 }
538 if (params[0] == "-jscrash") {
539 EventReport::JsErrReport(
540 AceApplicationInfo::GetInstance().GetPackageName(), "js crash reason", "js crash summary");
541 return true;
542 }
543 // hiview report dump will provide three params .
544 if (params[0] == "-hiviewreport" && params.size() >= 3) {
545 DumpLog::GetInstance().Print("Report hiview event. EventType: " + params[1] + ", error type: " + params[2]);
546 EventInfo eventInfo = { .eventType = params[1], .errorType = StringUtils::StringToInt(params[2]) };
547 EventReport::SendEvent(eventInfo);
548 return true;
549 }
550 ContainerScope scope(instanceId_);
551 if (params[0] == "-frontend") {
552 DumpFrontend();
553 DumpUIExt();
554 return true;
555 }
556 return OnDumpInfo(params);
557 }
558
IsDestroyed()559 bool PipelineBase::IsDestroyed()
560 {
561 return destroyed_;
562 }
563
SetDestroyed()564 void PipelineBase::SetDestroyed()
565 {
566 destroyed_ = true;
567 }
568
ForceLayoutForImplicitAnimation()569 void PipelineBase::ForceLayoutForImplicitAnimation()
570 {
571 if (!pendingImplicitLayout_.empty()) {
572 pendingImplicitLayout_.top() = true;
573 }
574 if (!pendingFrontendAnimation_.empty()) {
575 pendingFrontendAnimation_.top() = true;
576 }
577 }
578
ForceRenderForImplicitAnimation()579 void PipelineBase::ForceRenderForImplicitAnimation()
580 {
581 if (!pendingImplicitRender_.empty()) {
582 pendingImplicitRender_.top() = true;
583 }
584 if (!pendingFrontendAnimation_.empty()) {
585 pendingFrontendAnimation_.top() = true;
586 }
587 }
588
Animate(const AnimationOption & option,const RefPtr<Curve> & curve,const std::function<void ()> & propertyCallback,const std::function<void ()> & finishCallback)589 bool PipelineBase::Animate(const AnimationOption& option, const RefPtr<Curve>& curve,
590 const std::function<void()>& propertyCallback, const std::function<void()>& finishCallback)
591 {
592 if (!propertyCallback) {
593 return false;
594 }
595
596 OpenImplicitAnimation(option, curve, finishCallback);
597 propertyCallback();
598 return CloseImplicitAnimation();
599 }
600
GetUnexecutedFinishCount() const601 std::string PipelineBase::GetUnexecutedFinishCount() const
602 {
603 std::string finishCountToString;
604 for (const auto& element : finishCount_) {
605 finishCountToString += std::to_string(element) + " ";
606 }
607 return "[ " + finishCountToString + "]";
608 }
609
GetWrappedAnimationCallback(const AnimationOption & option,const std::function<void ()> & finishCallback,const std::optional<int32_t> & count)610 std::function<void()> PipelineBase::GetWrappedAnimationCallback(
611 const AnimationOption& option, const std::function<void()>& finishCallback, const std::optional<int32_t>& count)
612 {
613 if (!IsFormRenderExceptDynamicComponent() && !finishCallback) {
614 return nullptr;
615 }
616 auto finishPtr = std::make_shared<std::function<void()>>(finishCallback);
617 finishFunctions_.emplace(finishPtr);
618
619 // When the animateTo or keyframeAnimateTo has finishCallback and iteration is not infinite,
620 // count needs to be saved.
621 if (count.has_value() && option.GetIteration() != ANIMATION_REPEAT_INFINITE) {
622 finishCount_.emplace(count.value());
623 }
624 auto wrapFinishCallback = [weak = AceType::WeakClaim(this),
625 finishWeak = std::weak_ptr<std::function<void()>>(finishPtr), count]() {
626 auto context = weak.Upgrade();
627 CHECK_NULL_VOID(context);
628 auto finishPtr = finishWeak.lock();
629 CHECK_NULL_VOID(finishPtr);
630 context->finishFunctions_.erase(finishPtr);
631 if (count.has_value() && !context->finishFunctions_.count(finishPtr)) {
632 context->finishCount_.erase(count.value());
633 }
634 if (!(*finishPtr)) {
635 if (context->IsFormRenderExceptDynamicComponent()) {
636 TAG_LOGI(AceLogTag::ACE_FORM, "[Form animation] Form animation is finish.");
637 context->SetIsFormAnimation(false);
638 }
639 return;
640 }
641 if (context->IsFormRenderExceptDynamicComponent()) {
642 TAG_LOGI(AceLogTag::ACE_FORM, "[Form animation] Form animation is finish.");
643 context->SetFormAnimationFinishCallback(true);
644 (*finishPtr)();
645 context->FlushBuild();
646 context->SetFormAnimationFinishCallback(false);
647 context->SetIsFormAnimation(false);
648 return;
649 }
650 (*finishPtr)();
651 };
652 return wrapFinishCallback;
653 }
654
PrepareOpenImplicitAnimation()655 void PipelineBase::PrepareOpenImplicitAnimation()
656 {
657 #ifdef ENABLE_ROSEN_BACKEND
658 // initialize false for implicit animation layout and render pending flag
659 pendingImplicitLayout_.push(false);
660 pendingImplicitRender_.push(false);
661
662 // flush ui tasks before open implicit animation
663 if (!IsLayouting()) {
664 FlushUITasks(true);
665 }
666 #endif
667 }
668
PrepareCloseImplicitAnimation()669 void PipelineBase::PrepareCloseImplicitAnimation()
670 {
671 #ifdef ENABLE_ROSEN_BACKEND
672 if (pendingImplicitLayout_.empty() && pendingImplicitRender_.empty()) {
673 return;
674 }
675
676 // layout or render the views immediately to animate all related views, if layout or render updates are pending in
677 // the animation closure
678 if (pendingImplicitLayout_.top() || pendingImplicitRender_.top()) {
679 if (!IsLayouting()) {
680 FlushUITasks(true);
681 } else if (IsLayouting()) {
682 LOGW("IsLayouting, prepareCloseImplicitAnimation has tasks not flushed");
683 }
684 }
685 if (!pendingImplicitLayout_.empty()) {
686 pendingImplicitLayout_.pop();
687 }
688 if (!pendingImplicitRender_.empty()) {
689 pendingImplicitRender_.pop();
690 }
691 #endif
692 }
693
OpenImplicitAnimation(const AnimationOption & option,const RefPtr<Curve> & curve,const std::function<void ()> & finishCallback)694 void PipelineBase::OpenImplicitAnimation(
695 const AnimationOption& option,
696 const RefPtr<Curve>& curve,
697 const std::function<void()>& finishCallback)
698 {
699 #ifdef ENABLE_ROSEN_BACKEND
700 PrepareOpenImplicitAnimation();
701 StartImplicitAnimation(option, curve, finishCallback);
702 #endif
703 }
704
StartImplicitAnimation(const AnimationOption & option,const RefPtr<Curve> & curve,const std::function<void ()> & finishCallback,const std::optional<int32_t> & count)705 void PipelineBase::StartImplicitAnimation(const AnimationOption& option, const RefPtr<Curve>& curve,
706 const std::function<void()>& finishCallback, const std::optional<int32_t>& count)
707 {
708 #ifdef ENABLE_ROSEN_BACKEND
709 auto wrapFinishCallback = GetWrappedAnimationCallback(option, finishCallback, count);
710 if (IsFormRenderExceptDynamicComponent()) {
711 SetIsFormAnimation(true);
712 if (!IsFormAnimationFinishCallback()) {
713 SetFormAnimationStartTime(GetMicroTickCount());
714 }
715 }
716 AnimationUtils::OpenImplicitAnimation(option, curve, wrapFinishCallback);
717 #endif
718 }
719
CloseImplicitAnimation()720 bool PipelineBase::CloseImplicitAnimation()
721 {
722 #ifdef ENABLE_ROSEN_BACKEND
723 PrepareCloseImplicitAnimation();
724 return AnimationUtils::CloseImplicitAnimation();
725 #else
726 return false;
727 #endif
728 }
729
OnVsyncEvent(uint64_t nanoTimestamp,uint32_t frameCount)730 void PipelineBase::OnVsyncEvent(uint64_t nanoTimestamp, uint32_t frameCount)
731 {
732 CHECK_RUN_ON(UI);
733 ACE_SCOPED_TRACE("OnVsyncEvent now:%" PRIu64 "", nanoTimestamp);
734 frameCount_ = frameCount;
735
736 recvTime_ = GetSysTimestamp();
737 compensationValue_ =
738 nanoTimestamp > static_cast<uint64_t>(recvTime_) ? (nanoTimestamp - static_cast<uint64_t>(recvTime_)) : 0;
739
740 for (auto& callback : subWindowVsyncCallbacks_) {
741 callback.second(nanoTimestamp, frameCount);
742 }
743
744 decltype(jsFormVsyncCallbacks_) jsFormVsyncCallbacks(std::move(jsFormVsyncCallbacks_));
745 for (auto& callback : jsFormVsyncCallbacks) {
746 callback.second(nanoTimestamp, frameCount);
747 }
748
749 if (onVsyncProfiler_) {
750 AceTracker::Start();
751 }
752
753 if (gsVsyncCallback_) {
754 gsVsyncCallback_();
755 }
756
757 FlushVsync(nanoTimestamp, frameCount);
758 if (onVsyncProfiler_) {
759 onVsyncProfiler_(AceTracker::Stop());
760 }
761 }
762
SetTouchPipeline(const WeakPtr<PipelineBase> & context)763 void PipelineBase::SetTouchPipeline(const WeakPtr<PipelineBase>& context)
764 {
765 auto result = std::find(touchPluginPipelineContext_.begin(), touchPluginPipelineContext_.end(), context);
766 if (result == touchPluginPipelineContext_.end()) {
767 touchPluginPipelineContext_.emplace_back(context);
768 }
769 }
770
RemoveTouchPipeline(const WeakPtr<PipelineBase> & context)771 void PipelineBase::RemoveTouchPipeline(const WeakPtr<PipelineBase>& context)
772 {
773 auto result = std::find(touchPluginPipelineContext_.begin(), touchPluginPipelineContext_.end(), context);
774 if (result != touchPluginPipelineContext_.end()) {
775 touchPluginPipelineContext_.erase(result);
776 }
777 }
778
MarkUpdateSubwindowKeyboardInsert(int32_t instanceId,double keyboardHeight,int32_t type)779 bool PipelineBase::MarkUpdateSubwindowKeyboardInsert(int32_t instanceId, double keyboardHeight, int32_t type)
780 {
781 auto subwindow = SubwindowManager::GetInstance()->GetSubwindowByType(instanceId, static_cast<SubwindowType>(type));
782 if (subwindow && subwindow->GetShown() && subwindow->IsFocused() && !CheckNeedAvoidInSubWindow() &&
783 !subwindow->NeedAvoidKeyboard()) {
784 // subwindow is shown, main window no need to handle the keyboard event
785 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "subwindow is shown and pageOffset is zero, main window doesn't lift");
786 CheckAndUpdateKeyboardInset(keyboardHeight);
787 return true;
788 }
789 return false;
790 }
791
OnVirtualKeyboardAreaChange(Rect keyboardArea,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,const float safeHeight,bool supportAvoidance,bool forceChange)792 void PipelineBase::OnVirtualKeyboardAreaChange(Rect keyboardArea,
793 const std::shared_ptr<Rosen::RSTransaction>& rsTransaction, const float safeHeight, bool supportAvoidance,
794 bool forceChange)
795 {
796 auto currentContainer = Container::Current();
797 double keyboardHeight = keyboardArea.Height();
798 if (currentContainer && !currentContainer->IsSubContainer()) {
799 #ifdef OHOS_STANDARD_SYSTEM
800 int32_t instanceId = currentContainer->GetInstanceId();
801 if (MarkUpdateSubwindowKeyboardInsert(
802 instanceId, keyboardHeight, static_cast<int32_t>(SubwindowType::TYPE_DIALOG))) {
803 return;
804 }
805 if (MarkUpdateSubwindowKeyboardInsert(
806 instanceId, keyboardHeight, static_cast<int32_t>(SubwindowType::TYPE_POPUP))) {
807 return;
808 }
809 if (MarkUpdateSubwindowKeyboardInsert(
810 instanceId, keyboardHeight, static_cast<int32_t>(SubwindowType::TYPE_MENU))) {
811 return;
812 }
813 #endif
814 }
815 if (NotifyVirtualKeyBoard(rootWidth_, rootHeight_, keyboardHeight, true)) {
816 return;
817 }
818 OnVirtualKeyboardHeightChange(keyboardHeight, rsTransaction, safeHeight, supportAvoidance, forceChange);
819 }
820
OnVirtualKeyboardAreaChange(Rect keyboardArea,double positionY,double height,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,bool forceChange)821 void PipelineBase::OnVirtualKeyboardAreaChange(Rect keyboardArea, double positionY, double height,
822 const std::shared_ptr<Rosen::RSTransaction>& rsTransaction, bool forceChange)
823 {
824 auto currentContainer = Container::Current();
825 float keyboardHeight = keyboardArea.Height();
826 if (currentContainer && !currentContainer->IsSubContainer()) {
827 int32_t instanceId = currentContainer->GetInstanceId();
828 if (MarkUpdateSubwindowKeyboardInsert(
829 instanceId, keyboardHeight, static_cast<int32_t>(SubwindowType::TYPE_DIALOG))) {
830 return;
831 }
832 if (MarkUpdateSubwindowKeyboardInsert(
833 instanceId, keyboardHeight, static_cast<int32_t>(SubwindowType::TYPE_POPUP))) {
834 return;
835 }
836 if (MarkUpdateSubwindowKeyboardInsert(
837 instanceId, keyboardHeight, static_cast<int32_t>(SubwindowType::TYPE_MENU))) {
838 return;
839 }
840 }
841 if (NotifyVirtualKeyBoard(rootWidth_, rootHeight_, keyboardHeight, false)) {
842 return;
843 }
844 OnVirtualKeyboardHeightChange(keyboardHeight, positionY, height, rsTransaction, forceChange);
845 }
846
OnFoldStatusChanged(FoldStatus foldStatus)847 void PipelineBase::OnFoldStatusChanged(FoldStatus foldStatus)
848 {
849 OnFoldStatusChange(foldStatus);
850 }
851
OnFoldDisplayModeChanged(FoldDisplayMode foldDisplayMode)852 void PipelineBase::OnFoldDisplayModeChanged(FoldDisplayMode foldDisplayMode)
853 {
854 OnFoldDisplayModeChange(foldDisplayMode);
855 }
856
ModifyKeyboardHeight(double keyboardHeight) const857 double PipelineBase::ModifyKeyboardHeight(double keyboardHeight) const
858 {
859 auto windowRect = GetCurrentWindowRect();
860 auto deviceHeight = SystemProperties::GetDeviceHeight();
861 return keyboardHeight > 0.0 && keyboardHeight - (deviceHeight - windowRect.Bottom()) > 0.0
862 ? keyboardHeight - (deviceHeight - windowRect.Bottom())
863 : 0.0;
864 }
865
SetGetWindowRectImpl(std::function<Rect ()> && callback)866 void PipelineBase::SetGetWindowRectImpl(std::function<Rect()>&& callback)
867 {
868 if (window_) {
869 window_->SetGetWindowRectImpl(std::move(callback));
870 }
871 }
872
ContainerModalUnFocus()873 void PipelineBase::ContainerModalUnFocus() {}
874
GetCurrentWindowRect() const875 Rect PipelineBase::GetCurrentWindowRect() const
876 {
877 if (window_) {
878 return window_->GetCurrentWindowRect();
879 }
880 return {};
881 }
882
HasFloatTitle() const883 bool PipelineBase::HasFloatTitle() const
884 {
885 CHECK_NULL_RETURN(windowManager_, false);
886 return GetWindowModal() == WindowModal::CONTAINER_MODAL &&
887 windowManager_->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING;
888 }
889
GetAccessibilityManager() const890 RefPtr<AccessibilityManager> PipelineBase::GetAccessibilityManager() const
891 {
892 auto frontend = weakFrontend_.Upgrade();
893 if (!frontend) {
894 EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
895 return nullptr;
896 }
897 auto lock = frontend->GetLock();
898 return frontend->GetAccessibilityManager();
899 }
900
SendEventToAccessibility(const AccessibilityEvent & accessibilityEvent)901 void PipelineBase::SendEventToAccessibility(const AccessibilityEvent& accessibilityEvent)
902 {
903 auto accessibilityManager = GetAccessibilityManager();
904 if (!accessibilityManager || !AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
905 return;
906 }
907 accessibilityManager->SendAccessibilityAsyncEvent(accessibilityEvent);
908 }
909
FireUIExtensionEventValid()910 bool PipelineBase::FireUIExtensionEventValid()
911 {
912 if (!uiExtensionEventCallback_ || !IsFocusWindowIdSetted()) {
913 return false;
914 }
915 return true;
916 }
917
SetUIExtensionEventCallback(std::function<void (uint32_t)> && callback)918 void PipelineBase::SetUIExtensionEventCallback(std::function<void(uint32_t)>&& callback)
919 {
920 ACE_FUNCTION_TRACE();
921 uiExtensionEventCallback_ = callback;
922 }
923
AddUIExtensionCallbackEvent(NG::UIExtCallbackEventId eventId)924 void PipelineBase::AddUIExtensionCallbackEvent(NG::UIExtCallbackEventId eventId)
925 {
926 ACE_SCOPED_TRACE("AddUIExtensionCallbackEvent event[%u]", static_cast<uint32_t>(eventId));
927 uiExtensionEvents_.insert(NG::UIExtCallbackEvent(eventId));
928 }
929
FireAllUIExtensionEvents()930 void PipelineBase::FireAllUIExtensionEvents()
931 {
932 if (!FireUIExtensionEventValid() || uiExtensionEvents_.empty()) {
933 return;
934 }
935 std::vector<uint32_t> eventIds;
936 for (auto it = uiExtensionEvents_.begin(); it != uiExtensionEvents_.end();) {
937 eventIds.push_back(static_cast<uint32_t>(it->eventId));
938 if (!it->repeat) {
939 it = uiExtensionEvents_.erase(it);
940 } else {
941 ++it;
942 }
943 }
944 for (auto id : eventIds) {
945 FireUIExtensionEventInner(id);
946 }
947 }
948
FireUIExtensionEventOnceImmediately(NG::UIExtCallbackEventId eventId)949 void PipelineBase::FireUIExtensionEventOnceImmediately(NG::UIExtCallbackEventId eventId)
950 {
951 if (!FireUIExtensionEventValid()) {
952 return;
953 }
954 FireUIExtensionEventInner(static_cast<uint32_t>(eventId));
955 }
956
FireUIExtensionEventInner(uint32_t eventId)957 void PipelineBase::FireUIExtensionEventInner(uint32_t eventId)
958 {
959 auto callback = uiExtensionEventCallback_;
960 callback(eventId);
961 }
962
SetAccessibilityEventCallback(std::function<void (uint32_t,int64_t)> && callback)963 void PipelineBase::SetAccessibilityEventCallback(std::function<void(uint32_t, int64_t)>&& callback)
964 {
965 ACE_FUNCTION_TRACE();
966 accessibilityCallback_ = callback;
967 }
968
AddAccessibilityCallbackEvent(AccessibilityCallbackEventId event,int64_t parameter)969 void PipelineBase::AddAccessibilityCallbackEvent(AccessibilityCallbackEventId event, int64_t parameter)
970 {
971 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
972 ACE_SCOPED_TRACE("AccessibilityCallbackEvent event[%u]", static_cast<uint32_t>(event));
973 accessibilityEvents_.insert(AccessibilityCallbackEvent(event, parameter));
974 }
975 }
976
FireAccessibilityEvents()977 void PipelineBase::FireAccessibilityEvents()
978 {
979 if (!accessibilityCallback_ || accessibilityEvents_.empty()) {
980 return;
981 }
982 decltype(accessibilityEvents_) events;
983 std::swap(accessibilityEvents_, events);
984 for (auto &event : events) {
985 FireAccessibilityEventInner(static_cast<uint32_t>(event.eventId), event.parameter);
986 }
987 }
988
FireAccessibilityEventInner(uint32_t event,int64_t parameter)989 void PipelineBase::FireAccessibilityEventInner(uint32_t event, int64_t parameter)
990 {
991 auto callback = accessibilityCallback_;
992 callback(event, parameter);
993 }
994
SetSubWindowVsyncCallback(AceVsyncCallback && callback,int32_t subWindowId)995 void PipelineBase::SetSubWindowVsyncCallback(AceVsyncCallback&& callback, int32_t subWindowId)
996 {
997 if (callback) {
998 subWindowVsyncCallbacks_.try_emplace(subWindowId, std::move(callback));
999 }
1000 }
1001
SetJsFormVsyncCallback(AceVsyncCallback && callback,int32_t subWindowId)1002 void PipelineBase::SetJsFormVsyncCallback(AceVsyncCallback&& callback, int32_t subWindowId)
1003 {
1004 if (callback) {
1005 jsFormVsyncCallbacks_.try_emplace(subWindowId, std::move(callback));
1006 }
1007 }
1008
RemoveSubWindowVsyncCallback(int32_t subWindowId)1009 void PipelineBase::RemoveSubWindowVsyncCallback(int32_t subWindowId)
1010 {
1011 subWindowVsyncCallbacks_.erase(subWindowId);
1012 }
1013
RemoveJsFormVsyncCallback(int32_t subWindowId)1014 void PipelineBase::RemoveJsFormVsyncCallback(int32_t subWindowId)
1015 {
1016 jsFormVsyncCallbacks_.erase(subWindowId);
1017 }
1018
MaybeRelease()1019 bool PipelineBase::MaybeRelease()
1020 {
1021 CHECK_NULL_RETURN(taskExecutor_, true);
1022 if (taskExecutor_->WillRunOnCurrentThread(TaskExecutor::TaskType::UI)) {
1023 LOGI("Destroy Pipeline on UI thread.");
1024 return true;
1025 } else {
1026 std::lock_guard lock(destructMutex_);
1027 LOGI("Post Destroy Pipeline Task to UI thread.");
1028 return !taskExecutor_->PostTask([this] { delete this; }, TaskExecutor::TaskType::UI, "ArkUIDestroyPipeline");
1029 }
1030 }
1031
Destroy()1032 void PipelineBase::Destroy()
1033 {
1034 CHECK_RUN_ON(UI);
1035 destroyed_ = true;
1036 ClearImageCache();
1037 platformResRegister_.Reset();
1038 drawDelegate_.reset();
1039 eventManager_->ClearResults();
1040 {
1041 std::unique_lock<std::shared_mutex> lock(imageMtx_);
1042 imageCache_.Reset();
1043 }
1044 {
1045 std::unique_lock<std::shared_mutex> lock(themeMtx_);
1046 themeManager_.Reset();
1047 }
1048 fontManager_.Reset();
1049 window_->Destroy();
1050 touchPluginPipelineContext_.clear();
1051 virtualKeyBoardCallback_.clear();
1052 formLinkInfoMap_.clear();
1053 TAG_LOGI(AceLogTag::ACE_ANIMATION,
1054 "pipeline destroyed, has %{public}zu finish callbacks not executed, finish count is %{public}s",
1055 finishFunctions_.size(), GetUnexecutedFinishCount().c_str());
1056 finishFunctions_.clear();
1057 finishCount_.clear();
1058 animationOption_ = {};
1059 {
1060 // To avoid the race condition caused by the offscreen canvas get density from the pipeline in the worker
1061 // thread.
1062 std::lock_guard lock(densityChangeMutex_);
1063 densityChangedCallbacks_.clear();
1064 }
1065 }
1066
OnFormRecycle()1067 std::string PipelineBase::OnFormRecycle()
1068 {
1069 if (onFormRecycle_) {
1070 return onFormRecycle_();
1071 }
1072 LOGE("onFormRecycle_ is null.");
1073 return "";
1074 }
1075
OnFormRecover(const std::string & statusData)1076 void PipelineBase::OnFormRecover(const std::string& statusData)
1077 {
1078 if (onFormRecover_) {
1079 return onFormRecover_(statusData);
1080 }
1081 LOGE("onFormRecover_ is null.");
1082 }
1083
SetUiDvsyncSwitch(bool on)1084 void PipelineBase::SetUiDvsyncSwitch(bool on)
1085 {
1086 if (window_) {
1087 window_->SetUiDvsyncSwitch(on);
1088 }
1089 }
1090 } // namespace OHOS::Ace
1091