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