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 LOG_DESTROY();
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
Px2VpWithCurrentDensity(double px)138 double PipelineBase::Px2VpWithCurrentDensity(double px)
139 {
140 double density = PipelineBase::GetCurrentDensity();
141 return px / density;
142 }
143
Vp2PxWithCurrentDensity(double vp)144 double PipelineBase::Vp2PxWithCurrentDensity(double vp)
145 {
146 double density = PipelineBase::GetCurrentDensity();
147 return vp * density;
148 }
149
GetMainPipelineContext()150 RefPtr<PipelineBase> PipelineBase::GetMainPipelineContext()
151 {
152 auto containerId = Container::CurrentId();
153 RefPtr<PipelineBase> context;
154 if (containerId >= MIN_SUBCONTAINER_ID) {
155 auto parentContainerId = SubwindowManager::GetInstance()->GetParentContainerId(containerId);
156 auto parentContainer = AceEngine::Get().GetContainer(parentContainerId);
157 CHECK_NULL_RETURN(parentContainer, nullptr);
158 context = parentContainer->GetPipelineContext();
159 } else {
160 context = PipelineBase::GetCurrentContext();
161 }
162 return context;
163 }
164
CurrentThemeManager()165 RefPtr<ThemeManager> PipelineBase::CurrentThemeManager()
166 {
167 auto pipelineContext = OHOS::Ace::PipelineBase::GetCurrentContext();
168 #ifdef PLUGIN_COMPONENT_SUPPORTED
169 if (Container::CurrentId() >= MIN_PLUGIN_SUBCONTAINER_ID) {
170 auto pluginContainer = PluginManager::GetInstance().GetPluginSubContainer(Container::CurrentId());
171 CHECK_NULL_RETURN(pluginContainer, nullptr);
172 pipelineContext = pluginContainer->GetPipelineContext();
173 }
174 #endif
175 CHECK_NULL_RETURN(pipelineContext, nullptr);
176 return pipelineContext->GetThemeManager();
177 }
178
GetTimeFromExternalTimer()179 uint64_t PipelineBase::GetTimeFromExternalTimer()
180 {
181 static const int64_t secToNanosec = 1000000000;
182 struct timespec ts;
183 clock_gettime(CLOCK_MONOTONIC, &ts);
184 return (ts.tv_sec * secToNanosec + ts.tv_nsec);
185 }
186
RequestFrame()187 void PipelineBase::RequestFrame()
188 {
189 window_->RequestFrame();
190 }
191
GetFrontend() const192 RefPtr<Frontend> PipelineBase::GetFrontend() const
193 {
194 return weakFrontend_.Upgrade();
195 }
196
ClearImageCache()197 void PipelineBase::ClearImageCache()
198 {
199 std::lock_guard<std::shared_mutex> lock(imageMtx_);
200 if (imageCache_) {
201 imageCache_->Clear();
202 }
203 }
204
SetImageCache(const RefPtr<ImageCache> & imageCache)205 void PipelineBase::SetImageCache(const RefPtr<ImageCache>& imageCache)
206 {
207 std::lock_guard<std::shared_mutex> lock(imageMtx_);
208 if (imageCache) {
209 imageCache_ = imageCache;
210 }
211 }
212
GetImageCache() const213 RefPtr<ImageCache> PipelineBase::GetImageCache() const
214 {
215 std::shared_lock<std::shared_mutex> lock(imageMtx_);
216 return imageCache_;
217 }
218
SetRootSize(double density,float width,float height)219 void PipelineBase::SetRootSize(double density, float width, float height)
220 {
221 ACE_SCOPED_TRACE("SetRootSize(%lf, %f, %f)", density, width, height);
222 density_ = density;
223 auto task = [weak = AceType::WeakClaim(this), width, height]() {
224 auto context = weak.Upgrade();
225 if (!context) {
226 return;
227 }
228 context->SetRootRect(width, height);
229 };
230
231 if (taskExecutor_->WillRunOnCurrentThread(TaskExecutor::TaskType::UI)) {
232 task();
233 } else {
234 taskExecutor_->PostTask(task, TaskExecutor::TaskType::UI, "ArkUISetRootSize");
235 }
236 }
237
SetFontScale(float fontScale)238 void PipelineBase::SetFontScale(float fontScale)
239 {
240 const static float CARD_MAX_FONT_SCALE = 1.3f;
241 if (!NearEqual(fontScale_, fontScale)) {
242 fontScale_ = fontScale;
243 if ((isJsCard_ || (isFormRender_ && !isDynamicRender_)) && GreatOrEqual(fontScale_, CARD_MAX_FONT_SCALE)) {
244 fontScale_ = CARD_MAX_FONT_SCALE;
245 }
246 auto pipelineContext = PipelineContext::GetCurrentContext();
247 CHECK_NULL_VOID(pipelineContext);
248 pipelineContext->RebuildFontNode();
249 }
250 }
251
SetFontWeightScale(float fontWeightScale)252 void PipelineBase::SetFontWeightScale(float fontWeightScale)
253 {
254 const static float CARD_MAX_FONT_WEIGHT_SCALE = 1.25f;
255 if (!NearEqual(fontWeightScale_, fontWeightScale)) {
256 fontWeightScale_ = fontWeightScale;
257 if (isJsCard_ && GreatOrEqual(fontWeightScale_, CARD_MAX_FONT_WEIGHT_SCALE)) {
258 fontWeightScale_ = CARD_MAX_FONT_WEIGHT_SCALE;
259 }
260 auto pipelineContext = PipelineContext::GetCurrentContext();
261 CHECK_NULL_VOID(pipelineContext);
262 pipelineContext->RebuildFontNode();
263 }
264 }
265
NormalizeToPx(const Dimension & dimension) const266 double PipelineBase::NormalizeToPx(const Dimension& dimension) const
267 {
268 if ((dimension.Unit() == DimensionUnit::VP) || (dimension.Unit() == DimensionUnit::FP)) {
269 return (dimension.Value() * dipScale_);
270 } else if (dimension.Unit() == DimensionUnit::LPX) {
271 return (dimension.Value() * designWidthScale_);
272 }
273 return dimension.Value();
274 }
275
ConvertPxToVp(const Dimension & dimension) const276 double PipelineBase::ConvertPxToVp(const Dimension& dimension) const
277 {
278 if (dimension.Unit() == DimensionUnit::PX) {
279 return dimension.Value() / dipScale_;
280 }
281 return dimension.Value();
282 }
283
UpdateFontWeightScale()284 void PipelineBase::UpdateFontWeightScale()
285 {
286 if (fontManager_) {
287 fontManager_->UpdateFontWeightScale();
288 }
289 }
290
SetTextFieldManager(const RefPtr<ManagerInterface> & manager)291 void PipelineBase::SetTextFieldManager(const RefPtr<ManagerInterface>& manager)
292 {
293 textFieldManager_ = manager;
294 }
295
RegisterFont(const std::string & familyName,const std::string & familySrc,const std::string & bundleName,const std::string & moduleName)296 void PipelineBase::RegisterFont(const std::string& familyName, const std::string& familySrc,
297 const std::string& bundleName, const std::string& moduleName)
298 {
299 if (fontManager_) {
300 fontManager_->RegisterFont(familyName, familySrc, AceType::Claim(this), bundleName, moduleName);
301 }
302 }
303
GetSystemFontList(std::vector<std::string> & fontList)304 void PipelineBase::GetSystemFontList(std::vector<std::string>& fontList)
305 {
306 if (fontManager_) {
307 fontManager_->GetSystemFontList(fontList);
308 }
309 }
310
GetSystemFont(const std::string & fontName,FontInfo & fontInfo)311 bool PipelineBase::GetSystemFont(const std::string& fontName, FontInfo& fontInfo)
312 {
313 if (fontManager_) {
314 return fontManager_->GetSystemFont(fontName, fontInfo);
315 }
316 return false;
317 }
318
GetUIFontConfig(FontConfigJsonInfo & fontConfigJsonInfo)319 void PipelineBase::GetUIFontConfig(FontConfigJsonInfo& fontConfigJsonInfo)
320 {
321 if (fontManager_) {
322 fontManager_->GetUIFontConfig(fontConfigJsonInfo);
323 }
324 }
325
HyperlinkStartAbility(const std::string & address) const326 void PipelineBase::HyperlinkStartAbility(const std::string& address) const
327 {
328 CHECK_RUN_ON(UI);
329 if (startAbilityHandler_) {
330 startAbilityHandler_(address);
331 }
332 }
333
NotifyStatusBarBgColor(const Color & color) const334 void PipelineBase::NotifyStatusBarBgColor(const Color& color) const
335 {
336 CHECK_RUN_ON(UI);
337 if (statusBarBgColorEventHandler_) {
338 statusBarBgColorEventHandler_(color);
339 }
340 }
341
NotifyPopupDismiss() const342 void PipelineBase::NotifyPopupDismiss() const
343 {
344 CHECK_RUN_ON(UI);
345 if (popupEventHandler_) {
346 popupEventHandler_();
347 }
348 }
349
NotifyMenuDismiss() const350 void PipelineBase::NotifyMenuDismiss() const
351 {
352 CHECK_RUN_ON(UI);
353 if (menuEventHandler_) {
354 menuEventHandler_();
355 }
356 }
357
NotifyContextMenuDismiss() const358 void PipelineBase::NotifyContextMenuDismiss() const
359 {
360 CHECK_RUN_ON(UI);
361 if (contextMenuEventHandler_) {
362 contextMenuEventHandler_();
363 }
364 }
365
NotifyRouterBackDismiss() const366 void PipelineBase::NotifyRouterBackDismiss() const
367 {
368 CHECK_RUN_ON(UI);
369 if (routerBackEventHandler_) {
370 routerBackEventHandler_();
371 }
372 }
373
NotifyPopPageSuccessDismiss(const std::string & pageUrl,const int32_t pageId) const374 void PipelineBase::NotifyPopPageSuccessDismiss(const std::string& pageUrl, const int32_t pageId) const
375 {
376 CHECK_RUN_ON(UI);
377 for (auto& iterPopSuccessHander : popPageSuccessEventHandler_) {
378 if (iterPopSuccessHander) {
379 iterPopSuccessHander(pageUrl, pageId);
380 }
381 }
382 }
383
NotifyIsPagePathInvalidDismiss(bool isPageInvalid) const384 void PipelineBase::NotifyIsPagePathInvalidDismiss(bool isPageInvalid) const
385 {
386 CHECK_RUN_ON(UI);
387 for (auto& iterPathInvalidHandler : isPagePathInvalidEventHandler_) {
388 if (iterPathInvalidHandler) {
389 iterPathInvalidHandler(isPageInvalid);
390 }
391 }
392 }
393
NotifyDestroyEventDismiss() const394 void PipelineBase::NotifyDestroyEventDismiss() const
395 {
396 CHECK_RUN_ON(UI);
397 for (auto& iterDestroyEventHander : destroyEventHandler_) {
398 if (iterDestroyEventHander) {
399 iterDestroyEventHander();
400 }
401 }
402 }
403
NotifyDispatchTouchEventDismiss(const TouchEvent & event) const404 void PipelineBase::NotifyDispatchTouchEventDismiss(const TouchEvent& event) const
405 {
406 CHECK_RUN_ON(UI);
407 for (auto& iterDispatchTouchEventHandler : dispatchTouchEventHandler_) {
408 if (iterDispatchTouchEventHandler) {
409 iterDispatchTouchEventHandler(event);
410 }
411 }
412 }
413
OnActionEvent(const std::string & action)414 void PipelineBase::OnActionEvent(const std::string& action)
415 {
416 CHECK_RUN_ON(UI);
417 if (actionEventHandler_) {
418 actionEventHandler_(action);
419 }
420 }
421
onRouterChange(const std::string & url)422 void PipelineBase::onRouterChange(const std::string& url)
423 {
424 if (onRouterChangeCallback_ != nullptr) {
425 onRouterChangeCallback_(url);
426 }
427 }
428
TryLoadImageInfo(const std::string & src,std::function<void (bool,int32_t,int32_t)> && loadCallback)429 void PipelineBase::TryLoadImageInfo(const std::string& src, std::function<void(bool, int32_t, int32_t)>&& loadCallback)
430 {
431 ImageProvider::TryLoadImageInfo(AceType::Claim(this), src, std::move(loadCallback));
432 }
433
CreateOffscreenCanvas(int32_t width,int32_t height)434 RefPtr<OffscreenCanvas> PipelineBase::CreateOffscreenCanvas(int32_t width, int32_t height)
435 {
436 return RenderOffscreenCanvas::Create(AceType::WeakClaim(this), width, height);
437 }
438
PostAsyncEvent(TaskExecutor::Task && task,const std::string & name,TaskExecutor::TaskType type)439 void PipelineBase::PostAsyncEvent(TaskExecutor::Task&& task, const std::string& name, TaskExecutor::TaskType type)
440 {
441 if (taskExecutor_) {
442 taskExecutor_->PostTask(std::move(task), type, name);
443 }
444 }
445
PostAsyncEvent(const TaskExecutor::Task & task,const std::string & name,TaskExecutor::TaskType type)446 void PipelineBase::PostAsyncEvent(const TaskExecutor::Task& task, const std::string& name, TaskExecutor::TaskType type)
447 {
448 if (taskExecutor_) {
449 taskExecutor_->PostTask(task, type, name);
450 }
451 }
452
PostSyncEvent(const TaskExecutor::Task & task,const std::string & name,TaskExecutor::TaskType type)453 void PipelineBase::PostSyncEvent(const TaskExecutor::Task& task, const std::string& name, TaskExecutor::TaskType type)
454 {
455 if (taskExecutor_) {
456 taskExecutor_->PostSyncTask(task, type, name);
457 }
458 }
459
UpdateRootSizeAndScale(int32_t width,int32_t height)460 void PipelineBase::UpdateRootSizeAndScale(int32_t width, int32_t height)
461 {
462 auto frontend = weakFrontend_.Upgrade();
463 CHECK_NULL_VOID(frontend);
464 auto lock = frontend->GetLock();
465 auto& windowConfig = frontend->GetWindowConfig();
466 if (windowConfig.designWidth <= 0) {
467 return;
468 }
469 if (GetIsDeclarative()) {
470 viewScale_ = DEFAULT_VIEW_SCALE;
471 double pageWidth = width;
472 if (IsContainerModalVisible()) {
473 pageWidth -= 2 * (CONTAINER_BORDER_WIDTH + CONTENT_PADDING).ConvertToPx();
474 }
475 designWidthScale_ =
476 windowConfig.autoDesignWidth ? density_ : pageWidth / windowConfig.designWidth;
477 windowConfig.designWidthScale = designWidthScale_;
478 } else {
479 viewScale_ = windowConfig.autoDesignWidth ? density_ : static_cast<double>(width) / windowConfig.designWidth;
480 }
481 if (NearZero(viewScale_)) {
482 return;
483 }
484 dipScale_ = density_ / viewScale_;
485 rootHeight_ = height / viewScale_;
486 rootWidth_ = width / viewScale_;
487 }
488
DumpFrontend() const489 void PipelineBase::DumpFrontend() const
490 {
491 auto frontend = weakFrontend_.Upgrade();
492 CHECK_NULL_VOID(frontend);
493 auto lock = frontend->GetLock();
494 frontend->DumpFrontend();
495 }
496
Dump(const std::vector<std::string> & params) const497 bool PipelineBase::Dump(const std::vector<std::string>& params) const
498 {
499 if (params.empty()) {
500 return false;
501 }
502 // the first param is the key word of dump.
503 if (params[0] == "-memory") {
504 MemoryMonitor::GetInstance().Dump();
505 return true;
506 }
507 if (params[0] == "-jscrash") {
508 EventReport::JsErrReport(
509 AceApplicationInfo::GetInstance().GetPackageName(), "js crash reason", "js crash summary");
510 return true;
511 }
512 // hiview report dump will provide three params .
513 if (params[0] == "-hiviewreport" && params.size() >= 3) {
514 DumpLog::GetInstance().Print("Report hiview event. EventType: " + params[1] + ", error type: " + params[2]);
515 EventInfo eventInfo = { .eventType = params[1], .errorType = StringUtils::StringToInt(params[2]) };
516 EventReport::SendEvent(eventInfo);
517 return true;
518 }
519 ContainerScope scope(instanceId_);
520 if (params[0] == "-frontend") {
521 DumpFrontend();
522 return true;
523 }
524 return OnDumpInfo(params);
525 }
526
IsDestroyed()527 bool PipelineBase::IsDestroyed()
528 {
529 return destroyed_;
530 }
531
SetDestroyed()532 void PipelineBase::SetDestroyed()
533 {
534 destroyed_ = true;
535 }
536
ForceLayoutForImplicitAnimation()537 void PipelineBase::ForceLayoutForImplicitAnimation()
538 {
539 if (!pendingImplicitLayout_.empty()) {
540 pendingImplicitLayout_.top() = true;
541 }
542 if (!pendingFrontendAnimation_.empty()) {
543 pendingFrontendAnimation_.top() = true;
544 }
545 }
546
ForceRenderForImplicitAnimation()547 void PipelineBase::ForceRenderForImplicitAnimation()
548 {
549 if (!pendingImplicitRender_.empty()) {
550 pendingImplicitRender_.top() = true;
551 }
552 if (!pendingFrontendAnimation_.empty()) {
553 pendingFrontendAnimation_.top() = true;
554 }
555 }
556
Animate(const AnimationOption & option,const RefPtr<Curve> & curve,const std::function<void ()> & propertyCallback,const std::function<void ()> & finishCallback)557 bool PipelineBase::Animate(const AnimationOption& option, const RefPtr<Curve>& curve,
558 const std::function<void()>& propertyCallback, const std::function<void()>& finishCallback)
559 {
560 if (!propertyCallback) {
561 return false;
562 }
563
564 OpenImplicitAnimation(option, curve, finishCallback);
565 propertyCallback();
566 return CloseImplicitAnimation();
567 }
568
GetWrappedAnimationCallback(const std::function<void ()> & finishCallback)569 std::function<void()> PipelineBase::GetWrappedAnimationCallback(const std::function<void()>& finishCallback)
570 {
571 if (!IsFormRender() && !finishCallback) {
572 return nullptr;
573 }
574 auto finishPtr = std::make_shared<std::function<void()>>(finishCallback);
575 finishFunctions_.emplace(finishPtr);
576 auto wrapFinishCallback = [weak = AceType::WeakClaim(this),
577 finishWeak = std::weak_ptr<std::function<void()>>(finishPtr)]() {
578 auto context = weak.Upgrade();
579 CHECK_NULL_VOID(context);
580 auto finishPtr = finishWeak.lock();
581 CHECK_NULL_VOID(finishPtr);
582 context->finishFunctions_.erase(finishPtr);
583 if (!(*finishPtr)) {
584 if (context->IsFormRender()) {
585 TAG_LOGI(AceLogTag::ACE_FORM, "[Form animation] Form animation is finish.");
586 context->SetIsFormAnimation(false);
587 }
588 return;
589 }
590 if (context->IsFormRender()) {
591 TAG_LOGI(AceLogTag::ACE_FORM, "[Form animation] Form animation is finish.");
592 context->SetFormAnimationFinishCallback(true);
593 (*finishPtr)();
594 context->FlushBuild();
595 context->SetFormAnimationFinishCallback(false);
596 context->SetIsFormAnimation(false);
597 return;
598 }
599 (*finishPtr)();
600 };
601 return wrapFinishCallback;
602 }
603
PrepareOpenImplicitAnimation()604 void PipelineBase::PrepareOpenImplicitAnimation()
605 {
606 #ifdef ENABLE_ROSEN_BACKEND
607 // initialize false for implicit animation layout and render pending flag
608 pendingImplicitLayout_.push(false);
609 pendingImplicitRender_.push(false);
610
611 // flush ui tasks before open implicit animation
612 if (!IsLayouting()) {
613 FlushUITasks(true);
614 }
615 #endif
616 }
617
PrepareCloseImplicitAnimation()618 void PipelineBase::PrepareCloseImplicitAnimation()
619 {
620 #ifdef ENABLE_ROSEN_BACKEND
621 if (pendingImplicitLayout_.empty() && pendingImplicitRender_.empty()) {
622 return;
623 }
624
625 // layout or render the views immediately to animate all related views, if layout or render updates are pending in
626 // the animation closure
627 if (pendingImplicitLayout_.top() || pendingImplicitRender_.top()) {
628 if (!IsLayouting()) {
629 FlushUITasks(true);
630 } else if (IsLayouting()) {
631 LOGW("IsLayouting, prepareCloseImplicitAnimation has tasks not flushed");
632 }
633 }
634 if (!pendingImplicitLayout_.empty()) {
635 pendingImplicitLayout_.pop();
636 }
637 if (!pendingImplicitRender_.empty()) {
638 pendingImplicitRender_.pop();
639 }
640 #endif
641 }
642
OpenImplicitAnimation(const AnimationOption & option,const RefPtr<Curve> & curve,const std::function<void ()> & finishCallback)643 void PipelineBase::OpenImplicitAnimation(
644 const AnimationOption& option,
645 const RefPtr<Curve>& curve,
646 const std::function<void()>& finishCallback)
647 {
648 #ifdef ENABLE_ROSEN_BACKEND
649 PrepareOpenImplicitAnimation();
650 StartImplicitAnimation(option, curve, finishCallback);
651 #endif
652 }
653
StartImplicitAnimation(const AnimationOption & option,const RefPtr<Curve> & curve,const std::function<void ()> & finishCallback)654 void PipelineBase::StartImplicitAnimation(const AnimationOption& option, const RefPtr<Curve>& curve,
655 const std::function<void()>& finishCallback)
656 {
657 #ifdef ENABLE_ROSEN_BACKEND
658 auto wrapFinishCallback = GetWrappedAnimationCallback(finishCallback);
659 if (IsFormRender()) {
660 SetIsFormAnimation(true);
661 if (!IsFormAnimationFinishCallback()) {
662 SetFormAnimationStartTime(GetMicroTickCount());
663 }
664 }
665 AnimationUtils::OpenImplicitAnimation(option, curve, wrapFinishCallback);
666 #endif
667 }
668
CloseImplicitAnimation()669 bool PipelineBase::CloseImplicitAnimation()
670 {
671 #ifdef ENABLE_ROSEN_BACKEND
672 PrepareCloseImplicitAnimation();
673 return AnimationUtils::CloseImplicitAnimation();
674 #else
675 return false;
676 #endif
677 }
678
OnVsyncEvent(uint64_t nanoTimestamp,uint32_t frameCount)679 void PipelineBase::OnVsyncEvent(uint64_t nanoTimestamp, uint32_t frameCount)
680 {
681 CHECK_RUN_ON(UI);
682 ACE_SCOPED_TRACE("OnVsyncEvent now:%" PRIu64 "", nanoTimestamp);
683 frameCount_ = frameCount;
684
685 recvTime_ = GetSysTimestamp();
686 compensationValue_ =
687 nanoTimestamp > static_cast<uint64_t>(recvTime_) ? (nanoTimestamp - static_cast<uint64_t>(recvTime_)) : 0;
688
689 for (auto& callback : subWindowVsyncCallbacks_) {
690 callback.second(nanoTimestamp, frameCount);
691 }
692
693 decltype(jsFormVsyncCallbacks_) jsFormVsyncCallbacks(std::move(jsFormVsyncCallbacks_));
694 for (auto& callback : jsFormVsyncCallbacks) {
695 callback.second(nanoTimestamp, frameCount);
696 }
697
698 if (onVsyncProfiler_) {
699 AceTracker::Start();
700 }
701
702 if (gsVsyncCallback_) {
703 gsVsyncCallback_();
704 }
705
706 FlushVsync(nanoTimestamp, frameCount);
707 if (onVsyncProfiler_) {
708 onVsyncProfiler_(AceTracker::Stop());
709 }
710 }
711
SetTouchPipeline(const WeakPtr<PipelineBase> & context)712 void PipelineBase::SetTouchPipeline(const WeakPtr<PipelineBase>& context)
713 {
714 auto result = std::find(touchPluginPipelineContext_.begin(), touchPluginPipelineContext_.end(), context);
715 if (result == touchPluginPipelineContext_.end()) {
716 touchPluginPipelineContext_.emplace_back(context);
717 }
718 }
719
RemoveTouchPipeline(const WeakPtr<PipelineBase> & context)720 void PipelineBase::RemoveTouchPipeline(const WeakPtr<PipelineBase>& context)
721 {
722 auto result = std::find(touchPluginPipelineContext_.begin(), touchPluginPipelineContext_.end(), context);
723 if (result != touchPluginPipelineContext_.end()) {
724 touchPluginPipelineContext_.erase(result);
725 }
726 }
727
OnVirtualKeyboardAreaChange(Rect keyboardArea,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,const float safeHeight,bool supportAvoidance,bool forceChange)728 void PipelineBase::OnVirtualKeyboardAreaChange(Rect keyboardArea,
729 const std::shared_ptr<Rosen::RSTransaction>& rsTransaction, const float safeHeight, bool supportAvoidance,
730 bool forceChange)
731 {
732 auto currentContainer = Container::Current();
733 if (currentContainer && !currentContainer->IsSubContainer()) {
734 #ifdef OHOS_STANDARD_SYSTEM
735 auto subwindow = SubwindowManager::GetInstance()->GetSubwindow(currentContainer->GetInstanceId());
736 if (subwindow && subwindow->GetShown()) {
737 // subwindow is shown, main window no need to handle the keyboard event
738 return;
739 }
740 #endif
741 }
742 double keyboardHeight = keyboardArea.Height();
743 if (NotifyVirtualKeyBoard(rootWidth_, rootHeight_, keyboardHeight)) {
744 return;
745 }
746 OnVirtualKeyboardHeightChange(keyboardHeight, rsTransaction, safeHeight, supportAvoidance, forceChange);
747 }
748
OnVirtualKeyboardAreaChange(Rect keyboardArea,double positionY,double height,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,bool forceChange)749 void PipelineBase::OnVirtualKeyboardAreaChange(Rect keyboardArea, double positionY, double height,
750 const std::shared_ptr<Rosen::RSTransaction>& rsTransaction, bool forceChange)
751 {
752 auto currentContainer = Container::Current();
753 float keyboardHeight = keyboardArea.Height();
754 if (currentContainer && !currentContainer->IsSubContainer()) {
755 auto subwindow = SubwindowManager::GetInstance()->GetSubwindow(currentContainer->GetInstanceId());
756 if (subwindow && subwindow->GetShown() && subwindow->IsFocused() && !CheckNeedAvoidInSubWindow()) {
757 // subwindow is shown, main window doesn't lift, no need to handle the keyboard event
758 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "subwindow is shown and pageOffset is zero, main window doesn't lift");
759 CheckAndUpdateKeyboardInset(keyboardHeight);
760 return;
761 }
762 }
763 if (NotifyVirtualKeyBoard(rootWidth_, rootHeight_, keyboardHeight)) {
764 return;
765 }
766 OnVirtualKeyboardHeightChange(keyboardHeight, positionY, height, rsTransaction, forceChange);
767 }
768
OnFoldStatusChanged(FoldStatus foldStatus)769 void PipelineBase::OnFoldStatusChanged(FoldStatus foldStatus)
770 {
771 OnFoldStatusChange(foldStatus);
772 }
773
OnFoldDisplayModeChanged(FoldDisplayMode foldDisplayMode)774 void PipelineBase::OnFoldDisplayModeChanged(FoldDisplayMode foldDisplayMode)
775 {
776 OnFoldDisplayModeChange(foldDisplayMode);
777 }
778
ModifyKeyboardHeight(double keyboardHeight) const779 double PipelineBase::ModifyKeyboardHeight(double keyboardHeight) const
780 {
781 auto windowRect = GetCurrentWindowRect();
782 auto deviceHeight = SystemProperties::GetDeviceHeight();
783 return keyboardHeight > 0.0 && keyboardHeight - (deviceHeight - windowRect.Bottom()) > 0.0
784 ? keyboardHeight - (deviceHeight - windowRect.Bottom())
785 : 0.0;
786 }
787
SetGetWindowRectImpl(std::function<Rect ()> && callback)788 void PipelineBase::SetGetWindowRectImpl(std::function<Rect()>&& callback)
789 {
790 if (window_) {
791 window_->SetGetWindowRectImpl(std::move(callback));
792 }
793 }
794
ContainerModalUnFocus()795 void PipelineBase::ContainerModalUnFocus() {}
796
GetCurrentWindowRect() const797 Rect PipelineBase::GetCurrentWindowRect() const
798 {
799 if (window_) {
800 return window_->GetCurrentWindowRect();
801 }
802 return {};
803 }
804
HasFloatTitle() const805 bool PipelineBase::HasFloatTitle() const
806 {
807 CHECK_NULL_RETURN(windowManager_, false);
808 return GetWindowModal() == WindowModal::CONTAINER_MODAL &&
809 windowManager_->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING;
810 }
811
GetAccessibilityManager() const812 RefPtr<AccessibilityManager> PipelineBase::GetAccessibilityManager() const
813 {
814 auto frontend = weakFrontend_.Upgrade();
815 if (!frontend) {
816 EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
817 return nullptr;
818 }
819 auto lock = frontend->GetLock();
820 return frontend->GetAccessibilityManager();
821 }
822
SendEventToAccessibility(const AccessibilityEvent & accessibilityEvent)823 void PipelineBase::SendEventToAccessibility(const AccessibilityEvent& accessibilityEvent)
824 {
825 auto accessibilityManager = GetAccessibilityManager();
826 if (!accessibilityManager || !AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
827 return;
828 }
829 accessibilityManager->SendAccessibilityAsyncEvent(accessibilityEvent);
830 }
831
SetAccessibilityEventCallback(std::function<void (uint32_t,int64_t)> && callback)832 void PipelineBase::SetAccessibilityEventCallback(std::function<void(uint32_t, int64_t)>&& callback)
833 {
834 ACE_FUNCTION_TRACE();
835 accessibilityCallback_ = callback;
836 }
837
AddAccessibilityCallbackEvent(AccessibilityCallbackEventId event,int64_t parameter)838 void PipelineBase::AddAccessibilityCallbackEvent(AccessibilityCallbackEventId event, int64_t parameter)
839 {
840 ACE_SCOPED_TRACE("AccessibilityCallbackEvent event[%u]", static_cast<uint32_t>(event));
841 accessibilityEvents_.insert(AccessibilityCallbackEvent(event, parameter));
842 }
843
FireAccessibilityEvents()844 void PipelineBase::FireAccessibilityEvents()
845 {
846 if (!accessibilityCallback_ || accessibilityEvents_.empty()) {
847 return;
848 }
849
850 std::set<AccessibilityCallbackEvent> localEvents;
851 {
852 localEvents.swap(accessibilityEvents_);
853 }
854
855 for (const auto& event : localEvents) {
856 accessibilityCallback_(static_cast<uint32_t>(event.eventId), event.parameter);
857 }
858 }
859
SetSubWindowVsyncCallback(AceVsyncCallback && callback,int32_t subWindowId)860 void PipelineBase::SetSubWindowVsyncCallback(AceVsyncCallback&& callback, int32_t subWindowId)
861 {
862 if (callback) {
863 subWindowVsyncCallbacks_.try_emplace(subWindowId, std::move(callback));
864 }
865 }
866
SetJsFormVsyncCallback(AceVsyncCallback && callback,int32_t subWindowId)867 void PipelineBase::SetJsFormVsyncCallback(AceVsyncCallback&& callback, int32_t subWindowId)
868 {
869 if (callback) {
870 jsFormVsyncCallbacks_.try_emplace(subWindowId, std::move(callback));
871 }
872 }
873
AddEtsCardTouchEventCallback(int32_t pointId,EtsCardTouchEventCallback && callback)874 void PipelineBase::AddEtsCardTouchEventCallback(int32_t pointId, EtsCardTouchEventCallback&& callback)
875 {
876 if (!callback || pointId < 0) {
877 return;
878 }
879
880 etsCardTouchEventCallback_[pointId] = std::move(callback);
881 }
882
HandleEtsCardTouchEvent(const TouchEvent & point,SerializedGesture & serializedGesture)883 void PipelineBase::HandleEtsCardTouchEvent(const TouchEvent& point,
884 SerializedGesture& serializedGesture)
885 {
886 if (point.id < 0) {
887 return;
888 }
889
890 auto iter = etsCardTouchEventCallback_.find(point.id);
891 if (iter == etsCardTouchEventCallback_.end()) {
892 return;
893 }
894 if (iter->second) {
895 iter->second(point, serializedGesture);
896 }
897 }
898
RemoveEtsCardTouchEventCallback(int32_t pointId)899 void PipelineBase::RemoveEtsCardTouchEventCallback(int32_t pointId)
900 {
901 if (pointId < 0) {
902 return;
903 }
904
905 auto iter = etsCardTouchEventCallback_.find(pointId);
906 if (iter == etsCardTouchEventCallback_.end()) {
907 return;
908 }
909
910 etsCardTouchEventCallback_.erase(iter);
911 }
912
RemoveSubWindowVsyncCallback(int32_t subWindowId)913 void PipelineBase::RemoveSubWindowVsyncCallback(int32_t subWindowId)
914 {
915 subWindowVsyncCallbacks_.erase(subWindowId);
916 }
917
RemoveJsFormVsyncCallback(int32_t subWindowId)918 void PipelineBase::RemoveJsFormVsyncCallback(int32_t subWindowId)
919 {
920 jsFormVsyncCallbacks_.erase(subWindowId);
921 }
922
MaybeRelease()923 bool PipelineBase::MaybeRelease()
924 {
925 CHECK_NULL_RETURN(taskExecutor_, true);
926 if (taskExecutor_->WillRunOnCurrentThread(TaskExecutor::TaskType::UI)) {
927 LOGI("Destroy Pipeline on UI thread.");
928 return true;
929 } else {
930 std::lock_guard lock(destructMutex_);
931 LOGI("Post Destroy Pipeline Task to UI thread.");
932 return !taskExecutor_->PostTask([this] { delete this; }, TaskExecutor::TaskType::UI, "ArkUIDestroyPipeline");
933 }
934 }
935
Destroy()936 void PipelineBase::Destroy()
937 {
938 CHECK_RUN_ON(UI);
939 destroyed_ = true;
940 ClearImageCache();
941 platformResRegister_.Reset();
942 drawDelegate_.reset();
943 eventManager_->ClearResults();
944 {
945 std::unique_lock<std::shared_mutex> lock(imageMtx_);
946 imageCache_.Reset();
947 }
948 {
949 std::unique_lock<std::shared_mutex> lock(themeMtx_);
950 themeManager_.Reset();
951 }
952 fontManager_.Reset();
953 window_->Destroy();
954 touchPluginPipelineContext_.clear();
955 virtualKeyBoardCallback_.clear();
956 etsCardTouchEventCallback_.clear();
957 formLinkInfoMap_.clear();
958 TAG_LOGI(AceLogTag::ACE_ANIMATION, "pipeline destroyed, has %{public}zu finish callbacks not executed",
959 finishFunctions_.size());
960 finishFunctions_.clear();
961 animationOption_ = {};
962 {
963 // To avoid the race condition caused by the offscreen canvas get density from the pipeline in the worker
964 // thread.
965 std::lock_guard lock(densityChangeMutex_);
966 densityChangedCallbacks_.clear();
967 }
968 }
969
OnFormRecycle()970 std::string PipelineBase::OnFormRecycle()
971 {
972 if (onFormRecycle_) {
973 return onFormRecycle_();
974 }
975 LOGE("onFormRecycle_ is null.");
976 return "";
977 }
978
OnFormRecover(const std::string & statusData)979 void PipelineBase::OnFormRecover(const std::string& statusData)
980 {
981 if (onFormRecover_) {
982 return onFormRecover_(statusData);
983 }
984 LOGE("onFormRecover_ is null.");
985 }
986
SetUiDvsyncSwitch(bool on)987 void PipelineBase::SetUiDvsyncSwitch(bool on)
988 {
989 if (window_) {
990 window_->SetUiDvsyncSwitch(on);
991 }
992 }
993 } // namespace OHOS::Ace
994