• 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 <algorithm>
17 #include <cstddef>
18 #include <iostream>
19 #include <memory>
20 #include <string>
21 #include <sys/mman.h>
22 #include <type_traits>
23 #include <utility>
24 #include <vector>
25 
26 #include "message_parcel.h"
27 #include "rs_profiler.h"
28 #include "rs_profiler_cache.h"
29 #include "rs_profiler_capture_recorder.h"
30 #include "rs_profiler_file.h"
31 #include "rs_profiler_log.h"
32 #include "rs_profiler_network.h"
33 #include "rs_profiler_utils.h"
34 #include "sys_binder.h"
35 
36 #include "animation/rs_animation_manager.h"
37 #include "command/rs_base_node_command.h"
38 #include "command/rs_canvas_drawing_node_command.h"
39 #include "command/rs_canvas_node_command.h"
40 #include "command/rs_effect_node_command.h"
41 #include "command/rs_proxy_node_command.h"
42 #include "command/rs_root_node_command.h"
43 #include "command/rs_surface_node_command.h"
44 #include "modifier_ng/rs_modifier_ng_type.h"
45 #include "pipeline/rs_canvas_drawing_render_node.h"
46 #include "pipeline/rs_render_node.h"
47 #include "pipeline/rs_surface_render_node.h"
48 #include "pipeline/rs_screen_render_node.h"
49 #include "transaction/rs_ashmem_helper.h"
50 
51 #include "render/rs_shader_filter.h"
52 #include "ge_shader_filter.h"
53 
54 namespace OHOS::Rosen {
55 std::atomic_bool RSProfiler::recordAbortRequested_ = false;
56 std::atomic_uint32_t RSProfiler::mode_ = static_cast<uint32_t>(Mode::NONE);
57 static std::vector<pid_t> g_pids;
58 static pid_t g_pid = 0;
59 static NodeId g_parentNode = 0;
60 static std::atomic<uint32_t> g_commandCount = 0;        // UNMARSHALLING RSCOMMAND COUNT
61 static std::atomic<uint32_t> g_commandExecuteCount = 0; // EXECUTE RSCOMMAND COUNT
62 
63 static std::mutex g_msgBaseMutex;
64 static std::queue<std::string> g_msgBaseList;
65 
66 static std::mutex g_rsLogListMutex;
67 static std::queue<RSProfilerLogMsg> g_rsLogList;
68 
69 static std::mutex g_mutexCommandOffsets;
70 static std::map<uint32_t, std::vector<uint32_t>> g_parcelNumber2Offset;
71 
72 static uint64_t g_pauseAfterTime = 0;
73 static int64_t g_pauseCumulativeTime = 0;
74 static int64_t g_transactionTimeCorrection = 0;
75 static int64_t g_replayStartTimeNano = 0.0;
76 static double g_replaySpeed = 1.0f;
77 
78 static const size_t PARCEL_MAX_CAPACITY = 234 * 1024 * 1024;
79 
80 static std::unordered_map<AnimationId, std::vector<int64_t>> g_animeStartMap;
81 
82 bool RSProfiler::testing_ = false;
83 std::vector<std::shared_ptr<RSRenderNode>> RSProfiler::testTree_ = std::vector<std::shared_ptr<RSRenderNode>>();
84 bool RSProfiler::enabled_ = RSSystemProperties::GetProfilerEnabled();
85 bool RSProfiler::hrpServiceEnabled_ = RSSystemProperties::GetProfilerEnabled();
86 bool RSProfiler::betaRecordingEnabled_ = RSSystemProperties::GetBetaRecordingMode() != 0;
87 std::atomic<int8_t> RSProfiler::signalFlagChanged_ = 0;
88 std::atomic_bool RSProfiler::dcnRedraw_ = false;
89 std::atomic_bool RSProfiler::renderNodeKeepDrawCmdList_ = false;
90 std::vector<RSRenderNode::WeakPtr> g_childOfDisplayNodesPostponed;
91 std::unordered_map<AnimationId, int64_t> RSProfiler::animationsTimes_;
92 
93 static TextureRecordType g_textureRecordType = TextureRecordType::LZ4;
94 
GetParcelMaxCapacity()95 constexpr size_t GetParcelMaxCapacity()
96 {
97     return PARCEL_MAX_CAPACITY;
98 }
99 
IsEnabled()100 bool RSProfiler::IsEnabled()
101 {
102     return enabled_ || testing_;
103 }
104 
IsHrpServiceEnabled()105 bool RSProfiler::IsHrpServiceEnabled()
106 {
107     return hrpServiceEnabled_;
108 }
109 
IsBetaRecordEnabled()110 bool RSProfiler::IsBetaRecordEnabled()
111 {
112 #ifdef RS_PROFILER_BETA_ENABLED
113     return betaRecordingEnabled_;
114 #else
115     return false;
116 #endif
117 }
118 
IsNoneMode()119 bool RSProfiler::IsNoneMode()
120 {
121     return GetMode() == Mode::NONE;
122 }
123 
IsReadMode()124 bool RSProfiler::IsReadMode()
125 {
126     return GetMode() == Mode::READ;
127 }
128 
IsReadEmulationMode()129 bool RSProfiler::IsReadEmulationMode()
130 {
131     return GetMode() == Mode::READ_EMUL;
132 }
133 
IsWriteMode()134 bool RSProfiler::IsWriteMode()
135 {
136     return GetMode() == Mode::WRITE;
137 }
138 
IsWriteEmulationMode()139 bool RSProfiler::IsWriteEmulationMode()
140 {
141     return GetMode() == Mode::WRITE_EMUL;
142 }
143 
IsSavingMode()144 bool RSProfiler::IsSavingMode()
145 {
146     return GetMode() == Mode::SAVING;
147 }
148 
AddLightBlursMetrics(uint32_t areaBlurs)149 void RSProfiler::AddLightBlursMetrics(uint32_t areaBlurs)
150 {
151     if (!IsEnabled() || !IsWriteMode()) {
152         return;
153     }
154 
155     GetCustomMetrics().AddInt(RSPROFILER_METRIC_LIGHT_BLUR_OPERATIONS, 1);
156     GetCustomMetrics().AddInt(RSPROFILER_METRIC_BLUR_OPERATIONS, 1);
157     GetCustomMetrics().AddFloat(RSPROFILER_METRIC_BLUR_AREA_OPERATIONS, areaBlurs);
158 }
AddAnimationNodeMetrics(RSRenderNodeType type,int32_t size)159 void RSProfiler::AddAnimationNodeMetrics(RSRenderNodeType type, int32_t size)
160 {
161     if (!IsEnabled() || !IsWriteMode()) {
162         return;
163     }
164 
165     GetCustomMetrics().AddInt(RSPROFILER_METRIC_ANIMATION_NODE, 1);
166     GetCustomMetrics().AddFloat(RSPROFILER_METRIC_ANIMATION_NODE_SIZE, size);
167 
168     int profiler_node_type = -1;
169     switch (type) {
170         case RSRenderNodeType::SURFACE_NODE:
171             profiler_node_type = RSPROFILER_METRIC_ANIMATION_NODE_TYPE_SURFACE_NODE;
172             break;
173         case RSRenderNodeType::PROXY_NODE:
174             profiler_node_type = RSPROFILER_METRIC_ANIMATION_NODE_TYPE_PROXY_NODE;
175             break;
176         case RSRenderNodeType::CANVAS_NODE:
177             profiler_node_type = RSPROFILER_METRIC_ANIMATION_NODE_TYPE_CANVAS_NODE;
178             break;
179         case RSRenderNodeType::EFFECT_NODE:
180             profiler_node_type = RSPROFILER_METRIC_ANIMATION_NODE_TYPE_EFFECT_NODE;
181             break;
182         case RSRenderNodeType::ROOT_NODE:
183             profiler_node_type = RSPROFILER_METRIC_ANIMATION_NODE_TYPE_ROOT_NODE;
184             break;
185         case RSRenderNodeType::CANVAS_DRAWING_NODE:
186             profiler_node_type = RSPROFILER_METRIC_ANIMATION_NODE_TYPE_CANVAS_DRAWING_NODE;
187             break;
188         default:  // exclude RSRenderNodeType::(RS_NODE, UNKNOW, DISPLAY_NODE)
189             break;
190     }
191 
192     if (profiler_node_type >= 0) {
193         GetCustomMetrics().AddInt(profiler_node_type, 1);
194     }
195 }
196 
AddAnimationStart(AnimationId id,int64_t timestamp_ns)197 void RSProfiler::AddAnimationStart(AnimationId id, int64_t timestamp_ns)
198 {
199     if (!IsEnabled() || !IsWriteMode()) {
200         return;
201     }
202     animationsTimes_[id] = timestamp_ns;
203 }
204 
AddAnimationFinish(AnimationId id,int64_t timestamp_ns)205 void RSProfiler::AddAnimationFinish(AnimationId id, int64_t timestamp_ns)
206 {
207     if (!IsEnabled() || !IsWriteMode()) {
208         return;
209     }
210     if (animationsTimes_.count(id) == 1) {
211         GetCustomMetrics().AddFloat(
212             RSPROFILER_METRIC_ANIMATION_DURATION, float(timestamp_ns - animationsTimes_[id]) / 1'000'000'000.f);
213         animationsTimes_.erase(id);
214     }
215 }
216 
AddHPSBlursMetrics(uint32_t areaBlurs)217 void RSProfiler::AddHPSBlursMetrics(uint32_t areaBlurs)
218 {
219     if (!IsEnabled() || !IsWriteMode()) {
220         return;
221     }
222 
223     GetCustomMetrics().AddInt(RSPROFILER_METRIC_HPS_BLUR_OPERATIONS, 1);
224     GetCustomMetrics().AddInt(RSPROFILER_METRIC_BLUR_OPERATIONS, 1);
225     GetCustomMetrics().AddFloat(RSPROFILER_METRIC_BLUR_AREA_OPERATIONS, areaBlurs);
226 }
227 
AddKawaseBlursMetrics(uint32_t areaBlurs)228 void RSProfiler::AddKawaseBlursMetrics(uint32_t areaBlurs)
229 {
230     if (!IsEnabled() || !IsWriteMode()) {
231         return;
232     }
233 
234     GetCustomMetrics().AddInt(RSPROFILER_METRIC_KAWASE_BLUR_OPERATIONS, 1);
235     GetCustomMetrics().AddInt(RSPROFILER_METRIC_BLUR_OPERATIONS, 1);
236     GetCustomMetrics().AddFloat(RSPROFILER_METRIC_BLUR_AREA_OPERATIONS, areaBlurs);
237 }
238 
AddMESABlursMetrics(uint32_t areaBlurs)239 void RSProfiler::AddMESABlursMetrics(uint32_t areaBlurs)
240 {
241     if (!IsEnabled() || !IsWriteMode()) {
242         return;
243     }
244 
245     GetCustomMetrics().AddInt(RSPROFILER_METRIC_MESA_BLUR_OPERATIONS, 1);
246     GetCustomMetrics().AddInt(RSPROFILER_METRIC_BLUR_OPERATIONS, 1);
247     GetCustomMetrics().AddFloat(RSPROFILER_METRIC_BLUR_AREA_OPERATIONS, areaBlurs);
248 }
249 
LogShaderCall(const std::string & shaderType,const std::shared_ptr<Drawing::Image> & srcImage,const Drawing::Rect & dstRect,const std::shared_ptr<Drawing::Image> & outImage)250 void RSProfiler::LogShaderCall(const std::string& shaderType, const std::shared_ptr<Drawing::Image>& srcImage,
251     const Drawing::Rect& dstRect, const std::shared_ptr<Drawing::Image>& outImage)
252 {
253     if (!IsEnabled() || !IsWriteMode()) {
254         return;
255     }
256 
257     if (shaderType == "KAWASE_BLUR") {
258         GetCustomMetrics().AddInt(RSPROFILER_METRIC_KAWASE_BLUR_SHADER_CALLS, 1);
259     } else if (shaderType == "MESA_BLUR") {
260         GetCustomMetrics().AddInt(RSPROFILER_METRIC_MESA_BLUR_SHADER_CALLS, 1);
261     } else if (shaderType == "AIBAR") {
262         GetCustomMetrics().AddInt(RSPROFILER_METRIC_AIBAR_BLUR_SHADER_CALLS, 1);
263     } else if (shaderType == "GREY") {
264         GetCustomMetrics().AddInt(RSPROFILER_METRIC_GREY_BLUR_SHADER_CALLS, 1);
265     } else if (shaderType == "LINEAR_GRADIENT_BLUR") {
266         GetCustomMetrics().AddInt(RSPROFILER_METRIC_LINEAR_GRADIENT_BLUR_SHADER_CALLS, 1);
267     } else if (shaderType == "MAGNIFIER") {
268         GetCustomMetrics().AddInt(RSPROFILER_METRIC_MAGNIFIER_SHADER_CALLS, 1);
269     } else if (shaderType == "WATER_RIPPLE") {
270         GetCustomMetrics().AddInt(RSPROFILER_METRIC_WATER_RIPPLE_BLUR_SHADER_CALLS, 1);
271     }
272     GetCustomMetrics().AddInt(RSPROFILER_METRIC_BLUR_SHADER_CALLS, 1);
273     GetCustomMetrics().AddFloat(RSPROFILER_METRIC_BLUR_AREA_SHADER_CALLS, srcImage->GetWidth() * srcImage->GetHeight());
274 }
275 
GetCommandCount()276 uint32_t RSProfiler::GetCommandCount()
277 {
278     const uint32_t count = g_commandCount;
279     g_commandCount = 0;
280     return count;
281 }
282 
GetCommandExecuteCount()283 uint32_t RSProfiler::GetCommandExecuteCount()
284 {
285     const uint32_t count = g_commandExecuteCount;
286     g_commandExecuteCount = 0;
287     return count;
288 }
289 
EnableSharedMemory()290 void RSProfiler::EnableSharedMemory()
291 {
292     RSMarshallingHelper::EndNoSharedMem();
293 }
294 
DisableSharedMemory()295 void RSProfiler::DisableSharedMemory()
296 {
297     RSMarshallingHelper::BeginNoSharedMem(std::this_thread::get_id());
298 }
299 
IsSharedMemoryEnabled()300 bool RSProfiler::IsSharedMemoryEnabled()
301 {
302     return RSMarshallingHelper::GetUseSharedMem(std::this_thread::get_id());
303 }
304 
IsParcelMock(const Parcel & parcel)305 bool RSProfiler::IsParcelMock(const Parcel& parcel)
306 {
307     // gcc C++ optimization error (?): this is not working without volatile
308     const volatile auto address = reinterpret_cast<uint64_t>(&parcel);
309     return ((address & 1u) != 0);
310 }
311 
IsPlaybackParcel(const Parcel & parcel)312 bool RSProfiler::IsPlaybackParcel(const Parcel& parcel)
313 {
314     return (IsReadMode() || IsReadEmulationMode())
315         && IsParcelMock(parcel);
316 }
317 
CopyParcel(const MessageParcel & parcel)318 std::shared_ptr<MessageParcel> RSProfiler::CopyParcel(const MessageParcel& parcel)
319 {
320     if (!IsEnabled()) {
321         return std::make_shared<MessageParcel>();
322     }
323 
324     if (IsParcelMock(parcel)) {
325         auto* buffer = new(std::nothrow) uint8_t[sizeof(MessageParcel) + 1];
326         if (!buffer) {
327             return std::make_shared<MessageParcel>();
328         }
329         auto* mpPtr = new (buffer + 1) MessageParcel;
330         return std::shared_ptr<MessageParcel>(mpPtr, [](MessageParcel* ptr) {
331             ptr->~MessageParcel();
332             auto* allocPtr = reinterpret_cast<uint8_t*>(ptr);
333             allocPtr--;
334             delete[] allocPtr;
335         });
336     }
337 
338     return std::make_shared<MessageParcel>();
339 }
340 
PatchPlainNodeId(const Parcel & parcel,NodeId id)341 NodeId RSProfiler::PatchPlainNodeId(const Parcel& parcel, NodeId id)
342 {
343     if (!IsEnabled()) {
344         return id;
345     }
346 
347     if ((!IsReadMode() && !IsReadEmulationMode()) || !IsParcelMock(parcel)) {
348         return id;
349     }
350 
351     return Utils::PatchNodeId(id);
352 }
353 
PatchTypefaceId(const Parcel & parcel,std::shared_ptr<Drawing::DrawCmdList> & val)354 void RSProfiler::PatchTypefaceId(const Parcel& parcel, std::shared_ptr<Drawing::DrawCmdList>& val)
355 {
356     if (!val || !IsEnabled()) {
357         return;
358     }
359 
360     if (IsReadEmulationMode()) {
361         val->PatchTypefaceIds();
362     } else if (IsReadMode()) {
363         if (IsParcelMock(parcel)) {
364             val->PatchTypefaceIds();
365         }
366     }
367 }
368 
PatchPlainPid(const Parcel & parcel,pid_t pid)369 pid_t RSProfiler::PatchPlainPid(const Parcel& parcel, pid_t pid)
370 {
371     if (!IsEnabled() || (!IsReadMode() && !IsReadEmulationMode()) || !IsParcelMock(parcel)) {
372         return pid;
373     }
374 
375     return Utils::GetMockPid(pid);
376 }
377 
SetMode(Mode mode)378 void RSProfiler::SetMode(Mode mode)
379 {
380     mode_ = static_cast<uint32_t>(mode);
381     if (IsNoneMode()) {
382         g_pauseAfterTime = 0;
383         g_pauseCumulativeTime = 0;
384         g_replayStartTimeNano = 0;
385     }
386 }
387 
GetMode()388 Mode RSProfiler::GetMode()
389 {
390     return static_cast<Mode>(mode_.load());
391 }
392 
SetSubstitutingPid(const std::vector<pid_t> & pids,pid_t pid,NodeId parent)393 void RSProfiler::SetSubstitutingPid(const std::vector<pid_t>& pids, pid_t pid, NodeId parent)
394 {
395     g_pids = pids;
396     g_pid = pid;
397     g_parentNode = parent;
398 }
399 
GetParentNode()400 NodeId RSProfiler::GetParentNode()
401 {
402     return g_parentNode;
403 }
404 
GetPids()405 const std::vector<pid_t>& RSProfiler::GetPids()
406 {
407     return g_pids;
408 }
409 
GetSubstitutingPid()410 pid_t RSProfiler::GetSubstitutingPid()
411 {
412     return g_pid;
413 }
414 
PatchTime(uint64_t time)415 uint64_t RSProfiler::PatchTime(uint64_t time)
416 {
417     if (!IsEnabled()) {
418         return time;
419     }
420     if (!IsReadMode() && !IsReadEmulationMode()) {
421         return time;
422     }
423     if (time == 0.0) {
424         return 0.0;
425     }
426     if (time >= g_pauseAfterTime && g_pauseAfterTime > 0) {
427         return (static_cast<int64_t>(g_pauseAfterTime) - g_pauseCumulativeTime - g_replayStartTimeNano) *
428             BaseGetPlaybackSpeed() + g_replayStartTimeNano;
429     }
430     return (static_cast<int64_t>(time) - g_pauseCumulativeTime - g_replayStartTimeNano) *
431         BaseGetPlaybackSpeed() + g_replayStartTimeNano;
432 }
433 
PatchTransactionTime(const Parcel & parcel,uint64_t time)434 uint64_t RSProfiler::PatchTransactionTime(const Parcel& parcel, uint64_t time)
435 {
436     if (!IsEnabled()) {
437         return time;
438     }
439 
440     if (!IsReadMode()) {
441         return time;
442     }
443     if (time == 0.0) {
444         return 0.0;
445     }
446     if (!IsParcelMock(parcel)) {
447         return time;
448     }
449 
450     return PatchTime(time + g_transactionTimeCorrection);
451 }
452 
TimePauseAt(uint64_t curTime,uint64_t newPauseAfterTime,bool immediate)453 void RSProfiler::TimePauseAt(uint64_t curTime, uint64_t newPauseAfterTime, bool immediate)
454 {
455     if (g_pauseAfterTime > 0) {
456         // second time pause
457         if (curTime > g_pauseAfterTime) {
458             g_pauseCumulativeTime += static_cast<int64_t>(curTime - g_pauseAfterTime);
459         }
460     }
461     g_pauseAfterTime = newPauseAfterTime;
462     if (immediate) {
463         g_pauseCumulativeTime += static_cast<int64_t>(curTime - g_pauseAfterTime);
464         g_pauseAfterTime = curTime;
465     }
466 }
467 
TimePauseResume(uint64_t curTime)468 void RSProfiler::TimePauseResume(uint64_t curTime)
469 {
470     if (g_pauseAfterTime > 0) {
471         if (curTime > g_pauseAfterTime) {
472             g_pauseCumulativeTime += static_cast<int64_t>(curTime - g_pauseAfterTime);
473         }
474     }
475     g_pauseAfterTime = 0;
476 }
477 
TimePauseClear()478 void RSProfiler::TimePauseClear()
479 {
480     g_pauseCumulativeTime = 0;
481     g_pauseAfterTime = 0;
482 }
483 
TimePauseGet()484 uint64_t RSProfiler::TimePauseGet()
485 {
486     return g_pauseAfterTime;
487 }
488 
GetScreenNode(const RSContext & context)489 std::shared_ptr<RSScreenRenderNode> RSProfiler::GetScreenNode(const RSContext& context)
490 {
491     const std::shared_ptr<RSBaseRenderNode>& root = context.GetGlobalRootRenderNode();
492     // without these checks device might get stuck on startup
493     if (!root || !root->GetChildrenCount()) {
494         return nullptr;
495     }
496 
497     const auto& children = *root->GetChildren();
498     if (children.empty()) {
499         return nullptr;
500     }
501     for (const auto& screenNode : children) {   // apply multiple screen nodes
502         if (!screenNode) {
503             continue;
504         }
505         const auto& screenNodeChildren = screenNode->GetChildren();
506         if (screenNodeChildren->empty()) {
507             continue;
508         }
509         return RSBaseRenderNode::ReinterpretCast<RSScreenRenderNode>(screenNode);
510     }
511     return nullptr;
512 }
513 
GetScreenRect(const RSContext & context)514 Vector4f RSProfiler::GetScreenRect(const RSContext& context)
515 {
516     std::shared_ptr<RSScreenRenderNode> node = GetScreenNode(context);
517     if (!node) {
518         return {};
519     }
520 
521     const RectI rect = node->GetDirtyManager()->GetSurfaceRect();
522     return { rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom() };
523 }
524 
FilterForPlayback(RSContext & context,pid_t pid)525 void RSProfiler::FilterForPlayback(RSContext& context, pid_t pid)
526 {
527     auto& map = context.GetMutableNodeMap();
528 
529     auto canBeRemoved = [](NodeId node, pid_t pid) -> bool {
530         return (ExtractPid(node) == pid) && (Utils::ExtractNodeId(node) != 1);
531     };
532 
533     // remove all nodes belong to given pid (by matching higher 32 bits of node id)
534     auto iter = map.renderNodeMap_.find(pid);
535     if (iter != map.renderNodeMap_.end()) {
536         auto& subMap = iter->second;
537         EraseIf(subMap, [](const auto& pair) -> bool {
538             if (Utils::ExtractNodeId(pair.first) == 1) {
539                 return false;
540             }
541             // remove node from tree
542             pair.second->RemoveFromTree(false);
543             return true;
544         });
545         if (subMap.empty()) {
546             map.renderNodeMap_.erase(pid);
547         }
548     }
549 
550     EraseIf(
551         map.surfaceNodeMap_, [pid, canBeRemoved](const auto& pair) -> bool { return canBeRemoved(pair.first, pid); });
552 
553     EraseIf(map.residentSurfaceNodeMap_,
554         [pid, canBeRemoved](const auto& pair) -> bool { return canBeRemoved(pair.first, pid); });
555 
556     EraseIf(
557         map.screenNodeMap_, [pid, canBeRemoved](const auto& pair) -> bool { return canBeRemoved(pair.first, pid); });
558 
559     if (auto fallbackNode = map.GetAnimationFallbackNode()) {
560         fallbackNode->GetAnimationManager().FilterAnimationByPid(pid);
561     }
562 }
563 
FilterMockNode(RSContext & context)564 void RSProfiler::FilterMockNode(RSContext& context)
565 {
566     std::unordered_set<pid_t> pidSet;
567 
568     auto& nodeMap = context.GetMutableNodeMap();
569     nodeMap.TraversalNodes([&pidSet](const std::shared_ptr<RSBaseRenderNode>& node) {
570         if (node == nullptr) {
571             return;
572         }
573         if (Utils::IsNodeIdPatched(node->GetId())) {
574             pidSet.insert(Utils::ExtractPid(node->GetId()));
575         }
576     });
577 
578     for (auto pid : pidSet) {
579         nodeMap.FilterNodeByPid(pid, true);
580     }
581 
582     if (auto fallbackNode = nodeMap.GetAnimationFallbackNode()) {
583         // remove all fallback animations belong to given pid
584         FilterAnimationForPlayback(fallbackNode->GetAnimationManager());
585     }
586 }
587 
GetSurfacesTrees(const RSContext & context,std::map<std::string,std::tuple<NodeId,std::string>> & list)588 void RSProfiler::GetSurfacesTrees(
589     const RSContext& context, std::map<std::string, std::tuple<NodeId, std::string>>& list)
590 {
591     constexpr uint32_t treeDumpDepth = 2;
592 
593     list.clear();
594 
595     const RSRenderNodeMap& map = const_cast<RSContext&>(context).GetMutableNodeMap();
596     for (const auto& [_, subMap] : map.renderNodeMap_) {
597         for (const auto& [_, node] : subMap) {
598             if (node->GetType() == RSRenderNodeType::SURFACE_NODE) {
599                 std::string tree;
600                 node->DumpTree(treeDumpDepth, tree);
601                 const auto surfaceNode = node->ReinterpretCastTo<RSSurfaceRenderNode>();
602                 list.insert({ surfaceNode->GetName(), { surfaceNode->GetId(), tree } });
603             }
604         }
605     }
606 }
607 
GetSurfacesTrees(const RSContext & context,pid_t pid,std::map<NodeId,std::string> & list)608 void RSProfiler::GetSurfacesTrees(const RSContext& context, pid_t pid, std::map<NodeId, std::string>& list)
609 {
610     constexpr uint32_t treeDumpDepth = 2;
611 
612     list.clear();
613 
614     const RSRenderNodeMap& map = const_cast<RSContext&>(context).GetMutableNodeMap();
615     for (const auto& [_, subMap] : map.renderNodeMap_) {
616         for (const auto& [_, node] : subMap) {
617             if (node->GetId() == Utils::GetRootNodeId(pid)) {
618                 std::string tree;
619                 node->DumpTree(treeDumpDepth, tree);
620                 list.insert({ node->GetId(), tree });
621             }
622         }
623     }
624 }
625 
GetRenderNodeCount(const RSContext & context)626 size_t RSProfiler::GetRenderNodeCount(const RSContext& context)
627 {
628     return const_cast<RSContext&>(context).GetMutableNodeMap().GetSize();
629 }
630 
GetRandomSurfaceNode(const RSContext & context)631 NodeId RSProfiler::GetRandomSurfaceNode(const RSContext& context)
632 {
633     const RSRenderNodeMap& map = const_cast<RSContext&>(context).GetMutableNodeMap();
634     for (const auto& item : map.surfaceNodeMap_) {
635         return item.first;
636     }
637     return 0;
638 }
639 
MarshalNodes(const RSContext & context,std::stringstream & data,uint32_t fileVersion)640 void RSProfiler::MarshalNodes(const RSContext& context, std::stringstream& data, uint32_t fileVersion)
641 {
642     const auto& map = const_cast<RSContext&>(context).GetMutableNodeMap();
643     const uint32_t count = static_cast<uint32_t>(map.GetSize());
644     data.write(reinterpret_cast<const char*>(&count), sizeof(count));
645     const auto& rootRenderNode = context.GetGlobalRootRenderNode();
646     if (rootRenderNode == nullptr) {
647         RS_LOGE("RSProfiler::MarshalNodes rootRenderNode is nullptr");
648         return;
649     }
650 
651     std::vector<std::shared_ptr<RSRenderNode>> nodes;
652     nodes.emplace_back(rootRenderNode);
653 
654     for (const auto& [_, subMap] : map.renderNodeMap_) {
655         for (const auto& [_, node] : subMap) {
656             if (node != nullptr) {
657                 MarshalNode(*node, data, fileVersion);
658                 std::shared_ptr<RSRenderNode> parent = node->GetParent().lock();
659                 if (!parent && (node != rootRenderNode)) {
660                     nodes.emplace_back(node);
661                 }
662             }
663         }
664     }
665 
666     const uint32_t nodeCount = static_cast<uint32_t>(nodes.size());
667     data.write(reinterpret_cast<const char*>(&nodeCount), sizeof(nodeCount));
668     for (const auto& node : nodes) { // no nullptr in nodes, omit check
669         MarshalTree(*node, data, fileVersion);
670     }
671 }
672 
MarshalTree(const RSRenderNode & node,std::stringstream & data,uint32_t fileVersion)673 void RSProfiler::MarshalTree(const RSRenderNode& node, std::stringstream& data, uint32_t fileVersion)
674 {
675     const NodeId nodeId = node.GetId();
676     data.write(reinterpret_cast<const char*>(&nodeId), sizeof(nodeId));
677 
678     const uint32_t count = node.children_.size();
679     data.write(reinterpret_cast<const char*>(&count), sizeof(count));
680 
681     for (const auto& child : node.children_) {
682         if (auto node = child.lock().get()) {
683             const NodeId nodeId = node->GetId();
684             data.write(reinterpret_cast<const char*>(&nodeId), sizeof(nodeId));
685             MarshalTree(*node, data, fileVersion);
686         }
687     }
688 }
689 
MarshalNode(const RSRenderNode & node,std::stringstream & data,uint32_t fileVersion)690 void RSProfiler::MarshalNode(const RSRenderNode& node, std::stringstream& data, uint32_t fileVersion)
691 {
692     const RSRenderNodeType nodeType = node.GetType();
693     data.write(reinterpret_cast<const char*>(&nodeType), sizeof(nodeType));
694 
695     const NodeId nodeId = node.GetId();
696     data.write(reinterpret_cast<const char*>(&nodeId), sizeof(nodeId));
697 
698     const bool isTextureExportNode = node.GetIsTextureExportNode();
699     data.write(reinterpret_cast<const char*>(&isTextureExportNode), sizeof(isTextureExportNode));
700 
701     if (node.GetType() == RSRenderNodeType::SURFACE_NODE) {
702         const auto& surfaceNode = reinterpret_cast<const RSSurfaceRenderNode&>(node);
703         const std::string name = surfaceNode.GetName();
704         uint32_t size = name.size();
705         data.write(reinterpret_cast<const char*>(&size), sizeof(size));
706         data.write(reinterpret_cast<const char*>(name.c_str()), size);
707 
708         const std::string bundleName = "";
709         size = bundleName.size();
710         data.write(reinterpret_cast<const char*>(&size), sizeof(size));
711         data.write(reinterpret_cast<const char*>(bundleName.c_str()), size);
712 
713         const RSSurfaceNodeType type = surfaceNode.GetSurfaceNodeType();
714         data.write(reinterpret_cast<const char*>(&type), sizeof(type));
715 
716         const uint8_t backgroundAlpha = surfaceNode.GetAbilityBgAlpha();
717         data.write(reinterpret_cast<const char*>(&backgroundAlpha), sizeof(backgroundAlpha));
718 
719         const uint8_t globalAlpha = surfaceNode.GetGlobalAlpha();
720         data.write(reinterpret_cast<const char*>(&globalAlpha), sizeof(globalAlpha));
721     }
722 
723     const float positionZ = node.GetRenderProperties().GetPositionZ();
724     data.write(reinterpret_cast<const char*>(&positionZ), sizeof(positionZ));
725 
726     const float pivotZ = node.GetRenderProperties().GetPivotZ();
727     data.write(reinterpret_cast<const char*>(&pivotZ), sizeof(pivotZ));
728 
729     const NodePriorityType priority = const_cast<RSRenderNode&>(node).GetPriority();
730     data.write(reinterpret_cast<const char*>(&priority), sizeof(priority));
731 
732     const bool isOnTree = node.IsOnTheTree();
733     data.write(reinterpret_cast<const char*>(&isOnTree), sizeof(isOnTree));
734 
735     if (fileVersion >= RSFILE_VERSION_RENDER_METRICS_ADDED) {
736         const uint8_t nodeGroupType = node.nodeGroupType_;
737         data.write(reinterpret_cast<const char*>(&nodeGroupType), sizeof(nodeGroupType));
738     }
739 
740     if (fileVersion >= RSFILE_VERSION_ISREPAINT_BOUNDARY) {
741         const bool isRepaintBoundary = node.IsRepaintBoundary();
742         data.write(reinterpret_cast<const char*>(&isRepaintBoundary), sizeof(isRepaintBoundary));
743     }
744 
745     MarshalNodeModifiers(node, data, fileVersion);
746 }
747 
MarshalRenderModifier(const ModifierNG::RSRenderModifier & modifier,std::stringstream & data)748 static void MarshalRenderModifier(const ModifierNG::RSRenderModifier& modifier, std::stringstream& data)
749 {
750     Parcel parcel;
751     parcel.SetMaxCapacity(GetParcelMaxCapacity());
752 
753     // Parcel Code - can be any, in our case I selected -1 to support already captured subtrees
754     parcel.WriteInt32(-1);
755     // MARSHAL PARCEL VERSION
756     if (!RSMarshallingHelper::MarshallingTransactionVer(parcel)) {
757         return;
758     }
759 
760     const_cast<ModifierNG::RSRenderModifier&>(modifier).Marshalling(parcel);
761     const size_t dataSize = parcel.GetDataSize();
762     data.write(reinterpret_cast<const char*>(&dataSize), sizeof(dataSize));
763     data.write(reinterpret_cast<const char*>(parcel.GetData()), dataSize);
764 
765     // Remove all file descriptors
766     binder_size_t* object = reinterpret_cast<binder_size_t*>(parcel.GetObjectOffsets());
767     size_t objectNum = parcel.GetOffsetsSize();
768     uintptr_t parcelData = parcel.GetData();
769 
770     const size_t maxObjectNum = INT_MAX;
771     if (!object || (objectNum > maxObjectNum)) {
772         return;
773     }
774 
775     for (size_t i = 0; i < objectNum; i++) {
776         const flat_binder_object* flat = reinterpret_cast<flat_binder_object*>(parcelData + object[i]);
777         if (!flat) {
778             return;
779         }
780         if (flat->hdr.type == BINDER_TYPE_FD && flat->handle > 0) {
781             ::close(flat->handle);
782         }
783     }
784 }
785 
MarshalDrawCmdModifiers(ModifierNG::RSRenderModifier & modifier,std::stringstream & data)786 static void MarshalDrawCmdModifiers(ModifierNG::RSRenderModifier& modifier, std::stringstream& data)
787 {
788     auto propertyType = ModifierNG::ModifierTypeConvertor::GetPropertyType(modifier.GetType());
789     auto oldCmdList = modifier.Getter<Drawing::DrawCmdListPtr>(propertyType, nullptr);
790     if (!oldCmdList) {
791         MarshalRenderModifier(modifier, data);
792         return;
793     }
794 
795     auto newCmdList = std::make_shared<Drawing::DrawCmdList>(
796         oldCmdList->GetWidth(), oldCmdList->GetHeight(), Drawing::DrawCmdList::UnmarshalMode::IMMEDIATE);
797     oldCmdList->ProfilerMarshallingDrawOps(newCmdList.get());
798     newCmdList->PatchTypefaceIds(oldCmdList);
799     modifier.Setter<Drawing::DrawCmdListPtr>(propertyType, newCmdList);
800     MarshalRenderModifier(modifier, data);
801     modifier.Setter<Drawing::DrawCmdListPtr>(propertyType, oldCmdList);
802 }
803 
MarshalNodeModifiers(const RSRenderNode & node,std::stringstream & data,uint32_t fileVersion)804 void RSProfiler::MarshalNodeModifiers(const RSRenderNode& node, std::stringstream& data, uint32_t fileVersion)
805 {
806     data.write(reinterpret_cast<const char*>(&node.instanceRootNodeId_), sizeof(node.instanceRootNodeId_));
807     data.write(reinterpret_cast<const char*>(&node.firstLevelNodeId_), sizeof(node.firstLevelNodeId_));
808 
809     uint32_t modifierNGCount = 0;
810     for (const auto& slot : node.GetAllModifiers()) {
811         for (auto& modifierNG : slot) {
812             if (!modifierNG || modifierNG->GetType() == ModifierNG::RSModifierType::PARTICLE_EFFECT) {
813                 continue;
814             }
815             modifierNGCount++;
816         }
817     }
818     data.write(reinterpret_cast<const char*>(&modifierNGCount), sizeof(modifierNGCount));
819     for (const auto& slot : node.GetAllModifiers()) {
820         for (auto& modifierNG : slot) {
821             if (!modifierNG || modifierNG->GetType() == ModifierNG::RSModifierType::PARTICLE_EFFECT) {
822                 continue;
823             }
824             if (modifierNG->IsCustom()) {
825                 MarshalDrawCmdModifiers(*modifierNG, data);
826             } else {
827                 MarshalRenderModifier(*modifierNG, data);
828             }
829         }
830     }
831 }
832 
CreateRenderSurfaceNode(RSContext & context,NodeId id,bool isTextureExportNode,std::stringstream & data)833 static std::string CreateRenderSurfaceNode(RSContext& context,
834                                            NodeId id,
835                                            bool isTextureExportNode,
836                                            std::stringstream& data)
837 {
838     constexpr uint32_t nameSizeMax = 4096;
839     uint32_t size = 0u;
840     data.read(reinterpret_cast<char*>(&size), sizeof(size));
841     if (size > nameSizeMax) {
842         return "CreateRenderSurfaceNode unmarshalling failed, file is damaged";
843     }
844 
845     std::string name;
846     name.resize(size, ' ');
847     data.read(reinterpret_cast<char*>(name.data()), size);
848 
849     data.read(reinterpret_cast<char*>(&size), sizeof(size));
850     if (size > nameSizeMax) {
851         return "CreateRenderSurfaceNode unmarshalling failed, file is damaged";
852     }
853     std::string bundleName;
854     bundleName.resize(size, ' ');
855     data.read(reinterpret_cast<char*>(bundleName.data()), size);
856 
857     RSSurfaceNodeType nodeType = RSSurfaceNodeType::DEFAULT;
858     data.read(reinterpret_cast<char*>(&nodeType), sizeof(nodeType));
859 
860     uint8_t backgroundAlpha = 0u;
861     data.read(reinterpret_cast<char*>(&backgroundAlpha), sizeof(backgroundAlpha));
862 
863     uint8_t globalAlpha = 0u;
864     data.read(reinterpret_cast<char*>(&globalAlpha), sizeof(globalAlpha));
865 
866     const RSSurfaceRenderNodeConfig config = { .id = id,
867         .name = name + "_",
868         .nodeType = nodeType,
869         .additionalData = nullptr,
870         .isTextureExportNode = isTextureExportNode,
871         .isSync = false };
872 
873     if (auto node = SurfaceNodeCommandHelper::CreateWithConfigInRS(config, context)) {
874         context.GetMutableNodeMap().RegisterRenderNode(node);
875         node->SetAbilityBGAlpha(backgroundAlpha);
876         node->SetGlobalAlpha(globalAlpha);
877     }
878     return "";
879 }
880 
UnmarshalNodes(RSContext & context,std::stringstream & data,uint32_t fileVersion)881 std::string RSProfiler::UnmarshalNodes(RSContext& context, std::stringstream& data, uint32_t fileVersion)
882 {
883     std::string errReason;
884 
885     uint32_t count = 0;
886     data.read(reinterpret_cast<char*>(&count), sizeof(count));
887     for (uint32_t i = 0; i < count; i++) {
888         errReason = UnmarshalNode(context, data, fileVersion);
889         if (errReason.size()) {
890             return errReason;
891         }
892     }
893 
894     data.read(reinterpret_cast<char*>(&count), sizeof(count));
895     for (uint32_t i = 0; i < count; i++) {
896         errReason = UnmarshalTree(context, data, fileVersion);
897         if (errReason.size()) {
898             return errReason;
899         }
900     }
901 
902     MarkReplayNodesDirty(context);
903     return "";
904 }
905 
MarkReplayNodesDirty(RSContext & context)906 void RSProfiler::MarkReplayNodesDirty(RSContext& context)
907 {
908     auto& nodeMap = context.GetMutableNodeMap();
909     nodeMap.TraversalNodes([](const std::shared_ptr<RSBaseRenderNode>& node) {
910         if (node == nullptr) {
911             return;
912         }
913         if (Utils::IsNodeIdPatched(node->GetId())) {
914             node->SetContentDirty();
915             node->SetDirty();
916         }
917     });
918 }
919 
UnmarshalNode(RSContext & context,std::stringstream & data,uint32_t fileVersion)920 std::string RSProfiler::UnmarshalNode(RSContext& context, std::stringstream& data, uint32_t fileVersion)
921 {
922     RSRenderNodeType nodeType = RSRenderNodeType::UNKNOW;
923     data.read(reinterpret_cast<char*>(&nodeType), sizeof(nodeType));
924 
925     NodeId nodeId = 0;
926     data.read(reinterpret_cast<char*>(&nodeId), sizeof(nodeId));
927     nodeId = Utils::PatchNodeId(nodeId);
928 
929     bool isTextureExportNode = false;
930     data.read(reinterpret_cast<char*>(&isTextureExportNode), sizeof(isTextureExportNode));
931 
932     if (data.eof()) {
933         return "UnmarshalNode failed, file is damaged";
934     }
935 
936     if (nodeType == RSRenderNodeType::RS_NODE) {
937         RootNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
938     } else if (nodeType == RSRenderNodeType::SCREEN_NODE) {
939         RootNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
940     } else if (nodeType == RSRenderNodeType::LOGICAL_DISPLAY_NODE) {
941         RootNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
942     } else if (nodeType == RSRenderNodeType::SURFACE_NODE) {
943         std::string errReason = CreateRenderSurfaceNode(context, nodeId, isTextureExportNode, data);
944         if (errReason.size()) {
945             return errReason;
946         }
947     } else if (nodeType == RSRenderNodeType::PROXY_NODE) {
948         ProxyNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
949     } else if (nodeType == RSRenderNodeType::CANVAS_NODE) {
950         RSCanvasNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
951     } else if (nodeType == RSRenderNodeType::EFFECT_NODE) {
952         EffectNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
953     } else if (nodeType == RSRenderNodeType::ROOT_NODE) {
954         RootNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
955     } else if (nodeType == RSRenderNodeType::CANVAS_DRAWING_NODE) {
956         RSCanvasDrawingNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
957     } else {
958         RootNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
959     }
960 
961     return UnmarshalNode(context, data, nodeId, fileVersion);
962 }
963 
UnmarshalNode(RSContext & context,std::stringstream & data,NodeId nodeId,uint32_t fileVersion)964 std::string RSProfiler::UnmarshalNode(RSContext& context, std::stringstream& data, NodeId nodeId, uint32_t fileVersion)
965 {
966     float positionZ = 0.0f;
967     data.read(reinterpret_cast<char*>(&positionZ), sizeof(positionZ));
968     float pivotZ = 0.0f;
969     data.read(reinterpret_cast<char*>(&pivotZ), sizeof(pivotZ));
970     NodePriorityType priority = NodePriorityType::MAIN_PRIORITY;
971     data.read(reinterpret_cast<char*>(&priority), sizeof(priority));
972     bool isOnTree = false;
973     data.read(reinterpret_cast<char*>(&isOnTree), sizeof(isOnTree));
974 
975     uint8_t nodeGroupType = 0;
976     if (fileVersion >= RSFILE_VERSION_RENDER_METRICS_ADDED) {
977         data.read(reinterpret_cast<char*>(&nodeGroupType), sizeof(nodeGroupType));
978     }
979 
980     bool isRepaintBoundary = false;
981     if (fileVersion >= RSFILE_VERSION_ISREPAINT_BOUNDARY) {
982         data.read(reinterpret_cast<char*>(&isRepaintBoundary), sizeof(isRepaintBoundary));
983     }
984 
985     if (auto node = context.GetMutableNodeMap().GetRenderNode(nodeId)) {
986         node->GetMutableRenderProperties().SetPositionZ(positionZ);
987         node->GetMutableRenderProperties().SetPivotZ(pivotZ);
988         node->SetPriority(priority);
989         node->nodeGroupType_ = nodeGroupType;
990 #ifdef SUBTREE_PARALLEL_ENABLE
991         node->MarkRepaintBoundary(isRepaintBoundary);
992 #endif
993         return UnmarshalNodeModifiers(*node, data, fileVersion);
994     }
995     return "";
996 }
997 
UnmarshalRenderModifier(std::stringstream & data,std::string & errReason)998 static std::shared_ptr<ModifierNG::RSRenderModifier> UnmarshalRenderModifier(
999     std::stringstream& data, std::string& errReason)
1000 {
1001     errReason = "";
1002 
1003     constexpr size_t bufferSizeMax = 50'000'000;
1004     size_t bufferSize = 0;
1005     data.read(reinterpret_cast<char*>(&bufferSize), sizeof(bufferSize));
1006     if (bufferSize > bufferSizeMax) {
1007         errReason = "UnmarshalRenderModifier failed, file is damaged";
1008         return nullptr;
1009     }
1010 
1011     std::vector<uint8_t> buffer;
1012     buffer.resize(bufferSize);
1013     data.read(reinterpret_cast<char*>(buffer.data()), buffer.size());
1014     if (data.eof()) {
1015         errReason = "UnmarshalRenderModifier failed, file is damaged";
1016         return nullptr;
1017     }
1018 
1019     uint8_t parcelMemory[sizeof(Parcel) + 1];
1020     auto* parcel = new (parcelMemory + 1) Parcel;
1021     parcel->SetMaxCapacity(GetParcelMaxCapacity());
1022     parcel->WriteBuffer(buffer.data(), buffer.size());
1023 
1024     int32_t versionPrefix = parcel->ReadInt32();
1025     if (versionPrefix == -1) {
1026         RSMarshallingHelper::UnmarshallingTransactionVer(*parcel);
1027     } else {
1028         parcel->RewindRead(0);
1029     }
1030 
1031     auto ptr = ModifierNG::RSRenderModifier::Unmarshalling(*parcel);
1032     if (!ptr) {
1033         constexpr size_t minBufferSize = 2;
1034         if (buffer.size() >= minBufferSize) {
1035             const auto typeModifier = *(reinterpret_cast<ModifierNG::RSModifierType *>(&buffer[0]));
1036             errReason = ModifierNG::RSModifierTypeString::GetModifierTypeString(typeModifier);
1037         } else {
1038             errReason = "RSRenderModifier buffer too short";
1039         }
1040         errReason += ", size=" + std::to_string(buffer.size());
1041     }
1042 
1043     return ptr;
1044 }
1045 
SetupCanvasDrawingRenderNode(RSCanvasDrawingRenderNode & node)1046 static void SetupCanvasDrawingRenderNode(RSCanvasDrawingRenderNode& node)
1047 {
1048     int32_t width = 0;
1049     int32_t height = 0;
1050     for (uint16_t type = 0; type < ModifierNG::MODIFIER_TYPE_COUNT; type++) {
1051         auto& slot = node.GetAllModifiers()[type];
1052         if (slot.empty()) {
1053             continue;
1054         }
1055         if (!slot[0]->IsCustom()) {
1056             continue;
1057         }
1058         for (const auto& modifier : slot) {
1059             const auto commandList = modifier ? modifier->GetPropertyDrawCmdList() : nullptr;
1060             if (commandList) {
1061                 width = std::max(width, commandList->GetWidth());
1062                 height = std::max(height, commandList->GetHeight());
1063             }
1064         }
1065     }
1066     node.ResetSurface(width, height);
1067 }
1068 
UnmarshalNodeModifiers(RSRenderNode & node,std::stringstream & data,uint32_t fileVersion)1069 std::string RSProfiler::UnmarshalNodeModifiers(RSRenderNode& node, std::stringstream& data, uint32_t fileVersion)
1070 {
1071     data.read(reinterpret_cast<char*>(&node.instanceRootNodeId_), sizeof(node.instanceRootNodeId_));
1072     node.instanceRootNodeId_ = Utils::PatchNodeId(node.instanceRootNodeId_);
1073 
1074     data.read(reinterpret_cast<char*>(&node.firstLevelNodeId_), sizeof(node.firstLevelNodeId_));
1075     node.firstLevelNodeId_ = Utils::PatchNodeId(node.firstLevelNodeId_);
1076 
1077     int32_t modifierCount = 0;
1078     data.read(reinterpret_cast<char*>(&modifierCount), sizeof(modifierCount));
1079     for (int32_t i = 0; i < modifierCount; i++) {
1080         std::string errModifierCode = "";
1081         auto ptr = UnmarshalRenderModifier(data, errModifierCode);
1082         if (!ptr) {
1083             RSProfiler::SendMessageBase("LOADERROR: Modifier format changed [" + errModifierCode + "]");
1084             continue;
1085         }
1086         node.AddModifier(ptr);
1087     }
1088 
1089     if (data.eof()) {
1090         return "UnmarshalNodeModifiers failed, file is damaged";
1091     }
1092 
1093     if (node.GetType() == RSRenderNodeType::CANVAS_DRAWING_NODE) {
1094         SetupCanvasDrawingRenderNode(static_cast<RSCanvasDrawingRenderNode&>(node));
1095     }
1096 
1097     node.ApplyModifiers();
1098     return "";
1099 }
1100 
UnmarshalTree(RSContext & context,std::stringstream & data,uint32_t fileVersion)1101 std::string RSProfiler::UnmarshalTree(RSContext& context, std::stringstream& data, uint32_t fileVersion)
1102 {
1103     const auto& map = context.GetMutableNodeMap();
1104 
1105     NodeId nodeId = 0;
1106     data.read(reinterpret_cast<char*>(&nodeId), sizeof(nodeId));
1107     nodeId = Utils::PatchNodeId(nodeId);
1108 
1109     uint32_t count = 0;
1110     data.read(reinterpret_cast<char*>(&count), sizeof(count));
1111 
1112     auto node = map.GetRenderNode(nodeId);
1113     if (!node) {
1114         return "Error nodeId was not found";
1115     }
1116     for (uint32_t i = 0; i < count; i++) {
1117         NodeId nodeId = 0;
1118         data.read(reinterpret_cast<char*>(&nodeId), sizeof(nodeId));
1119         if (node) {
1120             node->AddChild(map.GetRenderNode(Utils::PatchNodeId(nodeId)), i);
1121         }
1122         UnmarshalTree(context, data, fileVersion);
1123     }
1124     return "";
1125 }
1126 
DumpRenderProperties(const RSRenderNode & node)1127 std::string RSProfiler::DumpRenderProperties(const RSRenderNode& node)
1128 {
1129     return node.renderProperties_.Dump();
1130 }
1131 
DumpModifiers(const RSRenderNode & node)1132 std::string RSProfiler::DumpModifiers(const RSRenderNode& node)
1133 {
1134     std::string out;
1135     out += "<";
1136     for (uint16_t type = 0; type < ModifierNG::MODIFIER_TYPE_COUNT; type++) {
1137         auto& slot = node.GetAllModifiers()[type];
1138         if (slot.empty()) {
1139             continue;
1140         }
1141         if (!slot[0]->IsCustom()) {
1142             continue;
1143         }
1144         out += "(";
1145         out += std::to_string(type);
1146         out += ", ";
1147         for (auto& modifier : slot) {
1148             out += "[";
1149             const auto modifierId = modifier->GetId();
1150             out += std::to_string(Utils::ExtractPid(modifierId));
1151             out += "|";
1152             out += std::to_string(Utils::ExtractNodeId(modifierId));
1153             out += " type=";
1154             out += std::to_string(type);
1155             out += " [modifier dump is not implemented yet]";
1156             out += "]";
1157         }
1158         out += ")";
1159     }
1160     out += ">";
1161     return out;
1162 }
1163 
DumpSurfaceNode(const RSRenderNode & node)1164 std::string RSProfiler::DumpSurfaceNode(const RSRenderNode& node)
1165 {
1166     if (node.GetType() != RSRenderNodeType::SURFACE_NODE) {
1167         return "";
1168     }
1169 
1170     std::string out;
1171     const auto& surfaceNode = (static_cast<const RSSurfaceRenderNode&>(node));
1172     const auto parent = node.parent_.lock();
1173     out += ", Parent [" + (parent ? std::to_string(parent->GetId()) : "null") + "]";
1174     out += ", Name [" + surfaceNode.GetName() + "]";
1175     if (surfaceNode.GetRSSurfaceHandler()) {
1176         out += ", hasConsumer: " + std::to_string(surfaceNode.GetRSSurfaceHandler()->HasConsumer());
1177     }
1178     std::string contextAlpha = std::to_string(surfaceNode.contextAlpha_);
1179     std::string propertyAlpha = std::to_string(surfaceNode.GetRenderProperties().GetAlpha());
1180     out += ", Alpha: " + propertyAlpha + " (include ContextAlpha: " + contextAlpha + ")";
1181     out += ", Visible: " + std::to_string(surfaceNode.GetRenderProperties().GetVisible());
1182     out += ", " + surfaceNode.GetVisibleRegion().GetRegionInfo();
1183     out += ", OcclusionBg: " + std::to_string(surfaceNode.GetAbilityBgAlpha());
1184     out += ", Properties: " + node.GetRenderProperties().Dump();
1185     return out;
1186 }
1187 
1188 // RSAnimationManager
FilterAnimationForPlayback(RSAnimationManager & manager)1189 void RSProfiler::FilterAnimationForPlayback(RSAnimationManager& manager)
1190 {
1191     EraseIf(manager.animations_, [](const auto& pair) -> bool {
1192         if (!Utils::IsNodeIdPatched(pair.first)) {
1193             return false;
1194         }
1195         pair.second->Finish();
1196         pair.second->Detach();
1197         return true;
1198     });
1199 }
1200 
SetTransactionTimeCorrection(double replayStartTime,double recordStartTime)1201 void RSProfiler::SetTransactionTimeCorrection(double replayStartTime, double recordStartTime)
1202 {
1203     g_transactionTimeCorrection = static_cast<int64_t>((replayStartTime - recordStartTime) * NS_TO_S);
1204     g_replayStartTimeNano = replayStartTime * NS_TO_S;
1205 }
1206 
GetParcelCommandList()1207 std::string RSProfiler::GetParcelCommandList()
1208 {
1209     const std::lock_guard<std::mutex> guard(g_mutexCommandOffsets);
1210     if (g_parcelNumber2Offset.size()) {
1211         const auto it = g_parcelNumber2Offset.begin();
1212         std::stringstream stream(std::ios::in | std::ios::out | std::ios::binary);
1213         stream.write(reinterpret_cast<const char*>(&it->first), sizeof(it->first));
1214         stream.write(reinterpret_cast<const char*>(it->second.data()), it->second.size() * sizeof(uint32_t));
1215         g_parcelNumber2Offset.erase(it);
1216         return stream.str();
1217     }
1218     return "";
1219 }
1220 
PushOffset(std::vector<uint32_t> & commandOffsets,uint32_t offset)1221 void RSProfiler::PushOffset(std::vector<uint32_t>& commandOffsets, uint32_t offset)
1222 {
1223     if (!IsEnabled()) {
1224         return;
1225     }
1226     if (IsWriteMode()) {
1227         commandOffsets.push_back(offset);
1228     }
1229 }
1230 
TransactionUnmarshallingStart(const Parcel & parcel,uint32_t parcelNumber)1231 void RSProfiler::TransactionUnmarshallingStart(const Parcel& parcel, uint32_t parcelNumber)
1232 {
1233     std::stringstream stream(std::ios::in | std::ios::out | std::ios::binary);
1234     stream.write(reinterpret_cast<const char*>(&parcelNumber), sizeof(parcelNumber));
1235     SendRSLogBase(RSProfilerLogType::PARCEL_UNMARSHALLING_START, stream.str());
1236 }
1237 
PushOffsets(const Parcel & parcel,uint32_t parcelNumber,std::vector<uint32_t> & commandOffsets)1238 void RSProfiler::PushOffsets(const Parcel& parcel, uint32_t parcelNumber, std::vector<uint32_t>& commandOffsets)
1239 {
1240     if (!IsEnabled()) {
1241         return;
1242     }
1243     if (!parcelNumber) {
1244         return;
1245     }
1246     if (IsWriteMode()) {
1247         const std::lock_guard<std::mutex> guard(g_mutexCommandOffsets);
1248         g_parcelNumber2Offset[parcelNumber] = commandOffsets;
1249 
1250         std::stringstream stream(std::ios::in | std::ios::out | std::ios::binary);
1251         stream.write(reinterpret_cast<const char*>(&parcelNumber), sizeof(parcelNumber));
1252         stream.write(reinterpret_cast<const char*>(commandOffsets.data()), commandOffsets.size() * sizeof(uint32_t));
1253         SendRSLogBase(RSProfilerLogType::PARCEL_UNMARSHALLING_END, stream.str());
1254     }
1255 }
1256 
PatchCommand(const Parcel & parcel,RSCommand * command)1257 void RSProfiler::PatchCommand(const Parcel& parcel, RSCommand* command)
1258 {
1259     if (!IsEnabled()) {
1260         return;
1261     }
1262     if (command == nullptr) {
1263         return;
1264     }
1265 
1266     if (command && IsParcelMock(parcel)) {
1267         command->Patch(Utils::PatchNodeId);
1268     }
1269 
1270     if (IsWriteMode()) {
1271         g_commandCount++;
1272     }
1273 }
1274 
ExecuteCommand(const RSCommand * command)1275 void RSProfiler::ExecuteCommand(const RSCommand* command)
1276 {
1277     if (!IsEnabled()) {
1278         return;
1279     }
1280     if (!IsWriteMode() && !IsReadMode()) {
1281         return;
1282     }
1283     if (command == nullptr) {
1284         return;
1285     }
1286 
1287     g_commandExecuteCount++;
1288 }
1289 
PerfTreeFlatten(const std::shared_ptr<RSRenderNode> node,std::vector<std::pair<NodeId,uint32_t>> & nodeSet,std::unordered_map<NodeId,uint32_t> & mapNode2Count,uint32_t depth)1290 uint32_t RSProfiler::PerfTreeFlatten(const std::shared_ptr<RSRenderNode> node,
1291     std::vector<std::pair<NodeId, uint32_t>>& nodeSet,
1292     std::unordered_map<NodeId, uint32_t>& mapNode2Count, uint32_t depth)
1293 {
1294     if (!node) {
1295         return 0;
1296     }
1297 
1298     constexpr uint32_t depthToAnalyze = 10;
1299     uint32_t drawCmdListCount = CalcNodeCmdListCount(*node);
1300     if (node->GetSortedChildren()) {
1301         uint32_t valuableChildrenCount = 0;
1302         for (auto& child : *node->GetSortedChildren()) {
1303             if (child && child->GetType() != RSRenderNodeType::EFFECT_NODE && depth < depthToAnalyze) {
1304                 nodeSet.emplace_back(child->id_, depth + 1);
1305             }
1306         }
1307         for (auto& child : *node->GetSortedChildren()) {
1308             if (child) {
1309                 drawCmdListCount += PerfTreeFlatten(child, nodeSet, mapNode2Count, depth + 1);
1310                 valuableChildrenCount++;
1311             }
1312         }
1313     }
1314 
1315     if (drawCmdListCount > 0) {
1316         mapNode2Count[node->id_] = drawCmdListCount;
1317     }
1318     return drawCmdListCount;
1319 }
1320 
CalcNodeCmdListCount(RSRenderNode & node)1321 uint32_t RSProfiler::CalcNodeCmdListCount(RSRenderNode& node)
1322 {
1323     uint32_t nodeCmdListCount = 0;
1324     for (uint16_t type = 0; type < ModifierNG::MODIFIER_TYPE_COUNT; type++) {
1325         auto& slot = node.GetAllModifiers()[type];
1326         if (slot.empty()) {
1327             continue;
1328         }
1329         if (!slot[0]->IsCustom()) {
1330             continue;
1331         }
1332         for (auto& modifier : slot) {
1333             std::shared_ptr<RSRenderProperty<Drawing::DrawCmdListPtr>> propertyPtr = nullptr;
1334             if (modifier != nullptr) {
1335                 propertyPtr = std::static_pointer_cast<RSRenderProperty<Drawing::DrawCmdListPtr>>(
1336                     modifier->GetProperty(ModifierNG::ModifierTypeConvertor::GetPropertyType(modifier->GetType())));
1337             }
1338             auto propertyValue = propertyPtr ? propertyPtr->Get() : nullptr;
1339             if (propertyValue && propertyValue->GetOpItemSize() > 0) {
1340                 nodeCmdListCount = 1;
1341             }
1342         }
1343     }
1344     return nodeCmdListCount;
1345 }
1346 
MarshalDrawingImage(std::shared_ptr<Drawing::Image> & image,std::shared_ptr<Drawing::Data> & compressData)1347 void RSProfiler::MarshalDrawingImage(std::shared_ptr<Drawing::Image>& image,
1348     std::shared_ptr<Drawing::Data>& compressData)
1349 {
1350     if (IsEnabled() && !IsSharedMemoryEnabled()) {
1351         image = nullptr;
1352         compressData = nullptr;
1353     }
1354 }
1355 
EnableBetaRecord()1356 void RSProfiler::EnableBetaRecord()
1357 {
1358     RSSystemProperties::SetBetaRecordingMode(1);
1359 }
1360 
IsBetaRecordSavingTriggered()1361 bool RSProfiler::IsBetaRecordSavingTriggered()
1362 {
1363     constexpr uint32_t savingMode = 2u;
1364     return RSSystemProperties::GetBetaRecordingMode() == savingMode;
1365 }
1366 
IsBetaRecordEnabledWithMetrics()1367 bool RSProfiler::IsBetaRecordEnabledWithMetrics()
1368 {
1369     constexpr uint32_t metricsMode = 3u;
1370     return RSSystemProperties::GetBetaRecordingMode() == metricsMode;
1371 }
1372 
SetDrawingCanvasNodeRedraw(bool enable)1373 void RSProfiler::SetDrawingCanvasNodeRedraw(bool enable)
1374 {
1375     dcnRedraw_ = enable && IsEnabled();
1376 }
1377 
DrawingNodeAddClearOp(const std::shared_ptr<Drawing::DrawCmdList> & drawCmdList)1378 void RSProfiler::DrawingNodeAddClearOp(const std::shared_ptr<Drawing::DrawCmdList>& drawCmdList)
1379 {
1380     if (dcnRedraw_ || !drawCmdList) {
1381         return;
1382     }
1383     drawCmdList->ClearOp();
1384 }
1385 
SetRenderNodeKeepDrawCmd(bool enable)1386 void RSProfiler::SetRenderNodeKeepDrawCmd(bool enable)
1387 {
1388     renderNodeKeepDrawCmdList_ = enable && IsEnabled();
1389 }
1390 
KeepDrawCmd(bool & drawCmdListNeedSync)1391 void RSProfiler::KeepDrawCmd(bool& drawCmdListNeedSync)
1392 {
1393     drawCmdListNeedSync = !renderNodeKeepDrawCmdList_;
1394 }
1395 
NewAshmemDataCacheId()1396 static uint64_t NewAshmemDataCacheId()
1397 {
1398     static std::atomic_uint32_t id = 0u;
1399     return Utils::ComposeDataId(Utils::GetPid(), id++);
1400 }
1401 
CacheAshmemData(uint64_t id,const uint8_t * data,size_t size)1402 static void CacheAshmemData(uint64_t id, const uint8_t* data, size_t size)
1403 {
1404     if (RSProfiler::IsWriteMode() && data && (size > 0)) {
1405         Image ashmem;
1406         ashmem.data.insert(ashmem.data.end(), data, data + size);
1407         ImageCache::Add(id, std::move(ashmem));
1408     }
1409 }
1410 
GetCachedAshmemData(uint64_t id)1411 static const uint8_t* GetCachedAshmemData(uint64_t id)
1412 {
1413     const auto ashmem = RSProfiler::IsReadMode() ? ImageCache::Get(id) : nullptr;
1414     return ashmem ? ashmem->data.data() : nullptr;
1415 }
1416 
WriteParcelData(Parcel & parcel)1417 void RSProfiler::WriteParcelData(Parcel& parcel)
1418 {
1419     bool isClientEnabled = RSSystemProperties::GetProfilerEnabled();
1420     if (!parcel.WriteBool(isClientEnabled)) {
1421         HRPE("Unable to write is_client_enabled");
1422         return;
1423     }
1424 
1425     if (!isClientEnabled) {
1426         return;
1427     }
1428 
1429     if (!parcel.WriteUint64(NewAshmemDataCacheId())) {
1430         HRPE("Unable to write NewAshmemDataCacheId failed");
1431         return;
1432     }
1433 }
1434 
ReadParcelData(Parcel & parcel,size_t size,bool & isMalloc)1435 const void* RSProfiler::ReadParcelData(Parcel& parcel, size_t size, bool& isMalloc)
1436 {
1437     bool isClientEnabled = false;
1438     if (!parcel.ReadBool(isClientEnabled)) {
1439         HRPE("Unable to read is_client_enabled");
1440         return nullptr;
1441     }
1442     if (!isClientEnabled) {
1443         return RSMarshallingHelper::ReadFromAshmem(parcel, size, isMalloc);
1444     }
1445 
1446     const uint64_t id = parcel.ReadUint64();
1447     if (auto data = GetCachedAshmemData(id)) {
1448         constexpr uint32_t skipBytes = 24u;
1449         parcel.SkipBytes(skipBytes);
1450         isMalloc = false;
1451         return data;
1452     }
1453 
1454     auto data = RSMarshallingHelper::ReadFromAshmem(parcel, size, isMalloc);
1455     CacheAshmemData(id, reinterpret_cast<const uint8_t*>(data), size);
1456     return data;
1457 }
1458 
SkipParcelData(Parcel & parcel,size_t size)1459 bool RSProfiler::SkipParcelData(Parcel& parcel, size_t size)
1460 {
1461     bool isClientEnabled = false;
1462     if (!parcel.ReadBool(isClientEnabled)) {
1463         HRPE("RSProfiler::SkipParcelData read isClientEnabled failed");
1464         return false;
1465     }
1466     if (!isClientEnabled) {
1467         return false;
1468     }
1469 
1470     [[maybe_unused]] const uint64_t id = parcel.ReadUint64();
1471 
1472     if (IsReadMode()) {
1473         constexpr uint32_t skipBytes = 24u;
1474         parcel.SkipBytes(skipBytes);
1475         return true;
1476     }
1477 
1478     return false;
1479 }
1480 
GetNodeDepth(const std::shared_ptr<RSRenderNode> node)1481 uint32_t RSProfiler::GetNodeDepth(const std::shared_ptr<RSRenderNode> node)
1482 {
1483     uint32_t depth = 0;
1484     for (auto curNode = node; curNode != nullptr; depth++) {
1485         curNode = curNode ? curNode->GetParent().lock() : nullptr;
1486     }
1487     return depth;
1488 }
1489 
ReceiveMessageBase()1490 std::string RSProfiler::ReceiveMessageBase()
1491 {
1492     const std::lock_guard<std::mutex> guard(g_msgBaseMutex);
1493     if (g_msgBaseList.empty()) {
1494         return "";
1495     }
1496     std::string value = g_msgBaseList.front();
1497     g_msgBaseList.pop();
1498     return value;
1499 }
1500 
SendMessageBase(const std::string & msg)1501 void RSProfiler::SendMessageBase(const std::string& msg)
1502 {
1503     const std::lock_guard<std::mutex> guard(g_msgBaseMutex);
1504     g_msgBaseList.push(msg);
1505 }
1506 
AnimeGetStartTimes()1507 std::unordered_map<AnimationId, std::vector<int64_t>>& RSProfiler::AnimeGetStartTimes()
1508 {
1509     return g_animeStartMap;
1510 }
1511 
ReplayFixTrIndex(uint64_t curIndex,uint64_t & lastIndex)1512 void RSProfiler::ReplayFixTrIndex(uint64_t curIndex, uint64_t& lastIndex)
1513 {
1514     if (!IsEnabled()) {
1515         return;
1516     }
1517     if (IsReadMode()) {
1518         if (lastIndex == 0) {
1519             lastIndex = curIndex - 1;
1520         }
1521     }
1522 }
1523 
AnimeSetStartTime(AnimationId id,int64_t nanoTime)1524 int64_t RSProfiler::AnimeSetStartTime(AnimationId id, int64_t nanoTime)
1525 {
1526     if (!IsEnabled()) {
1527         return nanoTime;
1528     }
1529 
1530     if (IsReadMode()) {
1531         if (!g_animeStartMap.count(id)) {
1532             return nanoTime;
1533         }
1534         int64_t minDt = INT64_MAX, minTime = nanoTime - g_replayStartTimeNano;
1535         for (const auto recordedTime : g_animeStartMap[id]) {
1536             int64_t dt = abs(recordedTime - (nanoTime - g_replayStartTimeNano));
1537             if (dt < minDt) {
1538                 minDt = dt;
1539                 minTime = recordedTime;
1540             }
1541         }
1542         return minTime + g_replayStartTimeNano;
1543     } else if (IsWriteMode()) {
1544         if (g_animeStartMap.count(id)) {
1545             g_animeStartMap[Utils::PatchNodeId(id)].push_back(nanoTime);
1546         } else {
1547             std::vector<int64_t> list;
1548             list.push_back(nanoTime);
1549             g_animeStartMap.insert({ Utils::PatchNodeId(id), list });
1550         }
1551     }
1552 
1553     return nanoTime;
1554 }
1555 
ProcessAddChild(RSRenderNode * parent,RSRenderNode::SharedPtr child,int index)1556 bool RSProfiler::ProcessAddChild(RSRenderNode* parent, RSRenderNode::SharedPtr child, int index)
1557 {
1558     if (!parent || !child || !IsEnabled()) {
1559         return false;
1560     }
1561     if (!IsReadMode()) {
1562         return false;
1563     }
1564 
1565     if (parent->GetType() == RSRenderNodeType::SCREEN_NODE &&
1566         ! (child->GetId() & Utils::ComposeNodeId(Utils::GetMockPid(0), 0))) {
1567         // BLOCK LOCK-SCREEN ATTACH TO SCREEN
1568         g_childOfDisplayNodesPostponed.clear();
1569         g_childOfDisplayNodesPostponed.emplace_back(child);
1570         return true;
1571     }
1572     return false;
1573 }
1574 
GetChildOfDisplayNodesPostponed()1575 std::vector<RSRenderNode::WeakPtr>& RSProfiler::GetChildOfDisplayNodesPostponed()
1576 {
1577     return g_childOfDisplayNodesPostponed;
1578 }
1579 
RequestRecordAbort()1580 void RSProfiler::RequestRecordAbort()
1581 {
1582     recordAbortRequested_ = true;
1583 }
1584 
IsRecordAbortRequested()1585 bool RSProfiler::IsRecordAbortRequested()
1586 {
1587     return recordAbortRequested_;
1588 }
1589 
BaseSetPlaybackSpeed(double speed)1590 bool RSProfiler::BaseSetPlaybackSpeed(double speed)
1591 {
1592     float invSpeed = 1.0f;
1593     if (speed <= .0f) {
1594         return false;
1595     } else {
1596         invSpeed /= speed > 0.0f ? speed : 1.0f;
1597     }
1598 
1599     if (IsReadMode()) {
1600         if (Utils::Now() >= g_pauseAfterTime && g_pauseAfterTime > 0) {
1601             // paused can change speed but need adjust start time then
1602             int64_t curTime = static_cast<int64_t>(g_pauseAfterTime) - g_pauseCumulativeTime - g_replayStartTimeNano;
1603             g_pauseCumulativeTime = static_cast<int64_t>(g_pauseAfterTime) - g_replayStartTimeNano -
1604                     curTime * g_replaySpeed * invSpeed;
1605             g_replaySpeed = speed;
1606             return true;
1607         }
1608         // change of speed when replay in progress is not possible
1609         return false;
1610     }
1611     g_replaySpeed = speed;
1612     return true;
1613 }
1614 
BaseGetPlaybackSpeed()1615 double RSProfiler::BaseGetPlaybackSpeed()
1616 {
1617     return g_replaySpeed;
1618 }
1619 
MarshalSubTreeLo(RSContext & context,std::stringstream & data,const RSRenderNode & node,uint32_t fileVersion)1620 void RSProfiler::MarshalSubTreeLo(RSContext& context, std::stringstream& data,
1621     const RSRenderNode& node, uint32_t fileVersion)
1622 {
1623     NodeId nodeId = node.GetId();
1624     data.write(reinterpret_cast<const char*>(&nodeId), sizeof(nodeId));
1625 
1626     MarshalNode(node, data, fileVersion);
1627 
1628     const uint32_t count = node.children_.size();
1629     data.write(reinterpret_cast<const char*>(&count), sizeof(count));
1630     for (const auto& child : node.children_) {
1631         if (auto childNode = child.lock().get()) {
1632             MarshalSubTreeLo(context, data, *childNode, fileVersion);
1633         }
1634     }
1635 }
1636 
UnmarshalSubTreeLo(RSContext & context,std::stringstream & data,RSRenderNode & attachNode,uint32_t fileVersion)1637 std::string RSProfiler::UnmarshalSubTreeLo(RSContext& context, std::stringstream& data,
1638     RSRenderNode& attachNode, uint32_t fileVersion)
1639 {
1640     NodeId nodeId;
1641     data.read(reinterpret_cast<char*>(&nodeId), sizeof(nodeId));
1642 
1643     std::string errorReason = UnmarshalNode(context, data, fileVersion);
1644     if (errorReason.size()) {
1645         return errorReason;
1646     }
1647 
1648     auto node = context.GetMutableNodeMap().GetRenderNode(Utils::PatchNodeId(nodeId));
1649     if (!node) {
1650         return "Failed to create node";
1651     }
1652 
1653     attachNode.AddChild(node);
1654 
1655     uint32_t childCount;
1656     data.read(reinterpret_cast<char*>(&childCount), sizeof(childCount));
1657     for (uint32_t i = 0; i < childCount; i++) {
1658         errorReason = UnmarshalSubTreeLo(context, data, *node, fileVersion);
1659         if (errorReason.size()) {
1660             return errorReason;
1661         }
1662     }
1663     return errorReason;
1664 }
1665 
GetTextureRecordType()1666 TextureRecordType RSProfiler::GetTextureRecordType()
1667 {
1668     if (IsBetaRecordEnabled()) {
1669         return TextureRecordType::ONE_PIXEL;
1670     }
1671     return g_textureRecordType;
1672 }
1673 
SetTextureRecordType(TextureRecordType type)1674 void RSProfiler::SetTextureRecordType(TextureRecordType type)
1675 {
1676     g_textureRecordType = type;
1677 }
1678 
IfNeedToSkipDuringReplay(Parcel & parcel,uint32_t skipBytes)1679 bool RSProfiler::IfNeedToSkipDuringReplay(Parcel& parcel, uint32_t skipBytes)
1680 {
1681     if (!IsEnabled()) {
1682         return false;
1683     }
1684     if (!IsParcelMock(parcel)) {
1685         return false;
1686     }
1687     if (IsReadEmulationMode() || IsReadMode()) {
1688         parcel.SkipBytes(skipBytes);
1689         return true;
1690     }
1691     return false;
1692 }
1693 
SurfaceOnDrawMatchOptimize(bool & useNodeMatchOptimize)1694 void RSProfiler::SurfaceOnDrawMatchOptimize(bool& useNodeMatchOptimize)
1695 {
1696     if (!IsEnabled()) {
1697         return;
1698     }
1699     if (IsReadEmulationMode() || IsReadMode()) {
1700         useNodeMatchOptimize = true;
1701     }
1702 }
1703 
MetricRenderNodeInc(bool isOnTree)1704 void RSProfiler::MetricRenderNodeInc(bool isOnTree)
1705 {
1706     if (!IsEnabled() || !IsWriteMode()) {
1707         return;
1708     }
1709     if (isOnTree) {
1710         GetCustomMetrics().AddInt(RSPROFILER_METRIC_ONTREE_NODE_COUNT, 1);
1711     } else {
1712         GetCustomMetrics().AddInt(RSPROFILER_METRIC_OFFTREE_NODE_COUNT, 1);
1713     }
1714 }
1715 
MetricRenderNodeDec(bool isOnTree)1716 void RSProfiler::MetricRenderNodeDec(bool isOnTree)
1717 {
1718     if (!IsEnabled() || !IsWriteMode()) {
1719         return;
1720     }
1721     if (isOnTree) {
1722         GetCustomMetrics().SubInt(RSPROFILER_METRIC_ONTREE_NODE_COUNT, 1);
1723     } else {
1724         GetCustomMetrics().SubInt(RSPROFILER_METRIC_OFFTREE_NODE_COUNT, 1);
1725     }
1726 }
1727 
MetricRenderNodeChange(bool isOnTree)1728 void RSProfiler::MetricRenderNodeChange(bool isOnTree)
1729 {
1730     if (!IsEnabled() || !IsWriteMode()) {
1731         return;
1732     }
1733     if (isOnTree) {
1734         GetCustomMetrics().AddInt(RSPROFILER_METRIC_ONTREE_NODE_COUNT, 1);
1735         GetCustomMetrics().SubInt(RSPROFILER_METRIC_OFFTREE_NODE_COUNT, 1);
1736     } else {
1737         GetCustomMetrics().AddInt(RSPROFILER_METRIC_OFFTREE_NODE_COUNT, 1);
1738         GetCustomMetrics().SubInt(RSPROFILER_METRIC_ONTREE_NODE_COUNT, 1);
1739     }
1740 }
1741 
MetricRenderNodeInit(RSContext * context)1742 void RSProfiler::MetricRenderNodeInit(RSContext* context)
1743 {
1744     if (!context) {
1745         return;
1746     }
1747     GetCustomMetrics().SetZero(RSPROFILER_METRIC_ONTREE_NODE_COUNT);
1748     GetCustomMetrics().SetZero(RSPROFILER_METRIC_OFFTREE_NODE_COUNT);
1749     auto globalRootNodeId = context->GetGlobalRootRenderNode()->GetId();
1750     auto& nodeMap = context->GetMutableNodeMap();
1751     nodeMap.TraversalNodes([globalRootNodeId](const std::shared_ptr<RSBaseRenderNode>& node) {
1752         if (node == nullptr) {
1753             return;
1754         }
1755         auto parentPtr = node->GetParent().lock();
1756         for (; parentPtr && parentPtr->GetId() != globalRootNodeId; parentPtr = parentPtr->GetParent().lock())
1757             ;
1758         if (parentPtr != nullptr) {
1759             GetCustomMetrics().AddInt(RSPROFILER_METRIC_ONTREE_NODE_COUNT, 1);
1760         } else {
1761             GetCustomMetrics().AddInt(RSPROFILER_METRIC_OFFTREE_NODE_COUNT, 1);
1762         }
1763     });
1764 }
1765 
RSLogOutput(RSProfilerLogType type,const char * format,va_list argptr)1766 void RSProfiler::RSLogOutput(RSProfilerLogType type, const char* format, va_list argptr)
1767 {
1768     if (!IsEnabled() || !(IsWriteMode() || IsReadEmulationMode())) {
1769         return;
1770     }
1771 
1772     // no access to vsnprintf_s_p in inner api of hilog - have to write naive code myself
1773     constexpr int maxSize = 1024;
1774     char format2[maxSize] = {0}; // zero ending always present
1775     const char* ptr1 = format;
1776     char* ptr2 = format2;
1777     const auto effectiveSize = maxSize - 3; // max 3 chars can be added in one iteration
1778     constexpr int publicLen = 8; // publicLen = strlen("{public}");
1779     for (; *ptr1 && ptr2 - format2 < effectiveSize && ptr1 - format < effectiveSize - publicLen;) {
1780         if (*ptr1 == '%') {
1781             if (*(ptr1 + 1) == '%') {
1782                 // %% translates to %%
1783                 *ptr2++ = *ptr1++;
1784                 *ptr2++ = *ptr1++;
1785             } else if (!memcmp(ptr1 + 1, "{public}", publicLen)) {
1786                 // %{public} translates to %
1787                 *ptr2++ = *ptr1++;
1788                 ptr1 += publicLen;
1789             } else {
1790                 // abcd%{private} translates to abcd{private} - all subsequent vars are skipped
1791                 strcat_s(ptr2, effectiveSize - (ptr2 - format2), "{private}");
1792                 ptr2 = format2 + strlen(format2);
1793                 break;
1794             }
1795         } else {
1796             // other symbols are just copied
1797             *ptr2++ = *ptr1++;
1798         }
1799     }
1800     *ptr2++ = 0;
1801 
1802     char outStr[maxSize] = {0};
1803     if (vsprintf_s(outStr, sizeof(outStr), format2, argptr) > 0) {
1804         SendRSLogBase(type, std::string(outStr));
1805     }
1806 }
1807 
ReceiveRSLogBase()1808 RSProfilerLogMsg RSProfiler::ReceiveRSLogBase()
1809 {
1810     const std::lock_guard<std::mutex> guard(g_rsLogListMutex);
1811     if (g_rsLogList.empty()) {
1812         return RSProfilerLogMsg();
1813     }
1814     auto value = g_rsLogList.front();
1815     g_rsLogList.pop();
1816     return value;
1817 }
1818 
SendRSLogBase(RSProfilerLogType type,const std::string & msg)1819 void RSProfiler::SendRSLogBase(RSProfilerLogType type, const std::string& msg)
1820 {
1821     if (IsReadEmulationMode()) {
1822         if (type == RSProfilerLogType::WARNING) {
1823             RSProfiler::SendMessageBase("RS_LOGW: " + msg);
1824         } else if (type == RSProfilerLogType::ERROR) {
1825             RSProfiler::SendMessageBase("RS_LOGE: " + msg);
1826         }
1827     } else {
1828         const std::lock_guard<std::mutex> guard(g_rsLogListMutex);
1829         g_rsLogList.push(RSProfilerLogMsg(type, Utils::Now(), msg));
1830     }
1831 }
1832 
ResetCustomMetrics()1833 void RSProfiler::ResetCustomMetrics()
1834 {
1835     RSProfilerCustomMetrics& customMetrics = GetCustomMetrics();
1836     customMetrics.Reset();
1837 }
1838 
GetCustomMetrics()1839 RSProfilerCustomMetrics& RSProfiler::GetCustomMetrics()
1840 {
1841     static RSProfilerCustomMetrics s_customMetrics;
1842     return s_customMetrics;
1843 }
1844 
IsRecordingMode()1845 bool RSProfiler::IsRecordingMode()
1846 {
1847     return IsEnabled() && IsWriteMode();
1848 }
1849 
1850 } // namespace OHOS::Rosen
1851