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