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