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