1 /*
2 * Copyright (c) 2024 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 "foundation/graphic/graphic_2d/utils/log/rs_trace.h"
17 #include "rs_profiler.h"
18 #include "rs_profiler_json.h"
19 #include "rs_profiler_network.h"
20
21 #include "common/rs_obj_geometry.h"
22 #include "pipeline/rs_context.h"
23 #include "pipeline/rs_display_render_node.h"
24 #include "pipeline/rs_root_render_node.h"
25 #include "pipeline/rs_surface_handler.h"
26 #include "pipeline/rs_surface_render_node.h"
27
28 namespace OHOS::Rosen {
29
DumpNode(const RSRenderNode & node,JsonWriter & out)30 void RSProfiler::DumpNode(const RSRenderNode& node, JsonWriter& out)
31 {
32 out.PushObject();
33 DumpNodeBaseInfo(node, out);
34 DumpNodeProperties(node.GetRenderProperties(), out);
35 DumpNodeOptionalFlags(node, out);
36 DumpNodeDrawCmdModifiers(node, out);
37 DumpNodeAnimations(node.animationManager_, out);
38 DumpNodeChildrenListUpdate(node, out);
39
40 auto& children = out["children"];
41 children.PushArray();
42 if (node.GetSortedChildren()) {
43 for (auto& child : *node.GetSortedChildren()) {
44 if (child) {
45 DumpNode(*child, children);
46 }
47 }
48 }
49 children.PopArray();
50 out.PopObject();
51 }
52
DumpNodeBaseInfo(const RSRenderNode & node,JsonWriter & out)53 void RSProfiler::DumpNodeBaseInfo(const RSRenderNode& node, JsonWriter& out)
54 {
55 std::string type;
56 node.DumpNodeType(node.GetType(), type);
57 out["type"] = type;
58 out["id"] = node.GetId();
59 out["instanceRootNodeId"] = node.GetInstanceRootNodeId();
60 DumpNodeSubsurfaces(node, out);
61 auto sharedTrans = node.GetSharedTransitionParam();
62 if (sharedTrans) {
63 out["SharedTransitionParam"] =
64 std::to_string(sharedTrans->inNodeId_) + " -> " + std::to_string(sharedTrans->outNodeId_);
65 }
66 if (node.IsSuggestedDrawInGroup()) {
67 out["nodeGroup"] = static_cast<int>(node.nodeGroupType_);
68 }
69 if (node.GetUifirstRootNodeId() != INVALID_NODEID) {
70 out["uifirstRootNodeId"] = node.GetUifirstRootNodeId();
71 }
72 DumpNodeSubClassNode(node, out);
73 }
74
DumpNodeSubsurfaces(const RSRenderNode & node,JsonWriter & out)75 void RSProfiler::DumpNodeSubsurfaces(const RSRenderNode& node, JsonWriter& out)
76 {
77 if (auto surface = node.ReinterpretCastTo<RSSurfaceRenderNode>(); surface && surface->HasSubSurfaceNodes()) {
78 auto& subsurface = out["subsurface"];
79 subsurface.PushArray();
80 for (auto [id, _] : surface->GetChildSubSurfaceNodes()) {
81 subsurface.Append(id);
82 }
83 subsurface.PopArray();
84 }
85 }
86
DumpNodeSubClassNode(const RSRenderNode & node,JsonWriter & out)87 void RSProfiler::DumpNodeSubClassNode(const RSRenderNode& node, JsonWriter& out)
88 {
89 auto& subclass = out["subclass"];
90 subclass.PushObject();
91 if (node.GetType() == RSRenderNodeType::SURFACE_NODE) {
92 auto& surfaceNode = static_cast<const RSSurfaceRenderNode&>(node);
93 auto p = node.parent_.lock();
94 subclass["Parent"] = p ? p->GetId() : uint64_t(0);
95 subclass["Name"] = surfaceNode.GetName();
96 out["hasConsumer"] = surfaceNode.GetRSSurfaceHandler()->HasConsumer();
97 std::string contextAlpha = std::to_string(surfaceNode.contextAlpha_);
98 std::string propertyAlpha = std::to_string(surfaceNode.GetRenderProperties().GetAlpha());
99 subclass["Alpha"] = propertyAlpha + " (include ContextAlpha: " + contextAlpha + ")";
100 subclass["Visible"] = std::to_string(surfaceNode.GetRenderProperties().GetVisible()) + " " +
101 surfaceNode.GetVisibleRegion().GetRegionInfo();
102 subclass["Opaque"] = surfaceNode.GetOpaqueRegion().GetRegionInfo();
103 subclass["OcclusionBg"] = std::to_string((surfaceNode.GetAbilityBgAlpha()));
104 subclass["SecurityLayer"] = surfaceNode.GetSecurityLayer();
105 subclass["skipLayer"] = surfaceNode.GetSkipLayer();
106 } else if (node.GetType() == RSRenderNodeType::ROOT_NODE) {
107 auto& rootNode = static_cast<const RSRootRenderNode&>(node);
108 subclass["Visible"] = rootNode.GetRenderProperties().GetVisible();
109 subclass["Size"] = { rootNode.GetRenderProperties().GetFrameWidth(),
110 rootNode.GetRenderProperties().GetFrameHeight() };
111 subclass["EnableRender"] = rootNode.GetEnableRender();
112 } else if (node.GetType() == RSRenderNodeType::DISPLAY_NODE) {
113 auto& displayNode = static_cast<const RSDisplayRenderNode&>(node);
114 subclass["skipLayer"] = displayNode.GetSecurityDisplay();
115 }
116 subclass.PopObject();
117 }
118
DumpNodeOptionalFlags(const RSRenderNode & node,JsonWriter & out)119 void RSProfiler::DumpNodeOptionalFlags(const RSRenderNode& node, JsonWriter& out)
120 {
121 if (node.GetBootAnimation()) {
122 out["GetBootAnimation"] = true;
123 }
124 if (node.isContainBootAnimation_) {
125 out["isContainBootAnimation_"] = true;
126 }
127 if (node.dirtyStatus_ != RSRenderNode::NodeDirty::CLEAN) {
128 out["isNodeDirty"] = static_cast<int>(node.dirtyStatus_);
129 }
130 if (node.GetRenderProperties().IsDirty()) {
131 out["isPropertyDirty"] = true;
132 }
133 if (node.isSubTreeDirty_) {
134 out["isSubTreeDirty"] = true;
135 }
136 if (node.IsPureContainer()) {
137 out["IsPureContainer"] = true;
138 }
139 }
140
DumpNodeDrawCmdModifiers(const RSRenderNode & node,JsonWriter & out)141 void RSProfiler::DumpNodeDrawCmdModifiers(const RSRenderNode& node, JsonWriter& out)
142 {
143 if (!node.renderContent_) {
144 return;
145 }
146
147 auto& modifiersJson = out["DrawCmdModifiers"];
148 modifiersJson.PushArray();
149 for (auto& [type, modifiers] : node.renderContent_->drawCmdModifiers_) {
150 modifiersJson.PushObject();
151 modifiersJson["type"] = static_cast<int>(type);
152 auto& modifierDesc = modifiersJson["modifiers"];
153 modifierDesc.PushArray();
154 for (const auto& modifier : modifiers) {
155 if (modifier) {
156 DumpNodeDrawCmdModifier(node, modifierDesc, static_cast<int>(type), *modifier);
157 }
158 }
159 modifiersJson.PopArray();
160 modifiersJson.PopObject();
161 }
162 modifiersJson.PopArray();
163 }
164
Hex(uint32_t value)165 static std::string Hex(uint32_t value)
166 {
167 std::stringstream sstream;
168 sstream << std::hex << value;
169 return sstream.str();
170 }
171
DumpNodeDrawCmdModifier(const RSRenderNode & node,JsonWriter & out,int type,RSRenderModifier & modifier)172 void RSProfiler::DumpNodeDrawCmdModifier(
173 const RSRenderNode& node, JsonWriter& out, int type, RSRenderModifier& modifier)
174 {
175 auto modType = static_cast<RSModifierType>(type);
176
177 if (modType < RSModifierType::ENV_FOREGROUND_COLOR) {
178 auto propertyPtr = std::static_pointer_cast<RSRenderProperty<Drawing::DrawCmdListPtr>>(modifier.GetProperty());
179 auto drawCmdListPtr = propertyPtr ? propertyPtr->Get() : nullptr;
180 auto propertyStr = drawCmdListPtr ? drawCmdListPtr->GetOpsWithDesc() : "";
181 size_t pos = 0;
182 size_t oldpos = 0;
183
184 out.PushObject();
185 auto& property = out["drawCmdList"];
186 property.PushArray();
187 while ((pos = propertyStr.find('\n', oldpos)) != std::string::npos) {
188 property.Append(propertyStr.substr(oldpos, pos - oldpos));
189 oldpos = pos + 1;
190 }
191 property.PopArray();
192 out.PopObject();
193 } else if (modType == RSModifierType::ENV_FOREGROUND_COLOR) {
194 auto propertyPtr = std::static_pointer_cast<RSRenderAnimatableProperty<Color>>(modifier.GetProperty());
195 if (propertyPtr) {
196 out.PushObject();
197 out["ENV_FOREGROUND_COLOR"] = "#" + Hex(propertyPtr->Get().AsRgbaInt()) + " (RGBA)";
198 out.PopObject();
199 }
200 } else if (modType == RSModifierType::ENV_FOREGROUND_COLOR_STRATEGY) {
201 auto propertyPtr =
202 std::static_pointer_cast<RSRenderProperty<ForegroundColorStrategyType>>(modifier.GetProperty());
203 if (propertyPtr) {
204 out.PushObject();
205 out["ENV_FOREGROUND_COLOR_STRATEGY"] = static_cast<int>(propertyPtr->Get());
206 out.PopObject();
207 }
208 } else if (modType == RSModifierType::GEOMETRYTRANS) {
209 auto propertyPtr = std::static_pointer_cast<RSRenderProperty<SkMatrix>>(modifier.GetProperty());
210 if (propertyPtr) {
211 std::string str;
212 propertyPtr->Get().dump(str, 0);
213 out.PushObject();
214 out["GEOMETRYTRANS"] = str;
215 out.PopObject();
216 }
217 } else if (modType == RSModifierType::CUSTOM_CLIP_TO_FRAME) {
218 auto propertyPtr = std::static_pointer_cast<RSRenderAnimatableProperty<Vector4f>>(modifier.GetProperty());
219 if (propertyPtr) {
220 std::string str;
221 propertyPtr->Dump(str);
222 out.PushObject();
223 out["CUSTOM_CLIP_TO_FRAME"] = str;
224 out.PopObject();
225 }
226 }
227 }
228
DumpNodeProperties(const RSProperties & properties,JsonWriter & out)229 void RSProfiler::DumpNodeProperties(const RSProperties& properties, JsonWriter& out)
230 {
231 auto& json = out["Properties"];
232 json.PushObject();
233 json["Bounds"] = { properties.GetBoundsPositionX(), properties.GetBoundsPositionY(), properties.GetBoundsWidth(),
234 properties.GetBoundsHeight() };
235 json["Frame"] = { properties.GetFramePositionX(), properties.GetFramePositionY(), properties.GetFrameWidth(),
236 properties.GetFrameHeight() };
237
238 if (!properties.GetVisible()) {
239 json["IsVisible"] = false;
240 }
241 DumpNodePropertiesClip(properties, json);
242 DumpNodePropertiesTransform(properties, json);
243 DumpNodePropertiesDecoration(properties, json);
244 DumpNodePropertiesShadow(properties, json);
245 DumpNodePropertiesEffects(properties, json);
246 DumpNodePropertiesColor(properties, json);
247 json.PopObject();
248 }
249
DumpNodePropertiesClip(const RSProperties & properties,JsonWriter & out)250 void RSProfiler::DumpNodePropertiesClip(const RSProperties& properties, JsonWriter& out)
251 {
252 if (properties.clipToBounds_) {
253 out["ClipToBounds"] = true;
254 }
255 if (properties.clipToFrame_) {
256 out["ClipToFrame"] = true;
257 }
258 }
259
DumpNodePropertiesTransform(const RSProperties & properties,JsonWriter & out)260 void RSProfiler::DumpNodePropertiesTransform(const RSProperties& properties, JsonWriter& out)
261 {
262 if (!ROSEN_EQ(properties.GetPositionZ(), 0.f)) {
263 out["PositionZ"] = properties.GetPositionZ();
264 }
265 RSTransform defaultTransform;
266 Vector2f pivot = properties.GetPivot();
267 if ((!ROSEN_EQ(pivot[0], defaultTransform.pivotX_) || !ROSEN_EQ(pivot[1], defaultTransform.pivotY_))) {
268 out["Pivot"] = { pivot[0], pivot[1] };
269 }
270 if (!ROSEN_EQ(properties.GetRotation(), defaultTransform.rotation_)) {
271 out["Rotation"] = properties.GetRotation();
272 }
273 if (!ROSEN_EQ(properties.GetRotationX(), defaultTransform.rotationX_)) {
274 out["RotationX"] = properties.GetRotationX();
275 }
276 if (!ROSEN_EQ(properties.GetRotationY(), defaultTransform.rotationY_)) {
277 out["RotationY"] = properties.GetRotationY();
278 }
279 if (!ROSEN_EQ(properties.GetTranslateX(), defaultTransform.translateX_)) {
280 out["TranslateX"] = properties.GetTranslateX();
281 }
282 if (!ROSEN_EQ(properties.GetTranslateY(), defaultTransform.translateY_)) {
283 out["TranslateY"] = properties.GetTranslateY();
284 }
285 if (!ROSEN_EQ(properties.GetTranslateZ(), defaultTransform.translateZ_)) {
286 out["TranslateZ"] = properties.GetTranslateZ();
287 }
288 if (!ROSEN_EQ(properties.GetScaleX(), defaultTransform.scaleX_)) {
289 out["ScaleX"] = properties.GetScaleX();
290 }
291 if (!ROSEN_EQ(properties.GetScaleY(), defaultTransform.scaleY_)) {
292 out["ScaleY"] = properties.GetScaleY();
293 }
294 }
295
DumpNodePropertiesDecoration(const RSProperties & properties,JsonWriter & out)296 void RSProfiler::DumpNodePropertiesDecoration(const RSProperties& properties, JsonWriter& out)
297 {
298 if (!properties.GetCornerRadius().IsZero()) {
299 out["CornerRadius"] = { properties.GetCornerRadius().x_, properties.GetCornerRadius().y_,
300 properties.GetCornerRadius().z_, properties.GetCornerRadius().w_ };
301 }
302 if (properties.pixelStretch_.has_value()) {
303 auto& pixelStretch = out["PixelStretch"];
304 pixelStretch.PushObject();
305 pixelStretch["left"] = properties.pixelStretch_->z_;
306 pixelStretch["top"] = properties.pixelStretch_->y_;
307 pixelStretch["right"] = properties.pixelStretch_->z_;
308 pixelStretch["bottom"] = properties.pixelStretch_->w_;
309 pixelStretch.PopObject();
310 }
311 if (!ROSEN_EQ(properties.GetAlpha(), 1.f)) {
312 out["Alpha"] = properties.GetAlpha();
313 }
314 if (!ROSEN_EQ(properties.GetSpherize(), 0.f)) {
315 out["Spherize"] = properties.GetSpherize();
316 }
317
318 if (!ROSEN_EQ(properties.GetAttractionFraction(), 0.f)) {
319 out["AttractionEffect"] = properties.GetAttractionFraction();
320 }
321
322 if (!ROSEN_EQ(properties.GetForegroundColor(), RgbPalette::Transparent())) {
323 out["ForegroundColor"] = "#" + Hex(properties.GetForegroundColor().AsArgbInt()) + " (ARGB)";
324 }
325 if (!ROSEN_EQ(properties.GetBackgroundColor(), RgbPalette::Transparent())) {
326 out["BackgroundColor"] = "#" + Hex(properties.GetBackgroundColor().AsArgbInt()) + " (ARGB)";
327 }
328 Decoration defaultDecoration;
329 if ((!ROSEN_EQ(properties.GetBgImagePositionX(), defaultDecoration.bgImageRect_.left_) ||
330 !ROSEN_EQ(properties.GetBgImagePositionY(), defaultDecoration.bgImageRect_.top_) ||
331 !ROSEN_EQ(properties.GetBgImageWidth(), defaultDecoration.bgImageRect_.width_) ||
332 !ROSEN_EQ(properties.GetBgImageHeight(), defaultDecoration.bgImageRect_.height_))) {
333 out["BgImage"] = { properties.GetBgImagePositionX(), properties.GetBgImagePositionY(),
334 properties.GetBgImageWidth(), properties.GetBgImageHeight() };
335 }
336 }
337
DumpNodePropertiesShadow(const RSProperties & properties,JsonWriter & out)338 void RSProfiler::DumpNodePropertiesShadow(const RSProperties& properties, JsonWriter& out)
339 {
340 if (!ROSEN_EQ(properties.GetShadowColor(), Color(DEFAULT_SPOT_COLOR))) {
341 out["ShadowColor"] = "#" + Hex(properties.GetShadowColor().AsArgbInt()) + " (ARGB)";
342 }
343 if (!ROSEN_EQ(properties.GetShadowOffsetX(), DEFAULT_SHADOW_OFFSET_X)) {
344 out["ShadowOffsetX"] = properties.GetShadowOffsetX();
345 }
346 if (!ROSEN_EQ(properties.GetShadowOffsetY(), DEFAULT_SHADOW_OFFSET_Y)) {
347 out["ShadowOffsetY"] = properties.GetShadowOffsetY();
348 }
349 if (!ROSEN_EQ(properties.GetShadowAlpha(), 0.f)) {
350 out["ShadowAlpha"] = properties.GetShadowAlpha();
351 }
352 if (!ROSEN_EQ(properties.GetShadowElevation(), 0.f)) {
353 out["ShadowElevation"] = properties.GetShadowElevation();
354 }
355 if (!ROSEN_EQ(properties.GetShadowRadius(), 0.f)) {
356 out["ShadowRadius"] = properties.GetShadowRadius();
357 }
358 if (!ROSEN_EQ(properties.GetShadowIsFilled(), false)) {
359 out["ShadowIsFilled"] = properties.GetShadowIsFilled();
360 }
361 }
362
DumpNodePropertiesEffects(const RSProperties & properties,JsonWriter & out)363 void RSProfiler::DumpNodePropertiesEffects(const RSProperties& properties, JsonWriter& out)
364 {
365 if (properties.border_ && properties.border_->HasBorder()) {
366 out["Border"] = properties.border_->ToString();
367 }
368 auto filter = properties.GetFilter();
369 if (filter && filter->IsValid()) {
370 out["Filter"] = filter->GetDescription();
371 }
372 auto backgroundFilter = properties.GetBackgroundFilter();
373 if (backgroundFilter && backgroundFilter->IsValid()) {
374 out["BackgroundFilter"] = backgroundFilter->GetDescription();
375 }
376 auto foregroundFilterCache = properties.GetForegroundFilterCache();
377 if (foregroundFilterCache && foregroundFilterCache->IsValid()) {
378 out["ForegroundFilter"] = foregroundFilterCache->GetDescription();
379 }
380 if (properties.outline_ && properties.outline_->HasBorder()) {
381 out["Outline"] = properties.outline_->ToString();
382 }
383 if (!ROSEN_EQ(properties.GetFrameGravity(), Gravity::DEFAULT)) {
384 out["FrameGravity"] = static_cast<int>(properties.GetFrameGravity());
385 }
386 if (properties.GetUseEffect()) {
387 out["GetUseEffect"] = true;
388 }
389 auto grayScale = properties.GetGrayScale();
390 if (grayScale.has_value() && !ROSEN_EQ(*grayScale, 0.f)) {
391 out["GrayScale"] = *grayScale;
392 }
393 if (!ROSEN_EQ(properties.GetLightUpEffect(), 1.f)) {
394 out["LightUpEffect"] = properties.GetLightUpEffect();
395 }
396 auto dynamicLightUpRate = properties.GetDynamicLightUpRate();
397 if (dynamicLightUpRate.has_value() && !ROSEN_EQ(*dynamicLightUpRate, 0.f)) {
398 out["DynamicLightUpRate"] = *dynamicLightUpRate;
399 }
400 auto dynamicLightUpDegree = properties.GetDynamicLightUpDegree();
401 if (dynamicLightUpDegree.has_value() && !ROSEN_EQ(*dynamicLightUpDegree, 0.f)) {
402 out["DynamicLightUpDegree"] = *dynamicLightUpDegree;
403 }
404 }
405
DumpNodePropertiesColor(const RSProperties & properties,JsonWriter & out)406 void RSProfiler::DumpNodePropertiesColor(const RSProperties& properties, JsonWriter& out)
407 {
408 auto brightness = properties.GetBrightness();
409 if (brightness.has_value() && !ROSEN_EQ(*brightness, 1.f)) {
410 out["Brightness"] = *brightness;
411 }
412 auto contrast = properties.GetContrast();
413 if (contrast.has_value() && !ROSEN_EQ(*contrast, 1.f)) {
414 out["Contrast"] = *contrast;
415 }
416 auto saturate = properties.GetSaturate();
417 if (saturate.has_value() && !ROSEN_EQ(*saturate, 1.f)) {
418 out["Saturate"] = *saturate;
419 }
420 auto sepia = properties.GetSepia();
421 if (sepia.has_value() && !ROSEN_EQ(*sepia, 0.f)) {
422 out["Sepia"] = *sepia;
423 }
424 auto invert = properties.GetInvert();
425 if (invert.has_value() && !ROSEN_EQ(*invert, 0.f)) {
426 out["Invert"] = *invert;
427 }
428 auto hueRotate = properties.GetHueRotate();
429 if (hueRotate.has_value() && !ROSEN_EQ(*hueRotate, 0.f)) {
430 out["HueRotate"] = *hueRotate;
431 }
432 auto colorBlend = properties.GetColorBlend();
433 if (colorBlend.has_value() && !ROSEN_EQ(*colorBlend, RgbPalette::Transparent())) {
434 out["ColorBlend"] = "#" + Hex(colorBlend->AsArgbInt()) + " (ARGB)";
435 }
436 if (!ROSEN_EQ(properties.GetColorBlendMode(), 0)) {
437 out["skblendmode"] = properties.GetColorBlendMode() - 1;
438 out["blendType"] = properties.GetColorBlendApplyType();
439 }
440 }
441
DumpNodeAnimations(const RSAnimationManager & animationManager,JsonWriter & out)442 void RSProfiler::DumpNodeAnimations(const RSAnimationManager& animationManager, JsonWriter& out)
443 {
444 if (animationManager.animations_.empty()) {
445 return;
446 }
447 auto& animations = out["RSAnimationManager"];
448 animations.PushArray();
449 for (auto [id, animation] : animationManager.animations_) {
450 if (animation) {
451 DumpNodeAnimation(*animation, animations);
452 }
453 }
454 animations.PopArray();
455 }
456
DumpNodeAnimation(const RSRenderAnimation & animation,JsonWriter & out)457 void RSProfiler::DumpNodeAnimation(const RSRenderAnimation& animation, JsonWriter& out)
458 {
459 out.PushObject();
460 out["id"] = animation.id_;
461 std::string type;
462 animation.DumpAnimationType(type);
463 out["type"] = type;
464 out["AnimationState"] = static_cast<int>(animation.state_);
465 out["StartDelay"] = animation.animationFraction_.GetDuration();
466 out["Duration"] = animation.animationFraction_.GetStartDelay();
467 out["Speed"] = animation.animationFraction_.GetSpeed();
468 out["RepeatCount"] = animation.animationFraction_.GetRepeatCount();
469 out["AutoReverse"] = animation.animationFraction_.GetAutoReverse();
470 out["Direction"] = animation.animationFraction_.GetDirection();
471 out["FillMode"] = static_cast<int>(animation.animationFraction_.GetFillMode());
472 out["RepeatCallbackEnable"] = animation.animationFraction_.GetRepeatCallbackEnable();
473 out["FrameRateRange_min"] = animation.animationFraction_.GetFrameRateRange().min_;
474 out["FrameRateRange_max"] = animation.animationFraction_.GetFrameRateRange().max_;
475 out["FrameRateRange_prefered"] = animation.animationFraction_.GetFrameRateRange().preferred_;
476 out.PopObject();
477 }
478
DumpNodeChildrenListUpdate(const RSRenderNode & node,JsonWriter & out)479 void RSProfiler::DumpNodeChildrenListUpdate(const RSRenderNode& node, JsonWriter& out)
480 {
481 if (!node.isFullChildrenListValid_) {
482 auto& childrenUpdate = out["children update"];
483 childrenUpdate.PushObject();
484 childrenUpdate["current count"] = node.fullChildrenList_->size();
485 std::string expected = std::to_string(node.GetSortedChildren()->size());
486 if (!node.disappearingChildren_.empty()) {
487 childrenUpdate["disappearing count"] = node.disappearingChildren_.size();
488 expected += " + " + std::to_string(node.disappearingChildren_.size());
489 }
490 childrenUpdate["expected count"] = expected;
491 childrenUpdate.PopObject();
492 }
493 }
494
495 } // namespace OHOS::Rosen