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 DumpUIExt();
506 return true;
507 }
508 if (params[0] == "-jscrash") {
509 EventReport::JsErrReport(
510 AceApplicationInfo::GetInstance().GetPackageName(), "js crash reason", "js crash summary");
511 return true;
512 }
513 // hiview report dump will provide three params .
514 if (params[0] == "-hiviewreport" && params.size() >= 3) {
515 DumpLog::GetInstance().Print("Report hiview event. EventType: " + params[1] + ", error type: " + params[2]);
516 EventInfo eventInfo = { .eventType = params[1], .errorType = StringUtils::StringToInt(params[2]) };
517 EventReport::SendEvent(eventInfo);
518 return true;
519 }
520 ContainerScope scope(instanceId_);
521 if (params[0] == "-frontend") {
522 DumpFrontend();
523 DumpUIExt();
524 return true;
525 }
526 return OnDumpInfo(params);
527 }
528
IsDestroyed()529 bool PipelineBase::IsDestroyed()
530 {
531 return destroyed_;
532 }
533
SetDestroyed()534 void PipelineBase::SetDestroyed()
535 {
536 destroyed_ = true;
537 }
538
ForceLayoutForImplicitAnimation()539 void PipelineBase::ForceLayoutForImplicitAnimation()
540 {
541 if (!pendingImplicitLayout_.empty()) {
542 pendingImplicitLayout_.top() = true;
543 }
544 if (!pendingFrontendAnimation_.empty()) {
545 pendingFrontendAnimation_.top() = true;
546 }
547 }
548
ForceRenderForImplicitAnimation()549 void PipelineBase::ForceRenderForImplicitAnimation()
550 {
551 if (!pendingImplicitRender_.empty()) {
552 pendingImplicitRender_.top() = true;
553 }
554 if (!pendingFrontendAnimation_.empty()) {
555 pendingFrontendAnimation_.top() = true;
556 }
557 }
558
Animate(const AnimationOption & option,const RefPtr<Curve> & curve,const std::function<void ()> & propertyCallback,const std::function<void ()> & finishCallback)559 bool PipelineBase::Animate(const AnimationOption& option, const RefPtr<Curve>& curve,
560 const std::function<void()>& propertyCallback, const std::function<void()>& finishCallback)
561 {
562 if (!propertyCallback) {
563 return false;
564 }
565
566 OpenImplicitAnimation(option, curve, finishCallback);
567 propertyCallback();
568 return CloseImplicitAnimation();
569 }
570
GetWrappedAnimationCallback(const std::function<void ()> & finishCallback)571 std::function<void()> PipelineBase::GetWrappedAnimationCallback(const std::function<void()>& finishCallback)
572 {
573 if (!IsFormRender() && !finishCallback) {
574 return nullptr;
575 }
576 auto finishPtr = std::make_shared<std::function<void()>>(finishCallback);
577 finishFunctions_.emplace(finishPtr);
578 auto wrapFinishCallback = [weak = AceType::WeakClaim(this),
579 finishWeak = std::weak_ptr<std::function<void()>>(finishPtr)]() {
580 auto context = weak.Upgrade();
581 CHECK_NULL_VOID(context);
582 auto finishPtr = finishWeak.lock();
583 CHECK_NULL_VOID(finishPtr);
584 context->finishFunctions_.erase(finishPtr);
585 if (!(*finishPtr)) {
586 if (context->IsFormRender()) {
587 TAG_LOGI(AceLogTag::ACE_FORM, "[Form animation] Form animation is finish.");
588 context->SetIsFormAnimation(false);
589 }
590 return;
591 }
592 if (context->IsFormRender()) {
593 TAG_LOGI(AceLogTag::ACE_FORM, "[Form animation] Form animation is finish.");
594 context->SetFormAnimationFinishCallback(true);
595 (*finishPtr)();
596 context->FlushBuild();
597 context->SetFormAnimationFinishCallback(false);
598 context->SetIsFormAnimation(false);
599 return;
600 }
601 (*finishPtr)();
602 };
603 return wrapFinishCallback;
604 }
605
PrepareOpenImplicitAnimation()606 void PipelineBase::PrepareOpenImplicitAnimation()
607 {
608 #ifdef ENABLE_ROSEN_BACKEND
609 // initialize false for implicit animation layout and render pending flag
610 pendingImplicitLayout_.push(false);
611 pendingImplicitRender_.push(false);
612
613 // flush ui tasks before open implicit animation
614 if (!IsLayouting()) {
615 FlushUITasks(true);
616 }
617 #endif
618 }
619
PrepareCloseImplicitAnimation()620 void PipelineBase::PrepareCloseImplicitAnimation()
621 {
622 #ifdef ENABLE_ROSEN_BACKEND
623 if (pendingImplicitLayout_.empty() && pendingImplicitRender_.empty()) {
624 return;
625 }
626
627 // layout or render the views immediately to animate all related views, if layout or render updates are pending in
628 // the animation closure
629 if (pendingImplicitLayout_.top() || pendingImplicitRender_.top()) {
630 if (!IsLayouting()) {
631 FlushUITasks(true);
632 } else if (IsLayouting()) {
633 LOGW("IsLayouting, prepareCloseImplicitAnimation has tasks not flushed");
634 }
635 }
636 if (!pendingImplicitLayout_.empty()) {
637 pendingImplicitLayout_.pop();
638 }
639 if (!pendingImplicitRender_.empty()) {
640 pendingImplicitRender_.pop();
641 }
642 #endif
643 }
644
OpenImplicitAnimation(const AnimationOption & option,const RefPtr<Curve> & curve,const std::function<void ()> & finishCallback)645 void PipelineBase::OpenImplicitAnimation(
646 const AnimationOption& option,
647 const RefPtr<Curve>& curve,
648 const std::function<void()>& finishCallback)
649 {
650 #ifdef ENABLE_ROSEN_BACKEND
651 PrepareOpenImplicitAnimation();
652 StartImplicitAnimation(option, curve, finishCallback);
653 #endif
654 }
655
StartImplicitAnimation(const AnimationOption & option,const RefPtr<Curve> & curve,const std::function<void ()> & finishCallback)656 void PipelineBase::StartImplicitAnimation(const AnimationOption& option, const RefPtr<Curve>& curve,
657 const std::function<void()>& finishCallback)
658 {
659 #ifdef ENABLE_ROSEN_BACKEND
660 auto wrapFinishCallback = GetWrappedAnimationCallback(finishCallback);
661 if (IsFormRender()) {
662 SetIsFormAnimation(true);
663 if (!IsFormAnimationFinishCallback()) {
664 SetFormAnimationStartTime(GetMicroTickCount());
665 }
666 }
667 AnimationUtils::OpenImplicitAnimation(option, curve, wrapFinishCallback);
668 #endif
669 }
670
CloseImplicitAnimation()671 bool PipelineBase::CloseImplicitAnimation()
672 {
673 #ifdef ENABLE_ROSEN_BACKEND
674 PrepareCloseImplicitAnimation();
675 return AnimationUtils::CloseImplicitAnimation();
676 #else
677 return false;
678 #endif
679 }
680
OnVsyncEvent(uint64_t nanoTimestamp,uint32_t frameCount)681 void PipelineBase::OnVsyncEvent(uint64_t nanoTimestamp, uint32_t frameCount)
682 {
683 CHECK_RUN_ON(UI);
684 ACE_SCOPED_TRACE("OnVsyncEvent now:%" PRIu64 "", nanoTimestamp);
685 frameCount_ = frameCount;
686
687 recvTime_ = GetSysTimestamp();
688 compensationValue_ =
689 nanoTimestamp > static_cast<uint64_t>(recvTime_) ? (nanoTimestamp - static_cast<uint64_t>(recvTime_)) : 0;
690
691 for (auto& callback : subWindowVsyncCallbacks_) {
692 callback.second(nanoTimestamp, frameCount);
693 }
694
695 decltype(jsFormVsyncCallbacks_) jsFormVsyncCallbacks(std::move(jsFormVsyncCallbacks_));
696 for (auto& callback : jsFormVsyncCallbacks) {
697 callback.second(nanoTimestamp, frameCount);
698 }
699
700 if (onVsyncProfiler_) {
701 AceTracker::Start();
702 }
703
704 if (gsVsyncCallback_) {
705 gsVsyncCallback_();
706 }
707
708 FlushVsync(nanoTimestamp, frameCount);
709 if (onVsyncProfiler_) {
710 onVsyncProfiler_(AceTracker::Stop());
711 }
712 }
713
SetTouchPipeline(const WeakPtr<PipelineBase> & context)714 void PipelineBase::SetTouchPipeline(const WeakPtr<PipelineBase>& context)
715 {
716 auto result = std::find(touchPluginPipelineContext_.begin(), touchPluginPipelineContext_.end(), context);
717 if (result == touchPluginPipelineContext_.end()) {
718 touchPluginPipelineContext_.emplace_back(context);
719 }
720 }
721
RemoveTouchPipeline(const WeakPtr<PipelineBase> & context)722 void PipelineBase::RemoveTouchPipeline(const WeakPtr<PipelineBase>& context)
723 {
724 auto result = std::find(touchPluginPipelineContext_.begin(), touchPluginPipelineContext_.end(), context);
725 if (result != touchPluginPipelineContext_.end()) {
726 touchPluginPipelineContext_.erase(result);
727 }
728 }
729
OnVirtualKeyboardAreaChange(Rect keyboardArea,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,const float safeHeight,bool supportAvoidance,bool forceChange)730 void PipelineBase::OnVirtualKeyboardAreaChange(Rect keyboardArea,
731 const std::shared_ptr<Rosen::RSTransaction>& rsTransaction, const float safeHeight, bool supportAvoidance,
732 bool forceChange)
733 {
734 auto currentContainer = Container::Current();
735 if (currentContainer && !currentContainer->IsSubContainer()) {
736 #ifdef OHOS_STANDARD_SYSTEM
737 auto subwindow = SubwindowManager::GetInstance()->GetSubwindow(currentContainer->GetInstanceId());
738 if (subwindow && subwindow->GetShown()) {
739 // subwindow is shown, main window no need to handle the keyboard event
740 return;
741 }
742 #endif
743 }
744 double keyboardHeight = keyboardArea.Height();
745 if (NotifyVirtualKeyBoard(rootWidth_, rootHeight_, keyboardHeight)) {
746 return;
747 }
748 OnVirtualKeyboardHeightChange(keyboardHeight, rsTransaction, safeHeight, supportAvoidance, forceChange);
749 }
750
OnVirtualKeyboardAreaChange(Rect keyboardArea,double positionY,double height,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,bool forceChange)751 void PipelineBase::OnVirtualKeyboardAreaChange(Rect keyboardArea, double positionY, double height,
752 const std::shared_ptr<Rosen::RSTransaction>& rsTransaction, bool forceChange)
753 {
754 auto currentContainer = Container::Current();
755 float keyboardHeight = keyboardArea.Height();
756 if (currentContainer && !currentContainer->IsSubContainer()) {
757 auto subwindow = SubwindowManager::GetInstance()->GetSubwindow(currentContainer->GetInstanceId());
758 if (subwindow && subwindow->GetShown() && subwindow->IsFocused() && !CheckNeedAvoidInSubWindow()) {
759 // subwindow is shown, main window doesn't lift, no need to handle the keyboard event
760 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "subwindow is shown and pageOffset is zero, main window doesn't lift");
761 CheckAndUpdateKeyboardInset(keyboardHeight);
762 return;
763 }
764 }
765 if (NotifyVirtualKeyBoard(rootWidth_, rootHeight_, keyboardHeight)) {
766 return;
767 }
768 OnVirtualKeyboardHeightChange(keyboardHeight, positionY, height, rsTransaction, forceChange);
769 }
770
OnFoldStatusChanged(FoldStatus foldStatus)771 void PipelineBase::OnFoldStatusChanged(FoldStatus foldStatus)
772 {
773 OnFoldStatusChange(foldStatus);
774 }
775
OnFoldDisplayModeChanged(FoldDisplayMode foldDisplayMode)776 void PipelineBase::OnFoldDisplayModeChanged(FoldDisplayMode foldDisplayMode)
777 {
778 OnFoldDisplayModeChange(foldDisplayMode);
779 }
780
ModifyKeyboardHeight(double keyboardHeight) const781 double PipelineBase::ModifyKeyboardHeight(double keyboardHeight) const
782 {
783 auto windowRect = GetCurrentWindowRect();
784 auto deviceHeight = SystemProperties::GetDeviceHeight();
785 return keyboardHeight > 0.0 && keyboardHeight - (deviceHeight - windowRect.Bottom()) > 0.0
786 ? keyboardHeight - (deviceHeight - windowRect.Bottom())
787 : 0.0;
788 }
789
SetGetWindowRectImpl(std::function<Rect ()> && callback)790 void PipelineBase::SetGetWindowRectImpl(std::function<Rect()>&& callback)
791 {
792 if (window_) {
793 window_->SetGetWindowRectImpl(std::move(callback));
794 }
795 }
796
ContainerModalUnFocus()797 void PipelineBase::ContainerModalUnFocus() {}
798
GetCurrentWindowRect() const799 Rect PipelineBase::GetCurrentWindowRect() const
800 {
801 if (window_) {
802 return window_->GetCurrentWindowRect();
803 }
804 return {};
805 }
806
HasFloatTitle() const807 bool PipelineBase::HasFloatTitle() const
808 {
809 CHECK_NULL_RETURN(windowManager_, false);
810 return GetWindowModal() == WindowModal::CONTAINER_MODAL &&
811 windowManager_->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING;
812 }
813
GetAccessibilityManager() const814 RefPtr<AccessibilityManager> PipelineBase::GetAccessibilityManager() const
815 {
816 auto frontend = weakFrontend_.Upgrade();
817 if (!frontend) {
818 EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
819 return nullptr;
820 }
821 auto lock = frontend->GetLock();
822 return frontend->GetAccessibilityManager();
823 }
824
SendEventToAccessibility(const AccessibilityEvent & accessibilityEvent)825 void PipelineBase::SendEventToAccessibility(const AccessibilityEvent& accessibilityEvent)
826 {
827 auto accessibilityManager = GetAccessibilityManager();
828 if (!accessibilityManager || !AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
829 return;
830 }
831 accessibilityManager->SendAccessibilityAsyncEvent(accessibilityEvent);
832 }
833
FireUIExtensionEventValid()834 bool PipelineBase::FireUIExtensionEventValid()
835 {
836 if (!uiExtensionEventCallback_ || !IsFocusWindowIdSetted()) {
837 return false;
838 }
839 return true;
840 }
841
SetUIExtensionEventCallback(std::function<void (uint32_t)> && callback)842 void PipelineBase::SetUIExtensionEventCallback(std::function<void(uint32_t)>&& callback)
843 {
844 ACE_FUNCTION_TRACE();
845 uiExtensionEventCallback_ = callback;
846 }
847
AddUIExtensionCallbackEvent(NG::UIExtCallbackEventId eventId)848 void PipelineBase::AddUIExtensionCallbackEvent(NG::UIExtCallbackEventId eventId)
849 {
850 ACE_SCOPED_TRACE("AddUIExtensionCallbackEvent event[%u]", static_cast<uint32_t>(eventId));
851 uiExtensionEvents_.insert(NG::UIExtCallbackEvent(eventId));
852 }
853
FireAllUIExtensionEvents()854 void PipelineBase::FireAllUIExtensionEvents()
855 {
856 if (!FireUIExtensionEventValid() || uiExtensionEvents_.empty()) {
857 return;
858 }
859 std::vector<uint32_t> eventIds;
860 for (auto it = uiExtensionEvents_.begin(); it != uiExtensionEvents_.end();) {
861 eventIds.push_back(static_cast<uint32_t>(it->eventId));
862 if (!it->repeat) {
863 it = uiExtensionEvents_.erase(it);
864 } else {
865 ++it;
866 }
867 }
868 for (auto id : eventIds) {
869 FireUIExtensionEventInner(id);
870 }
871 }
872
FireUIExtensionEventOnceImmediately(NG::UIExtCallbackEventId eventId)873 void PipelineBase::FireUIExtensionEventOnceImmediately(NG::UIExtCallbackEventId eventId)
874 {
875 if (!FireUIExtensionEventValid()) {
876 return;
877 }
878 FireUIExtensionEventInner(static_cast<uint32_t>(eventId));
879 }
880
FireUIExtensionEventInner(uint32_t eventId)881 void PipelineBase::FireUIExtensionEventInner(uint32_t eventId)
882 {
883 auto callback = uiExtensionEventCallback_;
884 callback(eventId);
885 }
886
SetAccessibilityEventCallback(std::function<void (uint32_t,int64_t)> && callback)887 void PipelineBase::SetAccessibilityEventCallback(std::function<void(uint32_t, int64_t)>&& callback)
888 {
889 ACE_FUNCTION_TRACE();
890 accessibilityCallback_ = callback;
891 }
892
AddAccessibilityCallbackEvent(AccessibilityCallbackEventId event,int64_t parameter)893 void PipelineBase::AddAccessibilityCallbackEvent(AccessibilityCallbackEventId event, int64_t parameter)
894 {
895 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
896 ACE_SCOPED_TRACE("AccessibilityCallbackEvent event[%u]", static_cast<uint32_t>(event));
897 accessibilityEvents_.insert(AccessibilityCallbackEvent(event, parameter));
898 }
899 }
900
FireAccessibilityEvents()901 void PipelineBase::FireAccessibilityEvents()
902 {
903 if (!accessibilityCallback_ || accessibilityEvents_.empty()) {
904 return;
905 }
906
907 std::set<AccessibilityCallbackEvent> localEvents;
908 {
909 localEvents.swap(accessibilityEvents_);
910 }
911
912 for (const auto& event : localEvents) {
913 accessibilityCallback_(static_cast<uint32_t>(event.eventId), event.parameter);
914 }
915 }
916
SetSubWindowVsyncCallback(AceVsyncCallback && callback,int32_t subWindowId)917 void PipelineBase::SetSubWindowVsyncCallback(AceVsyncCallback&& callback, int32_t subWindowId)
918 {
919 if (callback) {
920 subWindowVsyncCallbacks_.try_emplace(subWindowId, std::move(callback));
921 }
922 }
923
SetJsFormVsyncCallback(AceVsyncCallback && callback,int32_t subWindowId)924 void PipelineBase::SetJsFormVsyncCallback(AceVsyncCallback&& callback, int32_t subWindowId)
925 {
926 if (callback) {
927 jsFormVsyncCallbacks_.try_emplace(subWindowId, std::move(callback));
928 }
929 }
930
AddEtsCardTouchEventCallback(int32_t pointId,EtsCardTouchEventCallback && callback)931 void PipelineBase::AddEtsCardTouchEventCallback(int32_t pointId, EtsCardTouchEventCallback&& callback)
932 {
933 if (!callback || pointId < 0) {
934 return;
935 }
936
937 etsCardTouchEventCallback_[pointId] = std::move(callback);
938 }
939
HandleEtsCardTouchEvent(const TouchEvent & point,SerializedGesture & serializedGesture)940 void PipelineBase::HandleEtsCardTouchEvent(const TouchEvent& point,
941 SerializedGesture& serializedGesture)
942 {
943 if (point.id < 0) {
944 return;
945 }
946
947 auto iter = etsCardTouchEventCallback_.find(point.id);
948 if (iter == etsCardTouchEventCallback_.end()) {
949 return;
950 }
951 if (iter->second) {
952 iter->second(point, serializedGesture);
953 }
954 }
955
RemoveEtsCardTouchEventCallback(int32_t pointId)956 void PipelineBase::RemoveEtsCardTouchEventCallback(int32_t pointId)
957 {
958 if (pointId < 0) {
959 return;
960 }
961
962 auto iter = etsCardTouchEventCallback_.find(pointId);
963 if (iter == etsCardTouchEventCallback_.end()) {
964 return;
965 }
966
967 etsCardTouchEventCallback_.erase(iter);
968 }
969
RemoveSubWindowVsyncCallback(int32_t subWindowId)970 void PipelineBase::RemoveSubWindowVsyncCallback(int32_t subWindowId)
971 {
972 subWindowVsyncCallbacks_.erase(subWindowId);
973 }
974
RemoveJsFormVsyncCallback(int32_t subWindowId)975 void PipelineBase::RemoveJsFormVsyncCallback(int32_t subWindowId)
976 {
977 jsFormVsyncCallbacks_.erase(subWindowId);
978 }
979
MaybeRelease()980 bool PipelineBase::MaybeRelease()
981 {
982 CHECK_NULL_RETURN(taskExecutor_, true);
983 if (taskExecutor_->WillRunOnCurrentThread(TaskExecutor::TaskType::UI)) {
984 LOGI("Destroy Pipeline on UI thread.");
985 return true;
986 } else {
987 std::lock_guard lock(destructMutex_);
988 LOGI("Post Destroy Pipeline Task to UI thread.");
989 return !taskExecutor_->PostTask([this] { delete this; }, TaskExecutor::TaskType::UI, "ArkUIDestroyPipeline");
990 }
991 }
992
Destroy()993 void PipelineBase::Destroy()
994 {
995 CHECK_RUN_ON(UI);
996 destroyed_ = true;
997 ClearImageCache();
998 platformResRegister_.Reset();
999 drawDelegate_.reset();
1000 eventManager_->ClearResults();
1001 {
1002 std::unique_lock<std::shared_mutex> lock(imageMtx_);
1003 imageCache_.Reset();
1004 }
1005 {
1006 std::unique_lock<std::shared_mutex> lock(themeMtx_);
1007 themeManager_.Reset();
1008 }
1009 fontManager_.Reset();
1010 window_->Destroy();
1011 touchPluginPipelineContext_.clear();
1012 virtualKeyBoardCallback_.clear();
1013 etsCardTouchEventCallback_.clear();
1014 formLinkInfoMap_.clear();
1015 TAG_LOGI(AceLogTag::ACE_ANIMATION, "pipeline destroyed, has %{public}zu finish callbacks not executed",
1016 finishFunctions_.size());
1017 finishFunctions_.clear();
1018 animationOption_ = {};
1019 {
1020 // To avoid the race condition caused by the offscreen canvas get density from the pipeline in the worker
1021 // thread.
1022 std::lock_guard lock(densityChangeMutex_);
1023 densityChangedCallbacks_.clear();
1024 }
1025 }
1026
OnFormRecycle()1027 std::string PipelineBase::OnFormRecycle()
1028 {
1029 if (onFormRecycle_) {
1030 return onFormRecycle_();
1031 }
1032 LOGE("onFormRecycle_ is null.");
1033 return "";
1034 }
1035
OnFormRecover(const std::string & statusData)1036 void PipelineBase::OnFormRecover(const std::string& statusData)
1037 {
1038 if (onFormRecover_) {
1039 return onFormRecover_(statusData);
1040 }
1041 LOGE("onFormRecover_ is null.");
1042 }
1043
SetUiDvsyncSwitch(bool on)1044 void PipelineBase::SetUiDvsyncSwitch(bool on)
1045 {
1046 if (window_) {
1047 window_->SetUiDvsyncSwitch(on);
1048 }
1049 }
1050 } // namespace OHOS::Ace
1051