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
NeedTouchInterpolation()252 bool PipelineBase::NeedTouchInterpolation()
253 {
254 if (!IsFocusWindowIdSetted()) {
255 return true;
256 }
257 auto container = Container::GetContainer(instanceId_);
258 CHECK_NULL_RETURN(container, false);
259 auto uIContentType = container->GetUIContentType();
260 return uIContentType == UIContentType::SECURITY_UI_EXTENSION ||
261 uIContentType == UIContentType::MODAL_UI_EXTENSION;
262 }
263
SetFontWeightScale(float fontWeightScale)264 void PipelineBase::SetFontWeightScale(float fontWeightScale)
265 {
266 const static float CARD_MAX_FONT_WEIGHT_SCALE = 1.25f;
267 if (!NearEqual(fontWeightScale_, fontWeightScale)) {
268 fontWeightScale_ = fontWeightScale;
269 if (isJsCard_ && GreatOrEqual(fontWeightScale_, CARD_MAX_FONT_WEIGHT_SCALE)) {
270 fontWeightScale_ = CARD_MAX_FONT_WEIGHT_SCALE;
271 }
272 auto pipelineContext = PipelineContext::GetCurrentContext();
273 CHECK_NULL_VOID(pipelineContext);
274 pipelineContext->RebuildFontNode();
275 }
276 }
277
NormalizeToPx(const Dimension & dimension) const278 double PipelineBase::NormalizeToPx(const Dimension& dimension) const
279 {
280 if ((dimension.Unit() == DimensionUnit::VP) || (dimension.Unit() == DimensionUnit::FP)) {
281 return (dimension.Value() * dipScale_);
282 } else if (dimension.Unit() == DimensionUnit::LPX) {
283 return (dimension.Value() * designWidthScale_);
284 }
285 return dimension.Value();
286 }
287
ConvertPxToVp(const Dimension & dimension) const288 double PipelineBase::ConvertPxToVp(const Dimension& dimension) const
289 {
290 if (dimension.Unit() == DimensionUnit::PX) {
291 return dimension.Value() / dipScale_;
292 }
293 return dimension.Value();
294 }
295
UpdateFontWeightScale()296 void PipelineBase::UpdateFontWeightScale()
297 {
298 if (fontManager_) {
299 fontManager_->UpdateFontWeightScale();
300 }
301 }
302
SetTextFieldManager(const RefPtr<ManagerInterface> & manager)303 void PipelineBase::SetTextFieldManager(const RefPtr<ManagerInterface>& manager)
304 {
305 textFieldManager_ = manager;
306 }
307
RegisterFont(const std::string & familyName,const std::string & familySrc,const std::string & bundleName,const std::string & moduleName)308 void PipelineBase::RegisterFont(const std::string& familyName, const std::string& familySrc,
309 const std::string& bundleName, const std::string& moduleName)
310 {
311 if (fontManager_) {
312 fontManager_->RegisterFont(familyName, familySrc, AceType::Claim(this), bundleName, moduleName);
313 }
314 }
315
GetSystemFontList(std::vector<std::string> & fontList)316 void PipelineBase::GetSystemFontList(std::vector<std::string>& fontList)
317 {
318 if (fontManager_) {
319 fontManager_->GetSystemFontList(fontList);
320 }
321 }
322
GetSystemFont(const std::string & fontName,FontInfo & fontInfo)323 bool PipelineBase::GetSystemFont(const std::string& fontName, FontInfo& fontInfo)
324 {
325 if (fontManager_) {
326 return fontManager_->GetSystemFont(fontName, fontInfo);
327 }
328 return false;
329 }
330
GetUIFontConfig(FontConfigJsonInfo & fontConfigJsonInfo)331 void PipelineBase::GetUIFontConfig(FontConfigJsonInfo& fontConfigJsonInfo)
332 {
333 if (fontManager_) {
334 fontManager_->GetUIFontConfig(fontConfigJsonInfo);
335 }
336 }
337
HyperlinkStartAbility(const std::string & address) const338 void PipelineBase::HyperlinkStartAbility(const std::string& address) const
339 {
340 CHECK_RUN_ON(UI);
341 if (startAbilityHandler_) {
342 startAbilityHandler_(address);
343 }
344 }
345
NotifyStatusBarBgColor(const Color & color) const346 void PipelineBase::NotifyStatusBarBgColor(const Color& color) const
347 {
348 CHECK_RUN_ON(UI);
349 if (statusBarBgColorEventHandler_) {
350 statusBarBgColorEventHandler_(color);
351 }
352 }
353
NotifyPopupDismiss() const354 void PipelineBase::NotifyPopupDismiss() const
355 {
356 CHECK_RUN_ON(UI);
357 if (popupEventHandler_) {
358 popupEventHandler_();
359 }
360 }
361
NotifyMenuDismiss() const362 void PipelineBase::NotifyMenuDismiss() const
363 {
364 CHECK_RUN_ON(UI);
365 if (menuEventHandler_) {
366 menuEventHandler_();
367 }
368 }
369
NotifyContextMenuDismiss() const370 void PipelineBase::NotifyContextMenuDismiss() const
371 {
372 CHECK_RUN_ON(UI);
373 if (contextMenuEventHandler_) {
374 contextMenuEventHandler_();
375 }
376 }
377
NotifyRouterBackDismiss() const378 void PipelineBase::NotifyRouterBackDismiss() const
379 {
380 CHECK_RUN_ON(UI);
381 if (routerBackEventHandler_) {
382 routerBackEventHandler_();
383 }
384 }
385
NotifyPopPageSuccessDismiss(const std::string & pageUrl,const int32_t pageId) const386 void PipelineBase::NotifyPopPageSuccessDismiss(const std::string& pageUrl, const int32_t pageId) const
387 {
388 CHECK_RUN_ON(UI);
389 for (auto& iterPopSuccessHander : popPageSuccessEventHandler_) {
390 if (iterPopSuccessHander) {
391 iterPopSuccessHander(pageUrl, pageId);
392 }
393 }
394 }
395
NotifyIsPagePathInvalidDismiss(bool isPageInvalid) const396 void PipelineBase::NotifyIsPagePathInvalidDismiss(bool isPageInvalid) const
397 {
398 CHECK_RUN_ON(UI);
399 for (auto& iterPathInvalidHandler : isPagePathInvalidEventHandler_) {
400 if (iterPathInvalidHandler) {
401 iterPathInvalidHandler(isPageInvalid);
402 }
403 }
404 }
405
NotifyDestroyEventDismiss() const406 void PipelineBase::NotifyDestroyEventDismiss() const
407 {
408 CHECK_RUN_ON(UI);
409 for (auto& iterDestroyEventHander : destroyEventHandler_) {
410 if (iterDestroyEventHander) {
411 iterDestroyEventHander();
412 }
413 }
414 }
415
NotifyDispatchTouchEventDismiss(const TouchEvent & event) const416 void PipelineBase::NotifyDispatchTouchEventDismiss(const TouchEvent& event) const
417 {
418 CHECK_RUN_ON(UI);
419 for (auto& iterDispatchTouchEventHandler : dispatchTouchEventHandler_) {
420 if (iterDispatchTouchEventHandler) {
421 iterDispatchTouchEventHandler(event);
422 }
423 }
424 }
425
OnActionEvent(const std::string & action)426 void PipelineBase::OnActionEvent(const std::string& action)
427 {
428 CHECK_RUN_ON(UI);
429 if (actionEventHandler_) {
430 actionEventHandler_(action);
431 }
432 }
433
onRouterChange(const std::string & url)434 void PipelineBase::onRouterChange(const std::string& url)
435 {
436 if (onRouterChangeCallback_ != nullptr) {
437 onRouterChangeCallback_(url);
438 }
439 }
440
TryLoadImageInfo(const std::string & src,std::function<void (bool,int32_t,int32_t)> && loadCallback)441 void PipelineBase::TryLoadImageInfo(const std::string& src, std::function<void(bool, int32_t, int32_t)>&& loadCallback)
442 {
443 ImageProvider::TryLoadImageInfo(AceType::Claim(this), src, std::move(loadCallback));
444 }
445
CreateOffscreenCanvas(int32_t width,int32_t height)446 RefPtr<OffscreenCanvas> PipelineBase::CreateOffscreenCanvas(int32_t width, int32_t height)
447 {
448 return RenderOffscreenCanvas::Create(AceType::WeakClaim(this), width, height);
449 }
450
PostAsyncEvent(TaskExecutor::Task && task,const std::string & name,TaskExecutor::TaskType type)451 void PipelineBase::PostAsyncEvent(TaskExecutor::Task&& task, const std::string& name, TaskExecutor::TaskType type)
452 {
453 if (taskExecutor_) {
454 taskExecutor_->PostTask(std::move(task), type, name);
455 }
456 }
457
PostAsyncEvent(const TaskExecutor::Task & task,const std::string & name,TaskExecutor::TaskType type)458 void PipelineBase::PostAsyncEvent(const TaskExecutor::Task& task, const std::string& name, TaskExecutor::TaskType type)
459 {
460 if (taskExecutor_) {
461 taskExecutor_->PostTask(task, type, name);
462 }
463 }
464
PostSyncEvent(const TaskExecutor::Task & task,const std::string & name,TaskExecutor::TaskType type)465 void PipelineBase::PostSyncEvent(const TaskExecutor::Task& task, const std::string& name, TaskExecutor::TaskType type)
466 {
467 if (taskExecutor_) {
468 taskExecutor_->PostSyncTask(task, type, name);
469 }
470 }
471
UpdateRootSizeAndScale(int32_t width,int32_t height)472 void PipelineBase::UpdateRootSizeAndScale(int32_t width, int32_t height)
473 {
474 auto frontend = weakFrontend_.Upgrade();
475 CHECK_NULL_VOID(frontend);
476 auto lock = frontend->GetLock();
477 auto& windowConfig = frontend->GetWindowConfig();
478 if (windowConfig.designWidth <= 0) {
479 return;
480 }
481 if (GetIsDeclarative()) {
482 viewScale_ = DEFAULT_VIEW_SCALE;
483 double pageWidth = width;
484 if (IsContainerModalVisible()) {
485 pageWidth -= 2 * (CONTAINER_BORDER_WIDTH + CONTENT_PADDING).ConvertToPx();
486 }
487 designWidthScale_ =
488 windowConfig.autoDesignWidth ? density_ : pageWidth / windowConfig.designWidth;
489 windowConfig.designWidthScale = designWidthScale_;
490 } else {
491 viewScale_ = windowConfig.autoDesignWidth ? density_ : static_cast<double>(width) / windowConfig.designWidth;
492 }
493 if (NearZero(viewScale_)) {
494 return;
495 }
496 dipScale_ = density_ / viewScale_;
497 rootHeight_ = height / viewScale_;
498 rootWidth_ = width / viewScale_;
499 }
500
DumpFrontend() const501 void PipelineBase::DumpFrontend() const
502 {
503 auto frontend = weakFrontend_.Upgrade();
504 CHECK_NULL_VOID(frontend);
505 auto lock = frontend->GetLock();
506 frontend->DumpFrontend();
507 }
508
Dump(const std::vector<std::string> & params) const509 bool PipelineBase::Dump(const std::vector<std::string>& params) const
510 {
511 if (params.empty()) {
512 return false;
513 }
514 // the first param is the key word of dump.
515 if (params[0] == "-memory") {
516 MemoryMonitor::GetInstance().Dump();
517 DumpUIExt();
518 return true;
519 }
520 if (params[0] == "-jscrash") {
521 EventReport::JsErrReport(
522 AceApplicationInfo::GetInstance().GetPackageName(), "js crash reason", "js crash summary");
523 return true;
524 }
525 // hiview report dump will provide three params .
526 if (params[0] == "-hiviewreport" && params.size() >= 3) {
527 DumpLog::GetInstance().Print("Report hiview event. EventType: " + params[1] + ", error type: " + params[2]);
528 EventInfo eventInfo = { .eventType = params[1], .errorType = StringUtils::StringToInt(params[2]) };
529 EventReport::SendEvent(eventInfo);
530 return true;
531 }
532 ContainerScope scope(instanceId_);
533 if (params[0] == "-frontend") {
534 DumpFrontend();
535 DumpUIExt();
536 return true;
537 }
538 return OnDumpInfo(params);
539 }
540
IsDestroyed()541 bool PipelineBase::IsDestroyed()
542 {
543 return destroyed_;
544 }
545
SetDestroyed()546 void PipelineBase::SetDestroyed()
547 {
548 destroyed_ = true;
549 }
550
ForceLayoutForImplicitAnimation()551 void PipelineBase::ForceLayoutForImplicitAnimation()
552 {
553 if (!pendingImplicitLayout_.empty()) {
554 pendingImplicitLayout_.top() = true;
555 }
556 if (!pendingFrontendAnimation_.empty()) {
557 pendingFrontendAnimation_.top() = true;
558 }
559 }
560
ForceRenderForImplicitAnimation()561 void PipelineBase::ForceRenderForImplicitAnimation()
562 {
563 if (!pendingImplicitRender_.empty()) {
564 pendingImplicitRender_.top() = true;
565 }
566 if (!pendingFrontendAnimation_.empty()) {
567 pendingFrontendAnimation_.top() = true;
568 }
569 }
570
Animate(const AnimationOption & option,const RefPtr<Curve> & curve,const std::function<void ()> & propertyCallback,const std::function<void ()> & finishCallback)571 bool PipelineBase::Animate(const AnimationOption& option, const RefPtr<Curve>& curve,
572 const std::function<void()>& propertyCallback, const std::function<void()>& finishCallback)
573 {
574 if (!propertyCallback) {
575 return false;
576 }
577
578 OpenImplicitAnimation(option, curve, finishCallback);
579 propertyCallback();
580 return CloseImplicitAnimation();
581 }
582
GetWrappedAnimationCallback(const std::function<void ()> & finishCallback)583 std::function<void()> PipelineBase::GetWrappedAnimationCallback(const std::function<void()>& finishCallback)
584 {
585 if (!IsFormRender() && !finishCallback) {
586 return nullptr;
587 }
588 auto finishPtr = std::make_shared<std::function<void()>>(finishCallback);
589 finishFunctions_.emplace(finishPtr);
590 auto wrapFinishCallback = [weak = AceType::WeakClaim(this),
591 finishWeak = std::weak_ptr<std::function<void()>>(finishPtr)]() {
592 auto context = weak.Upgrade();
593 CHECK_NULL_VOID(context);
594 auto finishPtr = finishWeak.lock();
595 CHECK_NULL_VOID(finishPtr);
596 context->finishFunctions_.erase(finishPtr);
597 if (!(*finishPtr)) {
598 if (context->IsFormRender()) {
599 TAG_LOGI(AceLogTag::ACE_FORM, "[Form animation] Form animation is finish.");
600 context->SetIsFormAnimation(false);
601 }
602 return;
603 }
604 if (context->IsFormRender()) {
605 TAG_LOGI(AceLogTag::ACE_FORM, "[Form animation] Form animation is finish.");
606 context->SetFormAnimationFinishCallback(true);
607 (*finishPtr)();
608 context->FlushBuild();
609 context->SetFormAnimationFinishCallback(false);
610 context->SetIsFormAnimation(false);
611 return;
612 }
613 (*finishPtr)();
614 };
615 return wrapFinishCallback;
616 }
617
PrepareOpenImplicitAnimation()618 void PipelineBase::PrepareOpenImplicitAnimation()
619 {
620 #ifdef ENABLE_ROSEN_BACKEND
621 // initialize false for implicit animation layout and render pending flag
622 pendingImplicitLayout_.push(false);
623 pendingImplicitRender_.push(false);
624
625 // flush ui tasks before open implicit animation
626 if (!IsLayouting()) {
627 FlushUITasks(true);
628 }
629 #endif
630 }
631
PrepareCloseImplicitAnimation()632 void PipelineBase::PrepareCloseImplicitAnimation()
633 {
634 #ifdef ENABLE_ROSEN_BACKEND
635 if (pendingImplicitLayout_.empty() && pendingImplicitRender_.empty()) {
636 return;
637 }
638
639 // layout or render the views immediately to animate all related views, if layout or render updates are pending in
640 // the animation closure
641 if (pendingImplicitLayout_.top() || pendingImplicitRender_.top()) {
642 if (!IsLayouting()) {
643 FlushUITasks(true);
644 } else if (IsLayouting()) {
645 LOGW("IsLayouting, prepareCloseImplicitAnimation has tasks not flushed");
646 }
647 }
648 if (!pendingImplicitLayout_.empty()) {
649 pendingImplicitLayout_.pop();
650 }
651 if (!pendingImplicitRender_.empty()) {
652 pendingImplicitRender_.pop();
653 }
654 #endif
655 }
656
OpenImplicitAnimation(const AnimationOption & option,const RefPtr<Curve> & curve,const std::function<void ()> & finishCallback)657 void PipelineBase::OpenImplicitAnimation(
658 const AnimationOption& option,
659 const RefPtr<Curve>& curve,
660 const std::function<void()>& finishCallback)
661 {
662 #ifdef ENABLE_ROSEN_BACKEND
663 PrepareOpenImplicitAnimation();
664 StartImplicitAnimation(option, curve, finishCallback);
665 #endif
666 }
667
StartImplicitAnimation(const AnimationOption & option,const RefPtr<Curve> & curve,const std::function<void ()> & finishCallback)668 void PipelineBase::StartImplicitAnimation(const AnimationOption& option, const RefPtr<Curve>& curve,
669 const std::function<void()>& finishCallback)
670 {
671 #ifdef ENABLE_ROSEN_BACKEND
672 auto wrapFinishCallback = GetWrappedAnimationCallback(finishCallback);
673 if (IsFormRender()) {
674 SetIsFormAnimation(true);
675 if (!IsFormAnimationFinishCallback()) {
676 SetFormAnimationStartTime(GetMicroTickCount());
677 }
678 }
679 AnimationUtils::OpenImplicitAnimation(option, curve, wrapFinishCallback);
680 #endif
681 }
682
CloseImplicitAnimation()683 bool PipelineBase::CloseImplicitAnimation()
684 {
685 #ifdef ENABLE_ROSEN_BACKEND
686 PrepareCloseImplicitAnimation();
687 return AnimationUtils::CloseImplicitAnimation();
688 #else
689 return false;
690 #endif
691 }
692
OnVsyncEvent(uint64_t nanoTimestamp,uint32_t frameCount)693 void PipelineBase::OnVsyncEvent(uint64_t nanoTimestamp, uint32_t frameCount)
694 {
695 CHECK_RUN_ON(UI);
696 ACE_SCOPED_TRACE("OnVsyncEvent now:%" PRIu64 "", nanoTimestamp);
697 frameCount_ = frameCount;
698
699 recvTime_ = GetSysTimestamp();
700 compensationValue_ =
701 nanoTimestamp > static_cast<uint64_t>(recvTime_) ? (nanoTimestamp - static_cast<uint64_t>(recvTime_)) : 0;
702
703 for (auto& callback : subWindowVsyncCallbacks_) {
704 callback.second(nanoTimestamp, frameCount);
705 }
706
707 decltype(jsFormVsyncCallbacks_) jsFormVsyncCallbacks(std::move(jsFormVsyncCallbacks_));
708 for (auto& callback : jsFormVsyncCallbacks) {
709 callback.second(nanoTimestamp, frameCount);
710 }
711
712 if (onVsyncProfiler_) {
713 AceTracker::Start();
714 }
715
716 if (gsVsyncCallback_) {
717 gsVsyncCallback_();
718 }
719
720 FlushVsync(nanoTimestamp, frameCount);
721 if (onVsyncProfiler_) {
722 onVsyncProfiler_(AceTracker::Stop());
723 }
724 }
725
SetTouchPipeline(const WeakPtr<PipelineBase> & context)726 void PipelineBase::SetTouchPipeline(const WeakPtr<PipelineBase>& context)
727 {
728 auto result = std::find(touchPluginPipelineContext_.begin(), touchPluginPipelineContext_.end(), context);
729 if (result == touchPluginPipelineContext_.end()) {
730 touchPluginPipelineContext_.emplace_back(context);
731 }
732 }
733
RemoveTouchPipeline(const WeakPtr<PipelineBase> & context)734 void PipelineBase::RemoveTouchPipeline(const WeakPtr<PipelineBase>& context)
735 {
736 auto result = std::find(touchPluginPipelineContext_.begin(), touchPluginPipelineContext_.end(), context);
737 if (result != touchPluginPipelineContext_.end()) {
738 touchPluginPipelineContext_.erase(result);
739 }
740 }
741
OnVirtualKeyboardAreaChange(Rect keyboardArea,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,const float safeHeight,bool supportAvoidance,bool forceChange)742 void PipelineBase::OnVirtualKeyboardAreaChange(Rect keyboardArea,
743 const std::shared_ptr<Rosen::RSTransaction>& rsTransaction, const float safeHeight, bool supportAvoidance,
744 bool forceChange)
745 {
746 auto currentContainer = Container::Current();
747 if (currentContainer && !currentContainer->IsSubContainer()) {
748 #ifdef OHOS_STANDARD_SYSTEM
749 auto subwindow = SubwindowManager::GetInstance()->GetSubwindow(currentContainer->GetInstanceId());
750 if (subwindow && subwindow->GetShown() && !subwindow->NeedAvoidKeyboard()) {
751 // subwindow is shown, main window no need to handle the keyboard event
752 return;
753 }
754 #endif
755 }
756 double keyboardHeight = keyboardArea.Height();
757 if (NotifyVirtualKeyBoard(rootWidth_, rootHeight_, keyboardHeight)) {
758 return;
759 }
760 OnVirtualKeyboardHeightChange(keyboardHeight, rsTransaction, safeHeight, supportAvoidance, forceChange);
761 }
762
OnVirtualKeyboardAreaChange(Rect keyboardArea,double positionY,double height,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,bool forceChange)763 void PipelineBase::OnVirtualKeyboardAreaChange(Rect keyboardArea, double positionY, double height,
764 const std::shared_ptr<Rosen::RSTransaction>& rsTransaction, bool forceChange)
765 {
766 auto currentContainer = Container::Current();
767 float keyboardHeight = keyboardArea.Height();
768 if (currentContainer && !currentContainer->IsSubContainer()) {
769 auto subwindow = SubwindowManager::GetInstance()->GetSubwindow(currentContainer->GetInstanceId());
770 if (subwindow && subwindow->GetShown() && subwindow->IsFocused() && !CheckNeedAvoidInSubWindow() &&
771 !subwindow->NeedAvoidKeyboard()) {
772 // subwindow is shown, main window doesn't lift, no need to handle the keyboard event
773 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "subwindow is shown and pageOffset is zero, main window doesn't lift");
774 CheckAndUpdateKeyboardInset(keyboardHeight);
775 return;
776 }
777 }
778 if (NotifyVirtualKeyBoard(rootWidth_, rootHeight_, keyboardHeight)) {
779 return;
780 }
781 OnVirtualKeyboardHeightChange(keyboardHeight, positionY, height, rsTransaction, forceChange);
782 }
783
OnFoldStatusChanged(FoldStatus foldStatus)784 void PipelineBase::OnFoldStatusChanged(FoldStatus foldStatus)
785 {
786 OnFoldStatusChange(foldStatus);
787 }
788
OnFoldDisplayModeChanged(FoldDisplayMode foldDisplayMode)789 void PipelineBase::OnFoldDisplayModeChanged(FoldDisplayMode foldDisplayMode)
790 {
791 OnFoldDisplayModeChange(foldDisplayMode);
792 }
793
ModifyKeyboardHeight(double keyboardHeight) const794 double PipelineBase::ModifyKeyboardHeight(double keyboardHeight) const
795 {
796 auto windowRect = GetCurrentWindowRect();
797 auto deviceHeight = SystemProperties::GetDeviceHeight();
798 return keyboardHeight > 0.0 && keyboardHeight - (deviceHeight - windowRect.Bottom()) > 0.0
799 ? keyboardHeight - (deviceHeight - windowRect.Bottom())
800 : 0.0;
801 }
802
SetGetWindowRectImpl(std::function<Rect ()> && callback)803 void PipelineBase::SetGetWindowRectImpl(std::function<Rect()>&& callback)
804 {
805 if (window_) {
806 window_->SetGetWindowRectImpl(std::move(callback));
807 }
808 }
809
ContainerModalUnFocus()810 void PipelineBase::ContainerModalUnFocus() {}
811
GetCurrentWindowRect() const812 Rect PipelineBase::GetCurrentWindowRect() const
813 {
814 if (window_) {
815 return window_->GetCurrentWindowRect();
816 }
817 return {};
818 }
819
HasFloatTitle() const820 bool PipelineBase::HasFloatTitle() const
821 {
822 CHECK_NULL_RETURN(windowManager_, false);
823 return GetWindowModal() == WindowModal::CONTAINER_MODAL &&
824 windowManager_->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING;
825 }
826
GetAccessibilityManager() const827 RefPtr<AccessibilityManager> PipelineBase::GetAccessibilityManager() const
828 {
829 auto frontend = weakFrontend_.Upgrade();
830 if (!frontend) {
831 EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
832 return nullptr;
833 }
834 auto lock = frontend->GetLock();
835 return frontend->GetAccessibilityManager();
836 }
837
SendEventToAccessibility(const AccessibilityEvent & accessibilityEvent)838 void PipelineBase::SendEventToAccessibility(const AccessibilityEvent& accessibilityEvent)
839 {
840 auto accessibilityManager = GetAccessibilityManager();
841 if (!accessibilityManager || !AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
842 return;
843 }
844 accessibilityManager->SendAccessibilityAsyncEvent(accessibilityEvent);
845 }
846
FireUIExtensionEventValid()847 bool PipelineBase::FireUIExtensionEventValid()
848 {
849 if (!uiExtensionEventCallback_ || !IsFocusWindowIdSetted()) {
850 return false;
851 }
852 return true;
853 }
854
SetUIExtensionEventCallback(std::function<void (uint32_t)> && callback)855 void PipelineBase::SetUIExtensionEventCallback(std::function<void(uint32_t)>&& callback)
856 {
857 ACE_FUNCTION_TRACE();
858 uiExtensionEventCallback_ = callback;
859 }
860
AddUIExtensionCallbackEvent(NG::UIExtCallbackEventId eventId)861 void PipelineBase::AddUIExtensionCallbackEvent(NG::UIExtCallbackEventId eventId)
862 {
863 ACE_SCOPED_TRACE("AddUIExtensionCallbackEvent event[%u]", static_cast<uint32_t>(eventId));
864 uiExtensionEvents_.insert(NG::UIExtCallbackEvent(eventId));
865 }
866
FireAllUIExtensionEvents()867 void PipelineBase::FireAllUIExtensionEvents()
868 {
869 if (!FireUIExtensionEventValid() || uiExtensionEvents_.empty()) {
870 return;
871 }
872 std::vector<uint32_t> eventIds;
873 for (auto it = uiExtensionEvents_.begin(); it != uiExtensionEvents_.end();) {
874 eventIds.push_back(static_cast<uint32_t>(it->eventId));
875 if (!it->repeat) {
876 it = uiExtensionEvents_.erase(it);
877 } else {
878 ++it;
879 }
880 }
881 for (auto id : eventIds) {
882 FireUIExtensionEventInner(id);
883 }
884 }
885
FireUIExtensionEventOnceImmediately(NG::UIExtCallbackEventId eventId)886 void PipelineBase::FireUIExtensionEventOnceImmediately(NG::UIExtCallbackEventId eventId)
887 {
888 if (!FireUIExtensionEventValid()) {
889 return;
890 }
891 FireUIExtensionEventInner(static_cast<uint32_t>(eventId));
892 }
893
FireUIExtensionEventInner(uint32_t eventId)894 void PipelineBase::FireUIExtensionEventInner(uint32_t eventId)
895 {
896 auto callback = uiExtensionEventCallback_;
897 callback(eventId);
898 }
899
SetAccessibilityEventCallback(std::function<void (uint32_t,int64_t)> && callback)900 void PipelineBase::SetAccessibilityEventCallback(std::function<void(uint32_t, int64_t)>&& callback)
901 {
902 ACE_FUNCTION_TRACE();
903 accessibilityCallback_ = callback;
904 }
905
AddAccessibilityCallbackEvent(AccessibilityCallbackEventId event,int64_t parameter)906 void PipelineBase::AddAccessibilityCallbackEvent(AccessibilityCallbackEventId event, int64_t parameter)
907 {
908 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
909 ACE_SCOPED_TRACE("AccessibilityCallbackEvent event[%u]", static_cast<uint32_t>(event));
910 accessibilityEvents_.insert(AccessibilityCallbackEvent(event, parameter));
911 }
912 }
913
FireAccessibilityEvents()914 void PipelineBase::FireAccessibilityEvents()
915 {
916 if (!accessibilityCallback_ || accessibilityEvents_.empty()) {
917 return;
918 }
919
920 std::set<AccessibilityCallbackEvent> localEvents;
921 {
922 localEvents.swap(accessibilityEvents_);
923 }
924
925 for (const auto& event : localEvents) {
926 accessibilityCallback_(static_cast<uint32_t>(event.eventId), event.parameter);
927 }
928 }
929
SetSubWindowVsyncCallback(AceVsyncCallback && callback,int32_t subWindowId)930 void PipelineBase::SetSubWindowVsyncCallback(AceVsyncCallback&& callback, int32_t subWindowId)
931 {
932 if (callback) {
933 subWindowVsyncCallbacks_.try_emplace(subWindowId, std::move(callback));
934 }
935 }
936
SetJsFormVsyncCallback(AceVsyncCallback && callback,int32_t subWindowId)937 void PipelineBase::SetJsFormVsyncCallback(AceVsyncCallback&& callback, int32_t subWindowId)
938 {
939 if (callback) {
940 jsFormVsyncCallbacks_.try_emplace(subWindowId, std::move(callback));
941 }
942 }
943
AddEtsCardTouchEventCallback(int32_t pointId,EtsCardTouchEventCallback && callback)944 void PipelineBase::AddEtsCardTouchEventCallback(int32_t pointId, EtsCardTouchEventCallback&& callback)
945 {
946 if (!callback || pointId < 0) {
947 return;
948 }
949
950 etsCardTouchEventCallback_[pointId] = std::move(callback);
951 }
952
HandleEtsCardTouchEvent(const TouchEvent & point,SerializedGesture & serializedGesture)953 void PipelineBase::HandleEtsCardTouchEvent(const TouchEvent& point,
954 SerializedGesture& serializedGesture)
955 {
956 if (point.id < 0) {
957 return;
958 }
959
960 auto iter = etsCardTouchEventCallback_.find(point.id);
961 if (iter == etsCardTouchEventCallback_.end()) {
962 return;
963 }
964 if (iter->second) {
965 iter->second(point, serializedGesture);
966 }
967 }
968
RemoveEtsCardTouchEventCallback(int32_t pointId)969 void PipelineBase::RemoveEtsCardTouchEventCallback(int32_t pointId)
970 {
971 if (pointId < 0) {
972 return;
973 }
974
975 auto iter = etsCardTouchEventCallback_.find(pointId);
976 if (iter == etsCardTouchEventCallback_.end()) {
977 return;
978 }
979
980 etsCardTouchEventCallback_.erase(iter);
981 }
982
RemoveSubWindowVsyncCallback(int32_t subWindowId)983 void PipelineBase::RemoveSubWindowVsyncCallback(int32_t subWindowId)
984 {
985 subWindowVsyncCallbacks_.erase(subWindowId);
986 }
987
RemoveJsFormVsyncCallback(int32_t subWindowId)988 void PipelineBase::RemoveJsFormVsyncCallback(int32_t subWindowId)
989 {
990 jsFormVsyncCallbacks_.erase(subWindowId);
991 }
992
MaybeRelease()993 bool PipelineBase::MaybeRelease()
994 {
995 CHECK_NULL_RETURN(taskExecutor_, true);
996 if (taskExecutor_->WillRunOnCurrentThread(TaskExecutor::TaskType::UI)) {
997 LOGI("Destroy Pipeline on UI thread.");
998 return true;
999 } else {
1000 std::lock_guard lock(destructMutex_);
1001 LOGI("Post Destroy Pipeline Task to UI thread.");
1002 return !taskExecutor_->PostTask([this] { delete this; }, TaskExecutor::TaskType::UI, "ArkUIDestroyPipeline");
1003 }
1004 }
1005
Destroy()1006 void PipelineBase::Destroy()
1007 {
1008 CHECK_RUN_ON(UI);
1009 destroyed_ = true;
1010 ClearImageCache();
1011 platformResRegister_.Reset();
1012 drawDelegate_.reset();
1013 eventManager_->ClearResults();
1014 {
1015 std::unique_lock<std::shared_mutex> lock(imageMtx_);
1016 imageCache_.Reset();
1017 }
1018 {
1019 std::unique_lock<std::shared_mutex> lock(themeMtx_);
1020 themeManager_.Reset();
1021 }
1022 fontManager_.Reset();
1023 window_->Destroy();
1024 touchPluginPipelineContext_.clear();
1025 virtualKeyBoardCallback_.clear();
1026 etsCardTouchEventCallback_.clear();
1027 formLinkInfoMap_.clear();
1028 TAG_LOGI(AceLogTag::ACE_ANIMATION, "pipeline destroyed, has %{public}zu finish callbacks not executed",
1029 finishFunctions_.size());
1030 finishFunctions_.clear();
1031 animationOption_ = {};
1032 {
1033 // To avoid the race condition caused by the offscreen canvas get density from the pipeline in the worker
1034 // thread.
1035 std::lock_guard lock(densityChangeMutex_);
1036 densityChangedCallbacks_.clear();
1037 }
1038 }
1039
OnFormRecycle()1040 std::string PipelineBase::OnFormRecycle()
1041 {
1042 if (onFormRecycle_) {
1043 return onFormRecycle_();
1044 }
1045 LOGE("onFormRecycle_ is null.");
1046 return "";
1047 }
1048
OnFormRecover(const std::string & statusData)1049 void PipelineBase::OnFormRecover(const std::string& statusData)
1050 {
1051 if (onFormRecover_) {
1052 return onFormRecover_(statusData);
1053 }
1054 LOGE("onFormRecover_ is null.");
1055 }
1056
SetUiDvsyncSwitch(bool on)1057 void PipelineBase::SetUiDvsyncSwitch(bool on)
1058 {
1059 if (window_) {
1060 window_->SetUiDvsyncSwitch(on);
1061 }
1062 }
1063 } // namespace OHOS::Ace
1064