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 
26 namespace OHOS::Ace::NG {
27 namespace {
28 
29 constexpr std::chrono::duration<int, std::milli> SNAPSHOT_TIMEOUT_DURATION(3000);
30 constexpr std::chrono::duration<int, std::milli> CREATE_SNAPSHOT_TIMEOUT_DURATION(80);
31 
32 class CustomizedCallback : public Rosen::SurfaceCaptureCallback {
33 public:
CustomizedCallback(ComponentSnapshot::JsCallback && jsCallback,WeakPtr<FrameNode> node)34     CustomizedCallback(ComponentSnapshot::JsCallback&& jsCallback, WeakPtr<FrameNode> node)
35         : callback_(std::move(jsCallback)), node_(std::move(node))
36     {}
37     ~CustomizedCallback() override = default;
OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelMap)38     void OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelMap) override
39     {
40         if (callback_ == nullptr) {
41             TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Internal error! The callback_ is null");
42             auto node = node_.Upgrade();
43             CHECK_NULL_VOID(node);
44             Inspector::RemoveOffscreenNode(node);
45             return;
46         }
47         if (!pixelMap) {
48             TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Internal error! The pixelmap returned by the system is null");
49             callback_(nullptr, ERROR_CODE_INTERNAL_ERROR, [node = node_]() {
50                 auto frameNode = node.Upgrade();
51                 CHECK_NULL_VOID(frameNode);
52                 Inspector::RemoveOffscreenNode(frameNode);
53             });
54         } else {
55             TAG_LOGI(AceLogTag::ACE_COMPONENT_SNAPSHOT,
56                 "ComponentSnapshot successful! pixelMap.width=%{public}d pixelMap.height=%{public}d",
57                 pixelMap->GetWidth(), pixelMap->GetHeight());
58             callback_(pixelMap, ERROR_CODE_NO_ERROR, [node = node_]() {
59                 auto frameNode = node.Upgrade();
60                 CHECK_NULL_VOID(frameNode);
61                 Inspector::RemoveOffscreenNode(frameNode);
62             });
63         }
64     }
65 
66 private:
67     ComponentSnapshot::JsCallback callback_;
68     WeakPtr<FrameNode> node_;
69 };
70 
71 class NormalCaptureCallback : public Rosen::SurfaceCaptureCallback {
72 public:
NormalCaptureCallback(ComponentSnapshot::NormalCallback && callback)73     explicit NormalCaptureCallback(ComponentSnapshot::NormalCallback&& callback) : callback_(std::move(callback)) {}
74     ~NormalCaptureCallback() override = default;
OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelMap)75     void OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelMap) override
76     {
77         CHECK_NULL_VOID(callback_);
78         callback_(pixelMap);
79     }
80 
81 private:
82     ComponentSnapshot::NormalCallback callback_;
83 };
84 
85 class SyncCustomizedCallback : public Rosen::SurfaceCaptureCallback {
86 public:
87     SyncCustomizedCallback() = default;
88     ~SyncCustomizedCallback() override = default;
OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelMap)89     void OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelMap) override
90     {
91         if (!pixelMap) {
92             TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Internal error! The pixelmap returned by the system is null");
93             pixelMap_ = nullptr;
94         } else {
95             TAG_LOGI(AceLogTag::ACE_COMPONENT_SNAPSHOT,
96                 "ComponentSnapshot successful! pixelMap.width=%{public}d pixelMap.height=%{public}d",
97                 pixelMap->GetWidth(), pixelMap->GetHeight());
98             pixelMap_ = pixelMap;
99         }
100         std::unique_lock<std::mutex> lock(mutex_);
101         cv_.notify_all();
102     }
103 
GetPixelMap(std::chrono::duration<int,std::milli> timeout)104     std::pair<int32_t, std::shared_ptr<Media::PixelMap>> GetPixelMap(std::chrono::duration<int, std::milli> timeout)
105     {
106         std::pair<int32_t, std::shared_ptr<Media::PixelMap>> result(ERROR_CODE_INTERNAL_ERROR, nullptr);
107         std::unique_lock<std::mutex> lock(mutex_);
108         auto status = cv_.wait_for(lock, timeout);
109         if (status == std::cv_status::timeout) {
110             return { ERROR_CODE_COMPONENT_SNAPSHOT_TIMEOUT, nullptr };
111         }
112         if (pixelMap_) {
113             result = { ERROR_CODE_NO_ERROR, pixelMap_ };
114         }
115         return result;
116     }
117 
118 private:
119     mutable std::mutex mutex_;
120     std::condition_variable cv_;
121     std::shared_ptr<Media::PixelMap> pixelMap_;
122 };
123 } // namespace
124 
ProcessImageNode(const RefPtr<UINode> & node)125 void ProcessImageNode(const RefPtr<UINode>& node)
126 {
127     if (node->GetTag() == V2::IMAGE_ETS_TAG) {
128         auto imageNode = AceType::DynamicCast<FrameNode>(node);
129         if (imageNode && AceType::DynamicCast<ImagePattern>(imageNode->GetPattern())) {
130             auto imagePattern = AceType::DynamicCast<ImagePattern>(imageNode->GetPattern());
131             imagePattern->SetIsComponentSnapshotNode();
132             imagePattern->OnVisibleAreaChange(true);
133         }
134     }
135     auto children = node->GetChildren();
136     for (const auto& child : children) {
137         ProcessImageNode(child);
138     }
139 }
140 
CheckImageSuccessfullyLoad(const RefPtr<UINode> & node,int32_t & imageCount)141 bool CheckImageSuccessfullyLoad(const RefPtr<UINode>& node, int32_t& imageCount)
142 {
143     CHECK_NULL_RETURN(node, false);
144     auto frameNode = AceType::DynamicCast<FrameNode>(node);
145     if (frameNode && !frameNode->IsVisible()) {
146         return true;
147     }
148     if (node->GetTag() == V2::IMAGE_ETS_TAG) {
149         imageCount++;
150         auto imageNode = AceType::DynamicCast<FrameNode>(node);
151         CHECK_NULL_RETURN(imageNode, false);
152         auto imagePattern = AceType::DynamicCast<ImagePattern>(imageNode->GetPattern());
153         CHECK_NULL_RETURN(imagePattern, false);
154         auto imageLoadContext = imagePattern->GetImageLoadingContext().Upgrade();
155         CHECK_NULL_RETURN(imageLoadContext, false);
156         auto imageStateManger = imageLoadContext->GetStateManger();
157         CHECK_NULL_RETURN(imageStateManger, false);
158 
159         auto result = imageStateManger->GetCurrentState() == ImageLoadingState::LOAD_SUCCESS;
160         if (!result) {
161             TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
162                 "Image loading failed! ImageId=%{public}d ImageState=%{public}d ImageKey=%{public}s",
163                 imageNode->GetId(), static_cast<int32_t>(imageStateManger->GetCurrentState()),
164                 imageNode->GetInspectorId().value_or("").c_str());
165         }
166         return result;
167     }
168 
169     auto children = node->GetChildren();
170     for (const auto& child : children) {
171         if (!CheckImageSuccessfullyLoad(child, imageCount)) {
172             return false;
173         }
174     }
175     return true;
176 }
177 
GetTaskExecutor(const RefPtr<AceType> & customNode,RefPtr<PipelineContext> & pipeline,RefPtr<TaskExecutor> & executor)178 bool GetTaskExecutor(const RefPtr<AceType>& customNode, RefPtr<PipelineContext>& pipeline,
179     RefPtr<TaskExecutor>& executor)
180 {
181     auto uiNode = AceType::DynamicCast<UINode>(customNode);
182     if (!uiNode) {
183         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Internal error! uiNode is nullptr, "
184         "because customNode is type of %{public}s", AceType::TypeName(customNode));
185         return false;
186     }
187     pipeline = uiNode->GetContextRefPtr();
188     if (!pipeline) {
189         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Internal error! can't get pipeline");
190         return false;
191     }
192     executor = pipeline->GetTaskExecutor();
193     if (!executor) {
194         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Internal error! can't get executor");
195         return false;
196     }
197 
198     return true;
199 }
200 
GetRsNode(const RefPtr<FrameNode> & node)201 std::shared_ptr<Rosen::RSNode> ComponentSnapshot::GetRsNode(const RefPtr<FrameNode>& node)
202 {
203     CHECK_NULL_RETURN(node, nullptr);
204     auto context = AceType::DynamicCast<RosenRenderContext>(node->GetRenderContext());
205     CHECK_NULL_RETURN(context, nullptr);
206     auto rsNode = context->GetRSNode();
207     return rsNode;
208 }
209 
Get(const std::string & componentId,JsCallback && callback,const SnapshotOptions & options)210 void ComponentSnapshot::Get(const std::string& componentId, JsCallback&& callback, const SnapshotOptions& options)
211 {
212     auto node = Inspector::GetFrameNodeByKey(componentId);
213     if (!node) {
214         callback(nullptr, ERROR_CODE_INTERNAL_ERROR, nullptr);
215         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
216             "Can't find a component that id or key are %{public}s, Please check your parameters are correct",
217             componentId.c_str());
218         return;
219     }
220 
221     auto rsNode = GetRsNode(node);
222 
223     if (node->GetIsLayoutNode()) {
224         std::list<RefPtr<FrameNode>> children;
225         node->GetOneDepthVisibleFrame(children);
226         if (children.empty()) {
227             callback(nullptr, ERROR_CODE_INTERNAL_ERROR, nullptr);
228             TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
229                 "Children is empty from FrameNode(InspectorId=%{public}s Id=%{public}d)",
230                 componentId.c_str(), node->GetId());
231             return;
232         }
233         node = children.front();
234         rsNode = GetRsNode(children.front());
235     }
236 
237     if (!rsNode) {
238         callback(nullptr, ERROR_CODE_INTERNAL_ERROR, nullptr);
239         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
240             "RsNode is null from FrameNode(InspectorId=%{public}s Id=%{public}d)",
241             componentId.c_str(), node->GetId());
242         return;
243     }
244     int32_t imageCount = 0;
245     bool checkImage = CheckImageSuccessfullyLoad(node, imageCount);
246     TAG_LOGI(AceLogTag::ACE_COMPONENT_SNAPSHOT,
247         "Get ComponentSnapshot key=%{public}s options=%{public}s Id=%{public}d Tag=%{public}s imageCount=%{public}d "
248         "checkImage=%{public}d RsNodeId=%{public}" PRIu64 "",
249         componentId.c_str(), options.ToString().c_str(), node->GetId(), node->GetTag().c_str(), imageCount, checkImage,
250         rsNode->GetId());
251     auto& rsInterface = Rosen::RSInterfaces::GetInstance();
252     rsInterface.TakeSurfaceCaptureForUI(rsNode, std::make_shared<CustomizedCallback>(std::move(callback), nullptr),
253         options.scale, options.scale, options.waitUntilRenderFinished);
254 }
255 
Create(const RefPtr<AceType> & customNode,JsCallback && callback,bool enableInspector,const SnapshotParam & param,bool flag)256 void ComponentSnapshot::Create(
257     const RefPtr<AceType>& customNode, JsCallback&& callback, bool enableInspector, const SnapshotParam& param,
258     bool flag)
259 {
260     if (!customNode) {
261         callback(nullptr, ERROR_CODE_INTERNAL_ERROR, nullptr);
262         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Internal error! customNode is nullptr");
263         return;
264     }
265     auto* stack = ViewStackProcessor::GetInstance();
266     auto nodeId = stack->ClaimNodeId();
267     auto stackNode = FrameNode::CreateFrameNode(V2::STACK_ETS_TAG, nodeId, AceType::MakeRefPtr<StackPattern>());
268     RefPtr<PipelineContext> pipeline = nullptr;
269     RefPtr<TaskExecutor> executor = nullptr;
270     if (!GetTaskExecutor(customNode, pipeline, executor)) {
271         callback(nullptr, ERROR_CODE_INTERNAL_ERROR, nullptr);
272         return;
273     }
274     auto node = AceType::DynamicCast<FrameNode>(customNode);
275     if (!node) {
276         RefPtr<UINode> uiNode = AceType::DynamicCast<UINode>(customNode);
277         stackNode->AddChild(uiNode);
278         node = stackNode;
279     }
280     FrameNode::ProcessOffscreenNode(node);
281     TAG_LOGI(AceLogTag::ACE_COMPONENT_SNAPSHOT,
282         "Process off screen Node finished, root size = %{public}s Id=%{public}d Tag=%{public}s InspectorId=%{public}s "
283         "enableInspector=%{public}d",
284         node->GetGeometryNode()->GetFrameSize().ToString().c_str(), node->GetId(), node->GetTag().c_str(),
285         node->GetInspectorId().value_or("").c_str(), enableInspector);
286 
287     ProcessImageNode(node);
288 
289     if (enableInspector) {
290         Inspector::AddOffscreenNode(node);
291     }
292 
293     if (flag) {
294         executor->PostTask(
295             [node]() {
296                 auto pipeline = node->GetContext();
297                 CHECK_NULL_VOID(pipeline);
298                 pipeline->FlushUITasks();
299                 pipeline->FlushMessages();
300             },
301             TaskExecutor::TaskType::UI, "ArkUIComponentSnapshotFlushUITasks", PriorityType::VIP);
302     }
303     PostDelayedTaskOfBuiler(executor, std::move(callback), node, enableInspector, pipeline, param);
304 }
305 
GetNormalCapture(const RefPtr<FrameNode> & frameNode,NormalCallback && callback)306 void ComponentSnapshot::GetNormalCapture(const RefPtr<FrameNode>& frameNode, NormalCallback&& callback)
307 {
308     auto rsNode = GetRsNode(frameNode);
309     auto& rsInterface = Rosen::RSInterfaces::GetInstance();
310     rsInterface.TakeSurfaceCaptureForUI(rsNode, std::make_shared<NormalCaptureCallback>(std::move(callback)));
311 }
312 
PostDelayedTaskOfBuiler(const RefPtr<TaskExecutor> & executor,JsCallback && callback,const RefPtr<FrameNode> & node,bool enableInspector,const RefPtr<PipelineContext> & pipeline,const SnapshotParam & param)313 void ComponentSnapshot::PostDelayedTaskOfBuiler(const RefPtr<TaskExecutor>& executor, JsCallback&& callback,
314     const RefPtr<FrameNode>& node, bool enableInspector, const RefPtr<PipelineContext>& pipeline,
315     const SnapshotParam& param)
316 {
317     executor->PostDelayedTask(
318         [callback, node, enableInspector, pipeline, param]() mutable {
319             BuilerTask(std::move(callback), node, enableInspector, pipeline, param);
320         },
321         TaskExecutor::TaskType::UI, param.delay, "ArkUIComponentSnapshotCreateCapture", PriorityType::VIP);
322 }
323 
BuilerTask(JsCallback && callback,const RefPtr<FrameNode> & node,bool enableInspector,const RefPtr<PipelineContext> & pipeline,const SnapshotParam & param)324 void ComponentSnapshot::BuilerTask(JsCallback&& callback, const RefPtr<FrameNode>& node, bool enableInspector,
325     const RefPtr<PipelineContext>& pipeline, const SnapshotParam& param)
326 {
327     int32_t imageCount = 0;
328     if (param.checkImageStatus && !CheckImageSuccessfullyLoad(node, imageCount)) {
329         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
330             "Image loading failed! rootId=%{public}d rootNode=%{public}s InspectorId=%{public}s",
331             node->GetId(), node->GetTag().c_str(), node->GetInspectorId().value_or("").c_str());
332         Inspector::RemoveOffscreenNode(node);
333         callback(nullptr, ERROR_CODE_COMPONENT_SNAPSHOT_IMAGE_LOAD_ERROR, nullptr);
334         return;
335     }
336     if (param.options.waitUntilRenderFinished) {
337         pipeline->FlushUITasks();
338         pipeline->FlushMessages();
339     }
340     auto rsNode = GetRsNode(node);
341     auto& rsInterface = Rosen::RSInterfaces::GetInstance();
342     TAG_LOGI(AceLogTag::ACE_COMPONENT_SNAPSHOT,
343         "Begin to take surfaceCapture for ui, rootId=%{public}d param=%{public}s imageCount=%{public}d",
344         node->GetId(), param.ToString().c_str(), imageCount);
345     rsInterface.TakeSurfaceCaptureForUI(
346         rsNode,
347         std::make_shared<CustomizedCallback>(std::move(callback), enableInspector ? node : nullptr),
348         param.options.scale, param.options.scale, param.options.waitUntilRenderFinished);
349 }
350 
GetSync(const std::string & componentId,const SnapshotOptions & options)351 std::pair<int32_t, std::shared_ptr<Media::PixelMap>> ComponentSnapshot::GetSync(const std::string& componentId,
352     const SnapshotOptions& options)
353 {
354     CHECK_RUN_ON(UI);
355     ACE_SCOPED_TRACE("ComponentSnapshot::GetSyncStart_%s", componentId.c_str());
356     std::pair<int32_t, std::shared_ptr<Media::PixelMap>> result(ERROR_CODE_INTERNAL_ERROR, nullptr);
357     auto node = Inspector::GetFrameNodeByKey(componentId);
358     if (!node) {
359         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
360             "Can't find a component that id or key are %{public}s, Please check your parameters are correct",
361             componentId.c_str());
362         return result;
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             TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
372                 "Children is empty from FrameNode(InspectorId=%{public}s Id=%{public}d)",
373                 componentId.c_str(), node->GetId());
374             return result;
375         }
376         node = children.front();
377         rsNode = GetRsNode(children.front());
378     }
379 
380     if (!rsNode) {
381         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
382             "RsNode is null from FrameNode(InspectorId=%{public}s Id=%{public}d)",
383             componentId.c_str(), node->GetId());
384         return result;
385     }
386     TAG_LOGI(AceLogTag::ACE_COMPONENT_SNAPSHOT,
387         "GetSync ComponentSnapshot key=%{public}s options=%{public}s Id=%{public}d Tag=%{public}s "
388         "RsNodeId=%{public}" PRIu64 "",
389         componentId.c_str(), options.ToString().c_str(), node->GetId(), node->GetTag().c_str(), rsNode->GetId());
390     auto& rsInterface = Rosen::RSInterfaces::GetInstance();
391     auto syncCallback = std::make_shared<SyncCustomizedCallback>();
392     {
393         ACE_SCOPED_TRACE("ComponentSnapshot::GetSync_TakeSurfaceCaptureForUI_%s_%d_%" PRIu64 "", componentId.c_str(),
394             node->GetId(), rsNode->GetId());
395     }
396     rsInterface.TakeSurfaceCaptureForUI(rsNode, syncCallback,
397         options.scale, options.scale, options.waitUntilRenderFinished);
398     return syncCallback->GetPixelMap(SNAPSHOT_TIMEOUT_DURATION);
399 }
400 
401 // Note: do not use this method, it's only called in drag procedure process.
CreateSync(const RefPtr<AceType> & customNode,const SnapshotParam & param)402 std::shared_ptr<Media::PixelMap> ComponentSnapshot::CreateSync(
403     const RefPtr<AceType>& customNode, const SnapshotParam& param)
404 {
405     if (!customNode) {
406         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "CreateSync Internal error! customNode is nullptr");
407         return nullptr;
408     }
409     auto* stack = ViewStackProcessor::GetInstance();
410     auto nodeId = stack->ClaimNodeId();
411     auto stackNode = FrameNode::CreateFrameNode(V2::STACK_ETS_TAG, nodeId, AceType::MakeRefPtr<StackPattern>());
412     RefPtr<PipelineContext> pipeline = nullptr;
413     RefPtr<TaskExecutor> executor = nullptr;
414     if (!GetTaskExecutor(customNode, pipeline, executor)) {
415         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Internal error! Can't get TaskExecutor!");
416         return nullptr;
417     }
418     auto node = AceType::DynamicCast<FrameNode>(customNode);
419     if (!node) {
420         RefPtr<UINode> uiNode = AceType::DynamicCast<UINode>(customNode);
421         stackNode->AddChild(uiNode);
422         node = stackNode;
423     }
424     FrameNode::ProcessOffscreenNode(node);
425     TAG_LOGI(AceLogTag::ACE_COMPONENT_SNAPSHOT,
426         "Process off screen Node finished, root size = %{public}s Id=%{public}d Tag=%{public}s InspectorId=%{public}s",
427         node->GetGeometryNode()->GetFrameSize().ToString().c_str(), node->GetId(), node->GetTag().c_str(),
428         node->GetInspectorId().value_or("").c_str());
429 
430     ProcessImageNode(node);
431     pipeline->FlushUITasks();
432     pipeline->FlushMessages();
433     int32_t imageCount = 0;
434     bool checkImage = CheckImageSuccessfullyLoad(node, imageCount);
435     if (!checkImage) {
436         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
437             "Image loading failed! rootId=%{public}d rootNode=%{public}s InspectorId=%{public}s",
438             node->GetId(), node->GetTag().c_str(), node->GetInspectorId().value_or("").c_str());
439         return nullptr;
440     }
441     auto rsNode = GetRsNode(node);
442     if (!rsNode) {
443         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
444             "Can't get RsNode! rootId=%{public}d rootNode=%{public}s InspectorId=%{public}s",
445             node->GetId(), node->GetTag().c_str(), node->GetInspectorId().value_or("").c_str());
446         return nullptr;
447     }
448     auto& rsInterface = Rosen::RSInterfaces::GetInstance();
449     auto syncCallback = std::make_shared<SyncCustomizedCallback>();
450     rsInterface.TakeSurfaceCaptureForUI(rsNode, syncCallback,
451         1.f, 1.f, true);
452     return syncCallback->GetPixelMap(CREATE_SNAPSHOT_TIMEOUT_DURATION).second;
453 }
454 } // namespace OHOS::Ace::NG
455