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