• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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/components_ng/render/adapter/component_snapshot.h"
17 
18 #include "transaction/rs_interfaces.h"
19 #include "base/log/ace_trace.h"
20 #include "bridge/common/utils/utils.h"
21 #include "core/components_ng/base/inspector.h"
22 #include "core/components_ng/pattern/image/image_pattern.h"
23 #include "core/components_ng/pattern/stack/stack_pattern.h"
24 #include "core/components_ng/render/adapter/rosen_render_context.h"
25 #include "core/pipeline_ng/pipeline_context.h"
26 
27 namespace OHOS::Ace::NG {
28 namespace {
29 
30 constexpr std::chrono::duration<int, std::milli> SNAPSHOT_TIMEOUT_DURATION(3000);
31 constexpr std::chrono::duration<int, std::milli> CREATE_SNAPSHOT_TIMEOUT_DURATION(80);
32 
33 class CustomizedCallback : public Rosen::SurfaceCaptureCallback {
34 public:
CustomizedCallback(ComponentSnapshot::JsCallback && jsCallback,WeakPtr<FrameNode> node)35     CustomizedCallback(ComponentSnapshot::JsCallback&& jsCallback, WeakPtr<FrameNode> node)
36         : callback_(std::move(jsCallback)), node_(std::move(node))
37     {}
38     ~CustomizedCallback() override = default;
OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelMap)39     void OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelMap) override
40     {
41         if (callback_ == nullptr) {
42             TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Internal error! The callback_ is null");
43             auto node = node_.Upgrade();
44             CHECK_NULL_VOID(node);
45             Inspector::RemoveOffscreenNode(node);
46             return;
47         }
48         if (!pixelMap) {
49             TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Internal error! The pixelmap returned by the system is null");
50             callback_(nullptr, ERROR_CODE_INTERNAL_ERROR, [node = node_]() {
51                 auto frameNode = node.Upgrade();
52                 CHECK_NULL_VOID(frameNode);
53                 Inspector::RemoveOffscreenNode(frameNode);
54             });
55         } else {
56             TAG_LOGI(AceLogTag::ACE_COMPONENT_SNAPSHOT,
57                 "ComponentSnapshot successful! pixelMap.width=%{public}d pixelMap.height=%{public}d",
58                 pixelMap->GetWidth(), pixelMap->GetHeight());
59             callback_(pixelMap, ERROR_CODE_NO_ERROR, [node = node_]() {
60                 auto frameNode = node.Upgrade();
61                 CHECK_NULL_VOID(frameNode);
62                 Inspector::RemoveOffscreenNode(frameNode);
63             });
64         }
65     }
66 
OnSurfaceCaptureHDR(std::shared_ptr<Media::PixelMap> pixelMap,std::shared_ptr<Media::PixelMap> hdrPixelMap)67     void OnSurfaceCaptureHDR(std::shared_ptr<Media::PixelMap> pixelMap,
68         std::shared_ptr<Media::PixelMap> hdrPixelMap) override {}
69 
70 private:
71     ComponentSnapshot::JsCallback callback_;
72     WeakPtr<FrameNode> node_;
73 };
74 
75 class NormalCaptureCallback : public Rosen::SurfaceCaptureCallback {
76 public:
NormalCaptureCallback(ComponentSnapshot::NormalCallback && callback)77     explicit NormalCaptureCallback(ComponentSnapshot::NormalCallback&& callback) : callback_(std::move(callback)) {}
78     ~NormalCaptureCallback() override = default;
OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelMap)79     void OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelMap) override
80     {
81         CHECK_NULL_VOID(callback_);
82         callback_(pixelMap);
83     }
84 
OnSurfaceCaptureHDR(std::shared_ptr<Media::PixelMap> pixelMap,std::shared_ptr<Media::PixelMap> hdrPixelMap)85     void OnSurfaceCaptureHDR(std::shared_ptr<Media::PixelMap> pixelMap,
86         std::shared_ptr<Media::PixelMap> hdrPixelMap) override {}
87 
88 private:
89     ComponentSnapshot::NormalCallback callback_;
90 };
91 
92 class SyncCustomizedCallback : public Rosen::SurfaceCaptureCallback {
93 public:
94     SyncCustomizedCallback() = default;
95     ~SyncCustomizedCallback() override = default;
OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelMap)96     void OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelMap) override
97     {
98         if (!pixelMap) {
99             TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "ComponentSnapshotSync Internal error! "
100                 "The pixelmap returned by the system is null");
101             pixelMap_ = nullptr;
102         } else {
103             TAG_LOGI(AceLogTag::ACE_COMPONENT_SNAPSHOT,
104                 "ComponentSnapshotSync successful! pixelMap.width=%{public}d pixelMap.height=%{public}d",
105                 pixelMap->GetWidth(), pixelMap->GetHeight());
106             pixelMap_ = pixelMap;
107         }
108         std::unique_lock<std::mutex> lock(mutex_);
109         cv_.notify_all();
110     }
111 
OnSurfaceCaptureHDR(std::shared_ptr<Media::PixelMap> pixelMap,std::shared_ptr<Media::PixelMap> hdrPixelMap)112     void OnSurfaceCaptureHDR(std::shared_ptr<Media::PixelMap> pixelMap,
113         std::shared_ptr<Media::PixelMap> hdrPixelMap) override {}
114 
GetPixelMap(std::chrono::duration<int,std::milli> timeout)115     std::pair<int32_t, std::shared_ptr<Media::PixelMap>> GetPixelMap(std::chrono::duration<int, std::milli> timeout)
116     {
117         std::pair<int32_t, std::shared_ptr<Media::PixelMap>> result(ERROR_CODE_INTERNAL_ERROR, nullptr);
118         std::unique_lock<std::mutex> lock(mutex_);
119         auto status = cv_.wait_for(lock, timeout);
120         if (status == std::cv_status::timeout) {
121             return { ERROR_CODE_COMPONENT_SNAPSHOT_TIMEOUT, nullptr };
122         }
123         if (pixelMap_) {
124             result = { ERROR_CODE_NO_ERROR, pixelMap_ };
125         }
126         return result;
127     }
128 
129 private:
130     mutable std::mutex mutex_;
131     std::condition_variable cv_;
132     std::shared_ptr<Media::PixelMap> pixelMap_;
133 };
134 } // namespace
135 
IsSnapshotRegionValid(LocalizedSnapshotRegion & snapshotRegion)136 bool IsSnapshotRegionValid(LocalizedSnapshotRegion& snapshotRegion)
137 {
138     if (snapshotRegion.start < 0 || snapshotRegion.end < 0 || snapshotRegion.top < 0 ||
139         snapshotRegion.bottom < 0) {
140         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Snapshot reigon is invalid.");
141         return false;
142     }
143     return true;
144 }
145 
IsSnapshotRegionInRange(LocalizedSnapshotRegion & snapshotRegion,float & nodeWidth,float & nodeHeight)146 bool IsSnapshotRegionInRange(LocalizedSnapshotRegion& snapshotRegion, float& nodeWidth, float& nodeHeight)
147 {
148     if (snapshotRegion.start > nodeWidth || snapshotRegion.end > nodeWidth || snapshotRegion.top > nodeHeight ||
149         snapshotRegion.bottom > nodeHeight) {
150         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Snapshot reigon out of range.");
151         return false;
152     }
153     return true;
154 }
155 
SetCaptureReigon(const RefPtr<FrameNode> & node,const SnapshotOptions & options,Rosen::Drawing::Rect & specifiedAreaRect)156 int32_t SetCaptureReigon(const RefPtr<FrameNode>& node, const SnapshotOptions& options,
157     Rosen::Drawing::Rect& specifiedAreaRect)
158 {
159     auto context = node->GetRenderContext();
160     if (!context) {
161         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Can't get the render context of target node.");
162         return ERROR_CODE_INTERNAL_ERROR;
163     }
164     RectF nodeRect = context->GetPaintRectWithoutTransform();
165     float nodeWidth = nodeRect.Width();
166     float nodeHeight = nodeRect.Height();
167 
168     LocalizedSnapshotRegion snapshotRegion = options.snapshotRegion;
169     if (!IsSnapshotRegionValid(snapshotRegion) || !IsSnapshotRegionInRange(snapshotRegion, nodeWidth, nodeHeight)) {
170         return ERROR_CODE_PARAM_INVALID;
171     }
172 
173     auto nodeLayoutProperty = node->GetLayoutProperty();
174     if (!nodeLayoutProperty) {
175         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Can't get the layout property of target node.");
176         return ERROR_CODE_INTERNAL_ERROR;
177     }
178 
179     TextDirection layoutDirection = nodeLayoutProperty->GetLayoutDirection();
180     if (layoutDirection == TextDirection::AUTO || layoutDirection == TextDirection::INHERIT) {
181         layoutDirection = AceApplicationInfo::GetInstance().IsRightToLeft() ? TextDirection::RTL : TextDirection::LTR;
182     }
183     bool isRegionMirror = options.regionMode == NG::SnapshotRegionMode::LOCALIZED &&
184         layoutDirection == TextDirection::RTL;
185 
186     specifiedAreaRect = Rosen::Drawing::Rect(
187         isRegionMirror ? nodeWidth - snapshotRegion.end : snapshotRegion.start,
188         snapshotRegion.top,
189         isRegionMirror ? nodeWidth - snapshotRegion.start : snapshotRegion.end,
190         snapshotRegion.bottom);
191     return ERROR_CODE_NO_ERROR;
192 }
193 
ProcessImageNode(const RefPtr<UINode> & node,std::string & imageIds)194 void ProcessImageNode(const RefPtr<UINode>& node, std::string& imageIds)
195 {
196     if (node->GetTag() == V2::IMAGE_ETS_TAG) {
197         auto imageNode = AceType::DynamicCast<FrameNode>(node);
198         if (imageNode && AceType::DynamicCast<ImagePattern>(imageNode->GetPattern())) {
199             imageIds += (std::to_string(imageNode->GetId()) + ", " + imageNode->GetInspectorId().value_or("") + ";");
200             auto imagePattern = AceType::DynamicCast<ImagePattern>(imageNode->GetPattern());
201             imagePattern->SetIsComponentSnapshotNode(true);
202             imagePattern->OnVisibleAreaChange(true);
203         }
204     }
205     auto children = node->GetChildren();
206     for (const auto& child : children) {
207         ProcessImageNode(child, imageIds);
208     }
209 }
210 
CheckImageSuccessfullyLoad(const RefPtr<UINode> & node,int32_t & imageCount)211 bool CheckImageSuccessfullyLoad(const RefPtr<UINode>& node, int32_t& imageCount)
212 {
213     CHECK_NULL_RETURN(node, false);
214     auto frameNode = AceType::DynamicCast<FrameNode>(node);
215     if (frameNode && !frameNode->IsVisible()) {
216         return true;
217     }
218     if (node->GetTag() == V2::IMAGE_ETS_TAG) {
219         imageCount++;
220         auto imageNode = AceType::DynamicCast<FrameNode>(node);
221         CHECK_NULL_RETURN(imageNode, false);
222         auto imagePattern = AceType::DynamicCast<ImagePattern>(imageNode->GetPattern());
223         CHECK_NULL_RETURN(imagePattern, false);
224         auto imageLoadContext = imagePattern->GetImageLoadingContext().Upgrade();
225         CHECK_NULL_RETURN(imageLoadContext, false);
226         auto imageStateManger = imageLoadContext->GetStateManger();
227         CHECK_NULL_RETURN(imageStateManger, false);
228 
229         auto result = imageStateManger->GetCurrentState() == ImageLoadingState::LOAD_SUCCESS;
230         if (!result) {
231             TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
232                 "Image loading failed! ImageId=%{public}d ImageState=%{public}d",
233                 imageNode->GetId(), static_cast<int32_t>(imageStateManger->GetCurrentState()));
234         }
235         return result;
236     }
237 
238     auto children = node->GetChildren();
239     for (const auto& child : children) {
240         if (!CheckImageSuccessfullyLoad(child, imageCount)) {
241             return false;
242         }
243     }
244     return true;
245 }
246 
GetTaskExecutor(const RefPtr<AceType> & customNode,RefPtr<PipelineContext> & pipeline,RefPtr<TaskExecutor> & executor)247 bool GetTaskExecutor(const RefPtr<AceType>& customNode, RefPtr<PipelineContext>& pipeline,
248     RefPtr<TaskExecutor>& executor)
249 {
250     auto uiNode = AceType::DynamicCast<UINode>(customNode);
251     if (!uiNode) {
252         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Internal error! uiNode is nullptr, "
253         "because customNode is type of %{public}s", AceType::TypeName(customNode));
254         return false;
255     }
256     pipeline = uiNode->GetContextRefPtr();
257     if (!pipeline) {
258         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Internal error! can't get pipeline");
259         return false;
260     }
261     executor = pipeline->GetTaskExecutor();
262     if (!executor) {
263         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Internal error! can't get executor");
264         return false;
265     }
266 
267     return true;
268 }
269 
HandleCreateSyncNode(const RefPtr<FrameNode> & node,const RefPtr<PipelineContext> & pipeline,std::string & imageIds)270 void HandleCreateSyncNode(const RefPtr<FrameNode>& node, const RefPtr<PipelineContext>& pipeline, std::string& imageIds)
271 {
272     FrameNode::ProcessOffscreenNode(node);
273     ProcessImageNode(node, imageIds);
274     pipeline->FlushUITasks();
275     pipeline->FlushModifier();
276     pipeline->FlushMessages();
277 }
278 
GetRsNode(const RefPtr<FrameNode> & node)279 std::shared_ptr<Rosen::RSNode> ComponentSnapshot::GetRsNode(const RefPtr<FrameNode>& node)
280 {
281     CHECK_NULL_RETURN(node, nullptr);
282     auto context = AceType::DynamicCast<RosenRenderContext>(node->GetRenderContext());
283     CHECK_NULL_RETURN(context, nullptr);
284     context->AddRsNodeForCapture();
285     return context->GetRSNode();
286 }
287 
TakeCaptureWithCallback(const RefPtr<FrameNode> & node,std::shared_ptr<Rosen::RSNode> rsNode,const SnapshotOptions & options,ComponentSnapshot::JsCallback & callback)288 void TakeCaptureWithCallback(const RefPtr<FrameNode>& node, std::shared_ptr<Rosen::RSNode> rsNode,
289     const SnapshotOptions& options, ComponentSnapshot::JsCallback& callback)
290 {
291     auto& rsInterface = Rosen::RSInterfaces::GetInstance();
292     if (options.regionMode == NG::SnapshotRegionMode::NO_REGION) {
293         rsInterface.TakeSurfaceCaptureForUI(rsNode, std::make_shared<CustomizedCallback>(std::move(callback), nullptr),
294             options.scale, options.scale, options.waitUntilRenderFinished);
295         return;
296     }
297     Rosen::Drawing::Rect specifiedAreaRect = {};
298     int32_t setRegionReslut = SetCaptureReigon(node, options, specifiedAreaRect);
299     if (setRegionReslut != ERROR_CODE_NO_ERROR) {
300         callback(nullptr, setRegionReslut, nullptr);
301         return;
302     }
303     rsInterface.TakeSurfaceCaptureForUI(rsNode, std::make_shared<CustomizedCallback>(std::move(callback), nullptr),
304         options.scale, options.scale, options.waitUntilRenderFinished, specifiedAreaRect);
305 }
306 
Get(const std::string & componentId,JsCallback && callback,const SnapshotOptions & options)307 void ComponentSnapshot::Get(const std::string& componentId, JsCallback&& callback, const SnapshotOptions& options)
308 {
309     auto node = Inspector::GetFrameNodeByKey(componentId);
310     if (!node) {
311         callback(nullptr, ERROR_CODE_INTERNAL_ERROR, nullptr);
312         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
313             "Can't find a component that id or key are " SEC_PLD(%{public}s)
314             ", Please check your parameters are correct",
315             SEC_PARAM(componentId.c_str()));
316         return;
317     }
318 
319     auto rsNode = GetRsNode(node);
320 
321     if (node->GetIsLayoutNode()) {
322         std::list<RefPtr<FrameNode>> children;
323         node->GetOneDepthVisibleFrame(children);
324         if (children.empty()) {
325             callback(nullptr, ERROR_CODE_INTERNAL_ERROR, nullptr);
326             TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
327                 "Children is empty from FrameNode(Id=" SEC_PLD(%{public}d) ",Depth=%{public}d,Tag=%{public}s)",
328                 SEC_PARAM(node->GetId()), node->GetDepth(), node->GetTag().c_str());
329             return;
330         }
331         node = children.front();
332         rsNode = GetRsNode(children.front());
333     }
334 
335     if (!rsNode) {
336         callback(nullptr, ERROR_CODE_INTERNAL_ERROR, nullptr);
337         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
338             "RsNode is null from FrameNode(Id=" SEC_PLD(%{public}d) ",Depth=%{public}d,Tag=%{public}s)",
339             SEC_PARAM(node->GetId()), node->GetDepth(), node->GetTag().c_str());
340         return;
341     }
342     ACE_SCOPED_TRACE("ComponentSnapshot::Get_key=%s_Id=%d_RsId=%s", componentId.c_str(), node->GetId(),
343         std::to_string(rsNode->GetId()).c_str());
344     int32_t imageCount = 0;
345     bool checkImage = CheckImageSuccessfullyLoad(node, imageCount);
346     TAG_LOGI(AceLogTag::ACE_COMPONENT_SNAPSHOT,
347         "Get ComponentSnapshot options=%{public}s Id=" SEC_PLD(%{public}d) " Depth=%{public}d Tag=%{public}s "
348         "imageCount=%{public}d checkImage=%{public}d RsNodeId=%{public}" PRIu64 "",
349         options.ToString().c_str(), SEC_PARAM(node->GetId()), node->GetDepth(), node->GetTag().c_str(),
350         imageCount, checkImage, rsNode->GetId());
351     TakeCaptureWithCallback(node, rsNode, options, callback);
352 }
353 
GetByUniqueId(int32_t uniqueId,JsCallback && callback,const SnapshotOptions & options)354 void ComponentSnapshot::GetByUniqueId(int32_t uniqueId, JsCallback&& callback, const SnapshotOptions& options)
355 {
356     auto node = AceType::DynamicCast<FrameNode>(OHOS::Ace::ElementRegister::GetInstance()->GetNodeById(uniqueId));
357     if (!node) {
358         callback(nullptr, ERROR_CODE_INTERNAL_ERROR, nullptr);
359         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
360             "Can't find a component that uniqueId is %{public}d, Please check your parameters are correct",
361             uniqueId);
362         return;
363     }
364 
365     auto rsNode = GetRsNode(node);
366 
367     if (node->GetIsLayoutNode()) {
368         std::list<RefPtr<FrameNode>> children;
369         node->GetOneDepthVisibleFrame(children);
370         if (children.empty()) {
371             callback(nullptr, ERROR_CODE_INTERNAL_ERROR, nullptr);
372             TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
373                 "Children is empty from FrameNode(Id=" SEC_PLD(%{public}d) ",Depth=%{public}d,Tag=%{public}s)",
374                 SEC_PARAM(node->GetId()), node->GetDepth(), node->GetTag().c_str());
375             return;
376         }
377         node = children.front();
378         rsNode = GetRsNode(children.front());
379     }
380 
381     if (!rsNode) {
382         callback(nullptr, ERROR_CODE_INTERNAL_ERROR, nullptr);
383         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
384             "RsNode is null from FrameNode(Id=" SEC_PLD(%{public}d) ",Depth=%{public}d,Tag=%{public}s)",
385             SEC_PARAM(node->GetId()), node->GetDepth(), node->GetTag().c_str());
386         return;
387     }
388     ACE_SCOPED_TRACE("ComponentSnapshot::GetByUniqueId_Id=%d_RsId=%" PRIu64 "", node->GetId(), rsNode->GetId());
389     int32_t imageCount = 0;
390     bool checkImage = CheckImageSuccessfullyLoad(node, imageCount);
391     TAG_LOGI(AceLogTag::ACE_COMPONENT_SNAPSHOT,
392         "GetByUniqueId ComponentSnapshot options=%{public}s Id=%{public}d Tag=%{public}s imageCount=%{public}d "
393         "checkImage=%{public}d RsNodeId=%{public}" PRIu64 "",
394         options.ToString().c_str(), node->GetId(), node->GetTag().c_str(), imageCount, checkImage, rsNode->GetId());
395     TakeCaptureWithCallback(node, rsNode, options, callback);
396 }
397 
Create(const RefPtr<AceType> & customNode,JsCallback && callback,bool enableInspector,const SnapshotParam & param,bool flag)398 void ComponentSnapshot::Create(
399     const RefPtr<AceType>& customNode, JsCallback&& callback, bool enableInspector, const SnapshotParam& param,
400     bool flag)
401 {
402     if (!customNode) {
403         callback(nullptr, ERROR_CODE_INTERNAL_ERROR, nullptr);
404         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Internal error! customNode is nullptr");
405         return;
406     }
407     auto* stack = ViewStackProcessor::GetInstance();
408     auto nodeId = stack->ClaimNodeId();
409     auto stackNode = FrameNode::CreateFrameNode(V2::STACK_ETS_TAG, nodeId, AceType::MakeRefPtr<StackPattern>());
410     RefPtr<PipelineContext> pipeline = nullptr;
411     RefPtr<TaskExecutor> executor = nullptr;
412     if (!GetTaskExecutor(customNode, pipeline, executor)) {
413         callback(nullptr, ERROR_CODE_INTERNAL_ERROR, nullptr);
414         return;
415     }
416     auto node = AceType::DynamicCast<FrameNode>(customNode);
417     if (!node) {
418         RefPtr<UINode> uiNode = AceType::DynamicCast<UINode>(customNode);
419         stackNode->AddChild(uiNode);
420         node = stackNode;
421     }
422     ACE_SCOPED_TRACE("ComponentSnapshot::Create_Tag=%s_Id=%d_Key=%s", node->GetTag().c_str(), node->GetId(),
423         node->GetInspectorId().value_or("").c_str());
424     FrameNode::ProcessOffscreenNode(node);
425     node->SetActive();
426     std::string imageIds = "";
427     ProcessImageNode(node, imageIds);
428     TAG_LOGI(AceLogTag::ACE_COMPONENT_SNAPSHOT,
429         "Process off screen Node finished, root size = %{public}s Id=%{public}d Tag=%{public}s "
430         "enableInspector=%{public}d imageIds=%{public}s",
431         node->GetGeometryNode()->GetFrameSize().ToString().c_str(), node->GetId(), node->GetTag().c_str(),
432         enableInspector, imageIds.c_str());
433 
434     if (enableInspector) {
435         Inspector::AddOffscreenNode(node);
436     }
437 
438     if (flag) {
439         executor->PostTask(
440             [node]() {
441                 TAG_LOGI(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Flush UI tasks with flag");
442                 auto pipeline = node->GetContext();
443                 CHECK_NULL_VOID(pipeline);
444                 pipeline->FlushUITasks();
445                 pipeline->FlushModifier();
446                 pipeline->FlushMessages();
447             },
448             TaskExecutor::TaskType::UI, "ArkUIComponentSnapshotFlushUITasks", PriorityType::VIP);
449     }
450     PostDelayedTaskOfBuiler(executor, std::move(callback), node, enableInspector, pipeline, param);
451 }
452 
GetNormalCapture(const RefPtr<FrameNode> & frameNode,NormalCallback && callback)453 void ComponentSnapshot::GetNormalCapture(const RefPtr<FrameNode>& frameNode, NormalCallback&& callback)
454 {
455     auto rsNode = GetRsNode(frameNode);
456     auto& rsInterface = Rosen::RSInterfaces::GetInstance();
457     rsInterface.TakeSurfaceCaptureForUI(rsNode, std::make_shared<NormalCaptureCallback>(std::move(callback)));
458 }
459 
PostDelayedTaskOfBuiler(const RefPtr<TaskExecutor> & executor,JsCallback && callback,const RefPtr<FrameNode> & node,bool enableInspector,const RefPtr<PipelineContext> & pipeline,const SnapshotParam & param)460 void ComponentSnapshot::PostDelayedTaskOfBuiler(const RefPtr<TaskExecutor>& executor, JsCallback&& callback,
461     const RefPtr<FrameNode>& node, bool enableInspector, const RefPtr<PipelineContext>& pipeline,
462     const SnapshotParam& param)
463 {
464     auto instanceId = pipeline->GetInstanceId();
465     executor->PostDelayedTask(
466         [callback, node, enableInspector, pipeline, param, instanceId]() mutable {
467             ContainerScope scope(instanceId);
468             BuilerTask(std::move(callback), node, enableInspector, pipeline, param);
469         },
470         TaskExecutor::TaskType::UI, param.delay, "ArkUIComponentSnapshotCreateCapture", PriorityType::VIP);
471 }
472 
BuilerTask(JsCallback && callback,const RefPtr<FrameNode> & node,bool enableInspector,const RefPtr<PipelineContext> & pipeline,const SnapshotParam & param)473 void ComponentSnapshot::BuilerTask(JsCallback&& callback, const RefPtr<FrameNode>& node, bool enableInspector,
474     const RefPtr<PipelineContext>& pipeline, const SnapshotParam& param)
475 {
476     int32_t imageCount = 0;
477     auto checkResult = CheckImageSuccessfullyLoad(node, imageCount);
478     if (param.checkImageStatus && !checkResult) {
479         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
480             "Image loading failed! rootId=%{public}d rootNode=%{public}s",
481             node->GetId(), node->GetTag().c_str());
482         Inspector::RemoveOffscreenNode(node);
483         callback(nullptr, ERROR_CODE_COMPONENT_SNAPSHOT_IMAGE_LOAD_ERROR, nullptr);
484         return;
485     }
486     if (param.options.waitUntilRenderFinished) {
487         TAG_LOGI(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Flush UI tasks with waitUntilRenderFinished");
488         pipeline->FlushUITasks();
489         pipeline->FlushModifier();
490         pipeline->FlushMessages();
491     }
492     auto rsNode = GetRsNode(node);
493     auto& rsInterface = Rosen::RSInterfaces::GetInstance();
494     TAG_LOGI(AceLogTag::ACE_COMPONENT_SNAPSHOT,
495         "Begin to take surfaceCapture for ui, rootId=" SEC_PLD(%{public}d) " depth=%{public}d param=%{public}s "
496         "imageCount=%{public}d size=%{public}s, regionMode=%{public}d",
497         SEC_PARAM(node->GetId()), node->GetDepth(), param.ToString().c_str(), imageCount,
498         node->GetGeometryNode()->GetFrameSize().ToString().c_str(), param.options.regionMode);
499     if (param.options.regionMode == NG::SnapshotRegionMode::NO_REGION) {
500         rsInterface.TakeSurfaceCaptureForUI(
501             rsNode,
502             std::make_shared<CustomizedCallback>(std::move(callback), enableInspector ? node : nullptr),
503             param.options.scale, param.options.scale, param.options.waitUntilRenderFinished);
504         return;
505     }
506     Rosen::Drawing::Rect specifiedAreaRect = {};
507     int32_t setRegionReslut = SetCaptureReigon(node, param.options, specifiedAreaRect);
508     if (setRegionReslut != ERROR_CODE_NO_ERROR) {
509         callback(nullptr, setRegionReslut, nullptr);
510         return;
511     }
512     rsInterface.TakeSurfaceCaptureForUI(
513         rsNode,
514         std::make_shared<CustomizedCallback>(std::move(callback), enableInspector ? node : nullptr),
515         param.options.scale, param.options.scale, param.options.waitUntilRenderFinished, specifiedAreaRect);
516 }
517 
GetSync(RefPtr<FrameNode> & node,const SnapshotOptions & options)518 std::pair<int32_t, std::shared_ptr<Media::PixelMap>> ComponentSnapshot::GetSync(
519     RefPtr<FrameNode>& node, const SnapshotOptions& options)
520 {
521     CHECK_RUN_ON(UI);
522     ACE_SCOPED_TRACE("ComponentSnapshot::GetSyncStart_%s", node->GetInspectorIdValue("").c_str());
523     std::pair<int32_t, std::shared_ptr<Media::PixelMap>> result(ERROR_CODE_INTERNAL_ERROR, nullptr);
524     CHECK_NULL_RETURN(node, result);
525     auto rsNode = GetRsNode(node);
526 
527     if (node->GetIsLayoutNode()) {
528         std::list<RefPtr<FrameNode>> children;
529         node->GetOneDepthVisibleFrame(children);
530         if (children.empty()) {
531             TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
532                 "Children is empty from FrameNode(Id=" SEC_PLD(%{public}d) ",Depth=%{public}d,Tag=%{public}s)",
533                 SEC_PARAM(node->GetId()), node->GetDepth(), node->GetTag().c_str());
534             return result;
535         }
536         node = children.front();
537         rsNode = GetRsNode(children.front());
538     }
539 
540     if (!rsNode) {
541         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
542             "RsNode is null from FrameNode(Id=" SEC_PLD(%{public}d) ",Depth=%{public}d,Tag=%{public}s)",
543             SEC_PARAM(node->GetId()), node->GetDepth(), node->GetTag().c_str());
544         return result;
545     }
546     TAG_LOGI(AceLogTag::ACE_COMPONENT_SNAPSHOT,
547         "GetSync ComponentSnapshot options=%{public}s Id=" SEC_PLD(%{public}d) " Depth=%{public}d Tag=%{public}s "
548         "RsNodeId=%{public}" PRIu64 "",
549         options.ToString().c_str(), SEC_PARAM(node->GetId()), node->GetDepth(), node->GetTag().c_str(),
550         rsNode->GetId());
551     auto& rsInterface = Rosen::RSInterfaces::GetInstance();
552     auto syncCallback = std::make_shared<SyncCustomizedCallback>();
553     {
554         ACE_SCOPED_TRACE("ComponentSnapshot::GetSync_TakeSurfaceCaptureForUI_%s_%d_%" PRIu64 "",
555             node->GetInspectorIdValue("").c_str(), node->GetId(), rsNode->GetId());
556     }
557     if (options.regionMode == NG::SnapshotRegionMode::NO_REGION) {
558         rsInterface.TakeSurfaceCaptureForUI(rsNode, syncCallback,
559             options.scale, options.scale, options.waitUntilRenderFinished);
560         return syncCallback->GetPixelMap(SNAPSHOT_TIMEOUT_DURATION);
561     }
562     Rosen::Drawing::Rect specifiedAreaRect = {};
563     int32_t setRegionReslut = SetCaptureReigon(node, options, specifiedAreaRect);
564     if (setRegionReslut != ERROR_CODE_NO_ERROR) {
565         return {setRegionReslut, nullptr};
566     }
567     rsInterface.TakeSurfaceCaptureForUI(rsNode, syncCallback,
568         options.scale, options.scale, options.waitUntilRenderFinished, specifiedAreaRect);
569     return syncCallback->GetPixelMap(SNAPSHOT_TIMEOUT_DURATION);
570 }
571 
GetSync(const std::string & componentId,const SnapshotOptions & options)572 std::pair<int32_t, std::shared_ptr<Media::PixelMap>> ComponentSnapshot::GetSync(const std::string& componentId,
573     const SnapshotOptions& options)
574 {
575     CHECK_RUN_ON(UI);
576     std::pair<int32_t, std::shared_ptr<Media::PixelMap>> result(ERROR_CODE_INTERNAL_ERROR, nullptr);
577     auto node = Inspector::GetFrameNodeByKey(componentId);
578     if (!node) {
579         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
580             "Can't find a component that id or key are " SEC_PLD(%{public}s)
581             ", Please check your parameters are correct",
582             SEC_PARAM(componentId.c_str()));
583         return result;
584     }
585 
586     return GetSync(node, options);
587 }
588 
TakeCaptureBySync(const RefPtr<FrameNode> & node,std::shared_ptr<Rosen::RSNode> rsNode,const SnapshotOptions & options)589 std::pair<int32_t, std::shared_ptr<Media::PixelMap>> TakeCaptureBySync(const RefPtr<FrameNode>& node,
590     std::shared_ptr<Rosen::RSNode> rsNode, const SnapshotOptions& options)
591 {
592     auto& rsInterface = Rosen::RSInterfaces::GetInstance();
593     auto syncCallback = std::make_shared<SyncCustomizedCallback>();
594     {
595         ACE_SCOPED_TRACE("ComponentSnapshot::GetSyncByUniqueId_TakeSurfaceCaptureForUI_%d_%" PRIu64 "",
596             node->GetId(), rsNode->GetId());
597     }
598     if (options.regionMode == NG::SnapshotRegionMode::NO_REGION) {
599         rsInterface.TakeSurfaceCaptureForUI(rsNode, syncCallback,
600             options.scale, options.scale, options.waitUntilRenderFinished);
601         return syncCallback->GetPixelMap(SNAPSHOT_TIMEOUT_DURATION);
602     }
603     Rosen::Drawing::Rect specifiedAreaRect = {};
604     int32_t setRegionReslut = SetCaptureReigon(node, options, specifiedAreaRect);
605     if (setRegionReslut != ERROR_CODE_NO_ERROR) {
606         return {setRegionReslut, nullptr};
607     }
608     rsInterface.TakeSurfaceCaptureForUI(rsNode, syncCallback,
609         options.scale, options.scale, options.waitUntilRenderFinished, specifiedAreaRect);
610     return syncCallback->GetPixelMap(SNAPSHOT_TIMEOUT_DURATION);
611 }
612 
GetSyncByUniqueId(int32_t uniqueId,const SnapshotOptions & options)613 std::pair<int32_t, std::shared_ptr<Media::PixelMap>> ComponentSnapshot::GetSyncByUniqueId(int32_t uniqueId,
614     const SnapshotOptions& options)
615 {
616     CHECK_RUN_ON(UI);
617     ACE_SCOPED_TRACE("ComponentSnapshot::GetSyncByUniqueId_%d", uniqueId);
618     std::pair<int32_t, std::shared_ptr<Media::PixelMap>> result(ERROR_CODE_INTERNAL_ERROR, nullptr);
619     auto node = AceType::DynamicCast<FrameNode>(OHOS::Ace::ElementRegister::GetInstance()->GetNodeById(uniqueId));
620     if (!node) {
621         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
622             "Can't find a component that uniqueId is %{public}d, Please check your parameters are correct", uniqueId);
623         return result;
624     }
625 
626     auto rsNode = GetRsNode(node);
627 
628     if (node->GetIsLayoutNode()) {
629         std::list<RefPtr<FrameNode>> children;
630         node->GetOneDepthVisibleFrame(children);
631         if (children.empty()) {
632             TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
633                 "Children is empty from FrameNode(Id=" SEC_PLD(%{public}d) ",Depth=%{public}d,Tag=%{public}s)",
634                 SEC_PARAM(node->GetId()), node->GetDepth(), node->GetTag().c_str());
635             return result;
636         }
637         node = children.front();
638         rsNode = GetRsNode(children.front());
639     }
640 
641     if (!rsNode) {
642         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
643             "RsNode is null from FrameNode(Id=" SEC_PLD(%{public}d) ",Depth=%{public}d,Tag=%{public}s)",
644             SEC_PARAM(node->GetId()), node->GetDepth(), node->GetTag().c_str());
645         return result;
646     }
647     TAG_LOGI(AceLogTag::ACE_COMPONENT_SNAPSHOT,
648         "GetSyncByUniqueId ComponentSnapshot options=%{public}s Id=" SEC_PLD(%{public}d)
649         " Depth=%{public}d Tag=%{public}s RsNodeId=%{public}" PRIu64 "",
650         options.ToString().c_str(), SEC_PARAM(node->GetId()), node->GetDepth(), node->GetTag().c_str(),
651         rsNode->GetId());
652     std::pair<int32_t, std::shared_ptr<Media::PixelMap>> captureResult = TakeCaptureBySync(node, rsNode, options);
653     return captureResult;
654 }
655 
SetRSUIContext(const RefPtr<FrameNode> & frameNode,const std::shared_ptr<Rosen::RSUIContext> & rsUIContext)656 void ComponentSnapshot::SetRSUIContext(
657     const RefPtr<FrameNode>& frameNode, const std::shared_ptr<Rosen::RSUIContext>& rsUIContext)
658 {
659     CHECK_NULL_VOID(frameNode);
660     if (frameNode->GetAttachedContext()) {
661         return;
662     }
663     auto children = frameNode->GetChildren();
664     for (const auto& child : children) {
665         CHECK_NULL_VOID(child);
666         auto childFrameNode = AceType::DynamicCast<FrameNode>(child);
667         CHECK_NULL_VOID(childFrameNode);
668         auto context = AceType::DynamicCast<RosenRenderContext>(childFrameNode->GetRenderContext());
669         CHECK_NULL_VOID(context);
670         auto rsNode = context->GetRSNode();
671         CHECK_NULL_VOID(rsNode);
672         rsNode->SetRSUIContext(rsUIContext);
673         SetRSUIContext(childFrameNode, rsUIContext);
674     }
675 }
676 
GetRSUIContext(const RefPtr<PipelineContext> & pipeline)677 std::shared_ptr<Rosen::RSUIContext> ComponentSnapshot::GetRSUIContext(const RefPtr<PipelineContext>& pipeline)
678 {
679     CHECK_NULL_RETURN(pipeline, nullptr);
680     auto window = pipeline->GetWindow();
681     CHECK_NULL_RETURN(window, nullptr);
682     auto rsUIDirector = window->GetRSUIDirector();
683     CHECK_NULL_RETURN(rsUIDirector, nullptr);
684     auto rsUIContext = rsUIDirector->GetRSUIContext();
685     return rsUIContext;
686 }
687 
688 // Note: do not use this method, it's only called in drag procedure process.
CreateSync(const RefPtr<AceType> & customNode,const SnapshotParam & param)689 std::shared_ptr<Media::PixelMap> ComponentSnapshot::CreateSync(
690     const RefPtr<AceType>& customNode, const SnapshotParam& param)
691 {
692     if (!customNode) {
693         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "CreateSync Internal error! customNode is nullptr");
694         return nullptr;
695     }
696     auto* stack = ViewStackProcessor::GetInstance();
697     auto nodeId = stack->ClaimNodeId();
698     auto stackNode = FrameNode::CreateFrameNode(V2::STACK_ETS_TAG, nodeId, AceType::MakeRefPtr<StackPattern>());
699     RefPtr<PipelineContext> pipeline = nullptr;
700     RefPtr<TaskExecutor> executor = nullptr;
701     if (!GetTaskExecutor(customNode, pipeline, executor)) {
702         return nullptr;
703     }
704     auto node = AceType::DynamicCast<FrameNode>(customNode);
705     if (!node) {
706         RefPtr<UINode> uiNode = AceType::DynamicCast<UINode>(customNode);
707         stackNode->AddChild(uiNode);
708         node = stackNode;
709     }
710     auto rsUIContext = GetRSUIContext(pipeline);
711     SetRSUIContext(node, rsUIContext);
712     ACE_SCOPED_TRACE("ComponentSnapshot::CreateSync_Tag=%s_Id=%d_Key=%s", node->GetTag().c_str(), node->GetId(),
713         node->GetInspectorId().value_or("").c_str());
714     std::string imageIds = "";
715     HandleCreateSyncNode(node, pipeline, imageIds);
716     int32_t imageCount = 0;
717     bool checkImage = CheckImageSuccessfullyLoad(node, imageCount);
718     if (!checkImage) {
719         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
720             "Image loading failed! rootId=" SEC_PLD(%{public}d) " depth=%{public}d rootNode=%{public}s",
721             SEC_PARAM(node->GetId()), node->GetDepth(), node->GetTag().c_str());
722         return nullptr;
723     }
724     auto rsNode = GetRsNode(node);
725     if (!rsNode) {
726         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
727             "Can't get RsNode! rootId=" SEC_PLD(%{public}d) " depth=%{public}d rootNode=%{public}s",
728             SEC_PARAM(node->GetId()), node->GetDepth(), node->GetTag().c_str());
729         return nullptr;
730     }
731     auto& rsInterface = Rosen::RSInterfaces::GetInstance();
732     auto syncCallback = std::make_shared<SyncCustomizedCallback>();
733     rsInterface.TakeSurfaceCaptureForUI(rsNode, syncCallback, 1.f, 1.f, true);
734     auto pair = syncCallback->GetPixelMap(CREATE_SNAPSHOT_TIMEOUT_DURATION);
735     TAG_LOGI(AceLogTag::ACE_COMPONENT_SNAPSHOT,
736         "CreateSync, root size=%{public}s Id=" SEC_PLD(%{public}d) " depth=%{public}d Tag=%{public}s code:%{public}d "
737         "imageIds=%{public}s",
738         node->GetGeometryNode()->GetFrameSize().ToString().c_str(), SEC_PARAM(node->GetId()), node->GetDepth(),
739         node->GetTag().c_str(), pair.first, imageIds.c_str());
740     return pair.second;
741 }
742 
GetRangeIDNode(const NodeIdentity & ID)743 RefPtr<FrameNode> ComponentSnapshot::GetRangeIDNode(const NodeIdentity& ID)
744 {
745     if (!ID.first.empty()) {
746         return Inspector::GetFrameNodeByKey(ID.first);
747     }
748 
749     auto node = OHOS::Ace::ElementRegister::GetInstance()->GetNodeById(ID.second);
750     if (!node) {
751         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Node with id %{public}d not found", ID.second);
752         return nullptr;
753     }
754 
755     auto frameNode = AceType::DynamicCast<FrameNode>(node);
756     if (!frameNode) {
757         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
758             "Node with id %{public}d is not a FrameNode (actual type: %{public}s)",
759             ID.second, AceType::TypeName(node));
760         return nullptr;
761     }
762 
763     return frameNode;
764 }
765 
GetRangeIDStr(const NodeIdentity & ID)766 std::string ComponentSnapshot::GetRangeIDStr(const NodeIdentity& ID)
767 {
768     return ID.first.empty() ? std::to_string(ID.second) : ID.first;
769 }
770 
GetWithRange(const NodeIdentity & startID,const NodeIdentity & endID,const bool & isStartRect,JsCallback && callback,const SnapshotOptions & options)771 void ComponentSnapshot::GetWithRange(const NodeIdentity& startID, const NodeIdentity& endID, const bool& isStartRect,
772     JsCallback&& callback, const SnapshotOptions& options)
773 {
774     CHECK_RUN_ON(UI);
775     auto startNode = GetRangeIDNode(startID);
776     auto endNode = GetRangeIDNode(endID);
777     if (!startNode) {
778         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
779             "Node not found that startld is " SEC_PLD(%{public}s),
780             SEC_PARAM(GetRangeIDStr(startID).c_str()));
781         callback(nullptr, ERROR_CODE_INTERNAL_ERROR, nullptr);
782         return;
783     }
784     if (!endNode) {
785         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
786             "Node not found that endld is " SEC_PLD(%{public}s),
787             SEC_PARAM(GetRangeIDStr(endID).c_str()));
788         callback(nullptr, ERROR_CODE_INTERNAL_ERROR, nullptr);
789         return;
790     }
791     auto rsStartNode = GetRsNode(startNode);
792     auto rsEndNode = GetRsNode(endNode);
793     if (!rsStartNode || !rsEndNode) {
794         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
795             "Can't find a component that startId or endId are " SEC_PLD(%{public}s) " and " SEC_PLD(%{public}s)
796             ", please check your parameters are correct",
797             SEC_PARAM(GetRangeIDStr(startID).c_str()), SEC_PARAM(GetRangeIDStr(endID).c_str()));
798         callback(nullptr, ERROR_CODE_INTERNAL_ERROR, nullptr);
799         return;
800     }
801     ACE_SCOPED_TRACE("ComponentSnapshot::GetWithRange_startKey=%s_startId=%d_startRsId=%s_"
802         "endKey=%s_endId=%d_endRsId=%s", GetRangeIDStr(startID).c_str(), startNode->GetId(),
803         std::to_string(rsStartNode->GetId()).c_str(), GetRangeIDStr(endID).c_str(), endNode->GetId(),
804         std::to_string(rsEndNode->GetId()).c_str());
805 
806     auto& rsInterface = Rosen::RSInterfaces::GetInstance();
807     auto isSystem = rsInterface.TakeUICaptureInRange(rsStartNode, rsEndNode, isStartRect,
808         std::make_shared<CustomizedCallback>(std::move(callback), nullptr),
809         options.scale, options.scale, options.waitUntilRenderFinished);
810     if (!isSystem) {
811         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
812             "No system permissions to take screenshot");
813         callback(nullptr, ERROR_CODE_PERMISSION_DENIED, nullptr);
814     }
815 }
816 
GetSoloNode(const RefPtr<FrameNode> & node)817 std::vector<std::pair<uint64_t, std::shared_ptr<Media::PixelMap>>> ComponentSnapshot::GetSoloNode(
818     const RefPtr<FrameNode>& node)
819 {
820     if (!node) {
821         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "GetSoloNode Internal error! node is nullptr");
822         return {{ERROR_CODE_INTERNAL_ERROR, nullptr}};
823     }
824     auto rsNode = GetRsNode(node);
825     if (!rsNode) {
826         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
827             "Can't get RsNode! rootId=" SEC_PLD(%{public}d) " depth=%{public}d rootNode=%{public}s",
828             SEC_PARAM(node->GetId()), node->GetDepth(), node->GetTag().c_str());
829         return {{ERROR_CODE_INTERNAL_ERROR, nullptr}};
830     }
831     ACE_SCOPED_TRACE("ComponentSnapshot::GetSoloNode_Id=%d_RsId=%" PRIu64 "", node->GetId(), rsNode->GetId());
832     auto& rsInterface = Rosen::RSInterfaces::GetInstance();
833     TAG_LOGI(AceLogTag::ACE_COMPONENT_SNAPSHOT,
834         "Begin to get solo node snapshot, rootId=" SEC_PLD(%{public}d) " depth=%{public}d size=%{public}s",
835         SEC_PARAM(node->GetId()), node->GetDepth(), node->GetGeometryNode()->GetFrameSize().ToString().c_str());
836     return rsInterface.TakeSurfaceCaptureSoloNodeList(rsNode);
837 }
838 } // namespace OHOS::Ace::NG
839