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