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 "sys_binder.h"
27 #include "message_parcel.h"
28 #include "rs_profiler.h"
29 #include "rs_profiler_cache.h"
30 #include "rs_profiler_network.h"
31 #include "rs_profiler_utils.h"
32 #include "rs_profiler_file.h"
33 #include "rs_profiler_log.h"
34 
35 #include "animation/rs_animation_manager.h"
36 #include "command/rs_base_node_command.h"
37 #include "command/rs_canvas_drawing_node_command.h"
38 #include "command/rs_canvas_node_command.h"
39 #include "command/rs_effect_node_command.h"
40 #include "command/rs_proxy_node_command.h"
41 #include "command/rs_root_node_command.h"
42 #include "command/rs_surface_node_command.h"
43 #include "common/rs_common_def.h"
44 #include "pipeline/rs_display_render_node.h"
45 #include "pipeline/rs_surface_render_node.h"
46 #include "transaction/rs_ashmem_helper.h"
47 
48 namespace OHOS::Rosen {
49 
50 static Mode g_mode;
51 static std::vector<pid_t> g_pids;
52 static pid_t g_pid = 0;
53 static NodeId g_parentNode = 0;
54 static std::atomic<uint32_t> g_commandCount = 0;        // UNMARSHALLING RSCOMMAND COUNT
55 static std::atomic<uint32_t> g_commandExecuteCount = 0; // EXECUTE RSCOMMAND COUNT
56 constexpr uint32_t COMMAND_PARSE_LIST_COUNT = 1024;
57 constexpr uint32_t COMMAND_PARSE_LIST_SIZE = COMMAND_PARSE_LIST_COUNT * 2 + 5;
58 
59 static std::mutex g_msgBaseMutex;
60 static std::queue<std::string> g_msgBaseList;
61 
62 #pragma pack(push, 1)
63 struct PacketParsedCommandList {
64     double packetTime;
65     uint32_t packetSize;
66     uint16_t cmdCount;
67     uint32_t cmdCode[COMMAND_PARSE_LIST_SIZE];
68 };
69 #pragma pack(pop)
70 
71 static thread_local PacketParsedCommandList g_commandParseBuffer;
72 constexpr uint32_t COMMAND_LOOP_SIZE = 32;
73 static PacketParsedCommandList g_commandLoop[COMMAND_LOOP_SIZE];
74 static std::atomic<uint32_t> g_commandLoopIndexStart = 0;
75 static std::atomic<uint32_t> g_commandLoopIndexEnd = 0;
76 
77 static uint64_t g_pauseAfterTime = 0;
78 static uint64_t g_pauseCumulativeTime = 0;
79 static int64_t g_transactionTimeCorrection = 0;
80 static int64_t g_replayStartTimeNano = 0.0;
81 
82 static const size_t PARCEL_MAX_CAPACITY = 234 * 1024 * 1024;
83 
84 static std::unordered_map<AnimationId, std::vector<int64_t>> g_animeStartMap;
85 
86 bool RSProfiler::testing_ = false;
87 bool RSProfiler::enabled_ = RSSystemProperties::GetProfilerEnabled();
88 bool RSProfiler::betaRecordingEnabled_ = RSSystemProperties::GetBetaRecordingMode() != 0;
89 int8_t RSProfiler::signalFlagChanged_ = 0;
90 std::atomic_bool RSProfiler::dcnRedraw_ = false;
91 
GetParcelMaxCapacity()92 constexpr size_t GetParcelMaxCapacity()
93 {
94     return PARCEL_MAX_CAPACITY;
95 }
96 
IsEnabled()97 bool RSProfiler::IsEnabled()
98 {
99     return enabled_ || testing_;
100 }
101 
IsBetaRecordEnabled()102 bool RSProfiler::IsBetaRecordEnabled()
103 {
104     return betaRecordingEnabled_;
105 }
106 
GetCommandCount()107 uint32_t RSProfiler::GetCommandCount()
108 {
109     const uint32_t count = g_commandCount;
110     g_commandCount = 0;
111     return count;
112 }
113 
GetCommandExecuteCount()114 uint32_t RSProfiler::GetCommandExecuteCount()
115 {
116     const uint32_t count = g_commandExecuteCount;
117     g_commandExecuteCount = 0;
118     return count;
119 }
120 
EnableSharedMemory()121 void RSProfiler::EnableSharedMemory()
122 {
123     RSMarshallingHelper::EndNoSharedMem();
124 }
125 
DisableSharedMemory()126 void RSProfiler::DisableSharedMemory()
127 {
128     RSMarshallingHelper::BeginNoSharedMem(std::this_thread::get_id());
129 }
130 
IsSharedMemoryEnabled()131 bool RSProfiler::IsSharedMemoryEnabled()
132 {
133     return RSMarshallingHelper::GetUseSharedMem(std::this_thread::get_id());
134 }
135 
IsParcelMock(const Parcel& parcel)136 bool RSProfiler::IsParcelMock(const Parcel& parcel)
137 {
138     // gcc C++ optimization error (?): this is not working without volatile
139     const volatile auto address = reinterpret_cast<uint64_t>(&parcel);
140     return ((address & 1u) != 0);
141 }
142 
CopyParcel(const MessageParcel& parcel)143 std::shared_ptr<MessageParcel> RSProfiler::CopyParcel(const MessageParcel& parcel)
144 {
145     if (!IsEnabled()) {
146         return std::make_shared<MessageParcel>();
147     }
148 
149     if (IsParcelMock(parcel)) {
150         auto* buffer = new uint8_t[sizeof(MessageParcel) + 1];
151         auto* mpPtr = new (buffer + 1) MessageParcel;
152         return std::shared_ptr<MessageParcel>(mpPtr, [](MessageParcel* ptr) {
153             ptr->~MessageParcel();
154             auto* allocPtr = reinterpret_cast<uint8_t*>(ptr);
155             allocPtr--;
156             delete allocPtr;
157         });
158     }
159 
160     return std::make_shared<MessageParcel>();
161 }
162 
PatchPlainNodeId(const Parcel& parcel, NodeId id)163 NodeId RSProfiler::PatchPlainNodeId(const Parcel& parcel, NodeId id)
164 {
165     if (!IsEnabled()) {
166         return id;
167     }
168 
169     if ((g_mode != Mode::READ && g_mode != Mode::READ_EMUL) || !IsParcelMock(parcel)) {
170         return id;
171     }
172 
173     return Utils::PatchNodeId(id);
174 }
175 
PatchTypefaceId(const Parcel& parcel, std::shared_ptr<Drawing::DrawCmdList>& val)176 void RSProfiler::PatchTypefaceId(const Parcel& parcel, std::shared_ptr<Drawing::DrawCmdList>& val)
177 {
178     if (!val || !IsEnabled()) {
179         return;
180     }
181 
182     if (g_mode == Mode::READ_EMUL) {
183         val->PatchTypefaceIds();
184     } else if (g_mode == Mode::READ) {
185         if (IsParcelMock(parcel)) {
186             val->PatchTypefaceIds();
187         }
188     }
189 }
190 
PatchPlainPid(const Parcel& parcel, pid_t pid)191 pid_t RSProfiler::PatchPlainPid(const Parcel& parcel, pid_t pid)
192 {
193     if (!IsEnabled()) {
194         return pid;
195     }
196 
197     if ((g_mode != Mode::READ && g_mode != Mode::READ_EMUL) || !IsParcelMock(parcel)) {
198         return pid;
199     }
200 
201     return Utils::GetMockPid(pid);
202 }
203 
SetMode(Mode mode)204 void RSProfiler::SetMode(Mode mode)
205 {
206     g_mode = mode;
207     if (g_mode == Mode::NONE) {
208         g_pauseAfterTime = 0;
209         g_pauseCumulativeTime = 0;
210     }
211 }
212 
GetMode()213 Mode RSProfiler::GetMode()
214 {
215     return g_mode;
216 }
217 
SetSubstitutingPid(const std::vector<pid_t>& pids, pid_t pid, NodeId parent)218 void RSProfiler::SetSubstitutingPid(const std::vector<pid_t>& pids, pid_t pid, NodeId parent)
219 {
220     g_pids = pids;
221     g_pid = pid;
222     g_parentNode = parent;
223 }
224 
GetParentNode()225 NodeId RSProfiler::GetParentNode()
226 {
227     return g_parentNode;
228 }
229 
GetPids()230 const std::vector<pid_t>& RSProfiler::GetPids()
231 {
232     return g_pids;
233 }
234 
GetSubstitutingPid()235 pid_t RSProfiler::GetSubstitutingPid()
236 {
237     return g_pid;
238 }
239 
PatchTime(uint64_t time)240 uint64_t RSProfiler::PatchTime(uint64_t time)
241 {
242     if (!IsEnabled()) {
243         return time;
244     }
245     if (g_mode != Mode::READ && g_mode != Mode::READ_EMUL) {
246         return time;
247     }
248     if (time == 0.0) {
249         return 0.0;
250     }
251     if (time >= g_pauseAfterTime && g_pauseAfterTime > 0) {
252         return g_pauseAfterTime - g_pauseCumulativeTime;
253     }
254     return time - g_pauseCumulativeTime;
255 }
256 
PatchTransactionTime(const Parcel& parcel, uint64_t time)257 uint64_t RSProfiler::PatchTransactionTime(const Parcel& parcel, uint64_t time)
258 {
259     if (!IsEnabled()) {
260         return time;
261     }
262 
263     if (g_mode == Mode::WRITE) {
264         g_commandParseBuffer.packetTime = Utils::ToSeconds(time);
265         g_commandParseBuffer.packetSize = parcel.GetDataSize();
266         uint32_t index = g_commandLoopIndexEnd++;
267         index %= COMMAND_LOOP_SIZE;
268         g_commandLoop[index] = g_commandParseBuffer;
269         g_commandParseBuffer.cmdCount = 0;
270     }
271 
272     if (g_mode != Mode::READ) {
273         return time;
274     }
275     if (time == 0.0) {
276         return 0.0;
277     }
278     if (!IsParcelMock(parcel)) {
279         return time;
280     }
281 
282     return PatchTime(time + g_transactionTimeCorrection);
283 }
284 
TimePauseAt(uint64_t curTime, uint64_t newPauseAfterTime)285 void RSProfiler::TimePauseAt(uint64_t curTime, uint64_t newPauseAfterTime)
286 {
287     if (g_pauseAfterTime > 0) {
288         if (curTime > g_pauseAfterTime) {
289             g_pauseCumulativeTime += curTime - g_pauseAfterTime;
290         }
291     }
292     g_pauseAfterTime = newPauseAfterTime;
293 }
294 
TimePauseResume(uint64_t curTime)295 void RSProfiler::TimePauseResume(uint64_t curTime)
296 {
297     if (g_pauseAfterTime > 0) {
298         if (curTime > g_pauseAfterTime) {
299             g_pauseCumulativeTime += curTime - g_pauseAfterTime;
300         }
301     }
302     g_pauseAfterTime = 0;
303 }
304 
TimePauseClear()305 void RSProfiler::TimePauseClear()
306 {
307     g_pauseCumulativeTime = 0;
308     g_pauseAfterTime = 0;
309 }
310 
TimePauseGet()311 uint64_t RSProfiler::TimePauseGet()
312 {
313     return g_pauseAfterTime;
314 }
315 
GetDisplayNode(const RSContext& context)316 std::shared_ptr<RSDisplayRenderNode> RSProfiler::GetDisplayNode(const RSContext& context)
317 {
318     const std::shared_ptr<RSBaseRenderNode>& root = context.GetGlobalRootRenderNode();
319     // without these checks device might get stuck on startup
320     if (!root || (root->GetChildrenCount() != 1)) {
321         return nullptr;
322     }
323 
324     return RSBaseRenderNode::ReinterpretCast<RSDisplayRenderNode>(root->GetSortedChildren()->front());
325 }
326 
GetScreenRect(const RSContext& context)327 Vector4f RSProfiler::GetScreenRect(const RSContext& context)
328 {
329     std::shared_ptr<RSDisplayRenderNode> node = GetDisplayNode(context);
330     if (!node) {
331         return {};
332     }
333 
334     const RectI rect = node->GetDirtyManager()->GetSurfaceRect();
335     return { rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom() };
336 }
337 
FilterForPlayback(RSContext& context, pid_t pid)338 void RSProfiler::FilterForPlayback(RSContext& context, pid_t pid)
339 {
340     auto& map = context.GetMutableNodeMap();
341 
342     auto canBeRemoved = [](NodeId node, pid_t pid) -> bool {
343         return (ExtractPid(node) == pid) && (Utils::ExtractNodeId(node) != 1);
344     };
345 
346     // remove all nodes belong to given pid (by matching higher 32 bits of node id)
347     EraseIf(map.renderNodeMap_, [pid, canBeRemoved](const auto& pair) -> bool {
348         if (canBeRemoved(pair.first, pid) == false) {
349             return false;
350         }
351         // remove node from tree
352         pair.second->RemoveFromTree(false);
353         return true;
354     });
355 
356     EraseIf(
357         map.surfaceNodeMap_, [pid, canBeRemoved](const auto& pair) -> bool { return canBeRemoved(pair.first, pid); });
358 
359     EraseIf(map.residentSurfaceNodeMap_,
360         [pid, canBeRemoved](const auto& pair) -> bool { return canBeRemoved(pair.first, pid); });
361 
362     EraseIf(
363         map.displayNodeMap_, [pid, canBeRemoved](const auto& pair) -> bool { return canBeRemoved(pair.first, pid); });
364 
365     if (auto fallbackNode = map.GetAnimationFallbackNode()) {
366         fallbackNode->GetAnimationManager().FilterAnimationByPid(pid);
367     }
368 }
369 
FilterMockNode(RSContext& context)370 void RSProfiler::FilterMockNode(RSContext& context)
371 {
372     std::unordered_set<pid_t> pidSet;
373 
374     auto& nodeMap = context.GetMutableNodeMap();
375     nodeMap.TraversalNodes([&pidSet](const std::shared_ptr<RSBaseRenderNode>& node) {
376         if (node == nullptr) {
377             return;
378         }
379         if (Utils::IsNodeIdPatched(node->GetId())) {
380             pidSet.insert(Utils::ExtractPid(node->GetId()));
381         }
382     });
383 
384     for (auto pid : pidSet) {
385         nodeMap.FilterNodeByPid(pid);
386     }
387 
388     if (auto fallbackNode = nodeMap.GetAnimationFallbackNode()) {
389         // remove all fallback animations belong to given pid
390         FilterAnimationForPlayback(fallbackNode->GetAnimationManager());
391     }
392 }
393 
GetSurfacesTrees( const RSContext& context, std::map<std::string, std::tuple<NodeId, std::string>>& list)394 void RSProfiler::GetSurfacesTrees(
395     const RSContext& context, std::map<std::string, std::tuple<NodeId, std::string>>& list)
396 {
397     constexpr uint32_t treeDumpDepth = 2;
398 
399     list.clear();
400 
401     const RSRenderNodeMap& map = const_cast<RSContext&>(context).GetMutableNodeMap();
402     for (const auto& item : map.renderNodeMap_) {
403         if (item.second->GetType() == RSRenderNodeType::SURFACE_NODE) {
404             std::string tree;
405             item.second->DumpTree(treeDumpDepth, tree);
406 
407             const auto node = item.second->ReinterpretCastTo<RSSurfaceRenderNode>();
408             list.insert({ node->GetName(), { node->GetId(), tree } });
409         }
410     }
411 }
412 
GetSurfacesTrees(const RSContext& context, pid_t pid, std::map<NodeId, std::string>& list)413 void RSProfiler::GetSurfacesTrees(const RSContext& context, pid_t pid, std::map<NodeId, std::string>& list)
414 {
415     constexpr uint32_t treeDumpDepth = 2;
416 
417     list.clear();
418 
419     const RSRenderNodeMap& map = const_cast<RSContext&>(context).GetMutableNodeMap();
420     for (const auto& item : map.renderNodeMap_) {
421         if (item.second->GetId() == Utils::GetRootNodeId(pid)) {
422             std::string tree;
423             item.second->DumpTree(treeDumpDepth, tree);
424             list.insert({ item.second->GetId(), tree });
425         }
426     }
427 }
428 
GetRenderNodeCount(const RSContext& context)429 size_t RSProfiler::GetRenderNodeCount(const RSContext& context)
430 {
431     return const_cast<RSContext&>(context).GetMutableNodeMap().renderNodeMap_.size();
432 }
433 
GetRandomSurfaceNode(const RSContext& context)434 NodeId RSProfiler::GetRandomSurfaceNode(const RSContext& context)
435 {
436     const RSRenderNodeMap& map = const_cast<RSContext&>(context).GetMutableNodeMap();
437     for (const auto& item : map.surfaceNodeMap_) {
438         return item.first;
439     }
440     return 0;
441 }
442 
MarshalNodes(const RSContext& context, std::stringstream& data, uint32_t fileVersion)443 void RSProfiler::MarshalNodes(const RSContext& context, std::stringstream& data, uint32_t fileVersion)
444 {
445     const auto& map = const_cast<RSContext&>(context).GetMutableNodeMap();
446     const uint32_t count = map.renderNodeMap_.size();
447     data.write(reinterpret_cast<const char*>(&count), sizeof(count));
448     const auto& rootRenderNode = context.GetGlobalRootRenderNode();
449     if (rootRenderNode == nullptr) {
450         RS_LOGE("RSProfiler::MarshalNodes rootRenderNode is nullptr");
451         return;
452     }
453 
454     std::vector<std::shared_ptr<RSRenderNode>> nodes;
455     nodes.emplace_back(rootRenderNode);
456 
457     for (const auto& item : map.renderNodeMap_) {
458         if (const auto& node = item.second) {
459             MarshalNode(*node, data, fileVersion);
460             std::shared_ptr<RSRenderNode> parent = node->GetParent().lock();
461             if (!parent && (node != rootRenderNode)) {
462                 nodes.emplace_back(node);
463             }
464         }
465     }
466 
467     const uint32_t nodeCount = nodes.size();
468     data.write(reinterpret_cast<const char*>(&nodeCount), sizeof(nodeCount));
469     for (const auto& node : nodes) { // no nullptr in nodes, omit check
470         MarshalTree(*node, data, fileVersion);
471     }
472 }
473 
MarshalTree(const RSRenderNode& node, std::stringstream& data, uint32_t fileVersion)474 void RSProfiler::MarshalTree(const RSRenderNode& node, std::stringstream& data, uint32_t fileVersion)
475 {
476     const NodeId nodeId = node.GetId();
477     data.write(reinterpret_cast<const char*>(&nodeId), sizeof(nodeId));
478 
479     const uint32_t count = node.children_.size();
480     data.write(reinterpret_cast<const char*>(&count), sizeof(count));
481 
482     for (const auto& child : node.children_) {
483         if (auto node = child.lock().get()) {
484             const NodeId nodeId = node->GetId();
485             data.write(reinterpret_cast<const char*>(&nodeId), sizeof(nodeId));
486             MarshalTree(*node, data, fileVersion);
487         }
488     }
489 }
490 
MarshalNode(const RSRenderNode& node, std::stringstream& data, uint32_t fileVersion)491 void RSProfiler::MarshalNode(const RSRenderNode& node, std::stringstream& data, uint32_t fileVersion)
492 {
493     const RSRenderNodeType nodeType = node.GetType();
494     data.write(reinterpret_cast<const char*>(&nodeType), sizeof(nodeType));
495 
496     const NodeId nodeId = node.GetId();
497     data.write(reinterpret_cast<const char*>(&nodeId), sizeof(nodeId));
498 
499     const bool isTextureExportNode = node.GetIsTextureExportNode();
500     data.write(reinterpret_cast<const char*>(&isTextureExportNode), sizeof(isTextureExportNode));
501 
502     if (node.GetType() == RSRenderNodeType::SURFACE_NODE) {
503         const auto& surfaceNode = reinterpret_cast<const RSSurfaceRenderNode&>(node);
504         const std::string name = surfaceNode.GetName();
505         uint32_t size = name.size();
506         data.write(reinterpret_cast<const char*>(&size), sizeof(size));
507         data.write(reinterpret_cast<const char*>(name.c_str()), size);
508 
509         const std::string bundleName = "";
510         size = bundleName.size();
511         data.write(reinterpret_cast<const char*>(&size), sizeof(size));
512         data.write(reinterpret_cast<const char*>(bundleName.c_str()), size);
513 
514         const RSSurfaceNodeType type = surfaceNode.GetSurfaceNodeType();
515         data.write(reinterpret_cast<const char*>(&type), sizeof(type));
516 
517         const uint8_t backgroundAlpha = surfaceNode.GetAbilityBgAlpha();
518         data.write(reinterpret_cast<const char*>(&backgroundAlpha), sizeof(backgroundAlpha));
519 
520         const uint8_t globalAlpha = surfaceNode.GetGlobalAlpha();
521         data.write(reinterpret_cast<const char*>(&globalAlpha), sizeof(globalAlpha));
522     }
523 
524     const float positionZ = node.GetRenderProperties().GetPositionZ();
525     data.write(reinterpret_cast<const char*>(&positionZ), sizeof(positionZ));
526 
527     const float pivotZ = node.GetRenderProperties().GetPivotZ();
528     data.write(reinterpret_cast<const char*>(&pivotZ), sizeof(pivotZ));
529 
530     const NodePriorityType priority = const_cast<RSRenderNode&>(node).GetPriority();
531     data.write(reinterpret_cast<const char*>(&priority), sizeof(priority));
532 
533     const bool isOnTree = node.IsOnTheTree();
534     data.write(reinterpret_cast<const char*>(&isOnTree), sizeof(isOnTree));
535 
536     if (fileVersion >= RSFILE_VERSION_RENDER_METRICS_ADDED) {
537         const uint8_t nodeGroupType = node.nodeGroupType_;
538         data.write(reinterpret_cast<const char*>(&nodeGroupType), sizeof(nodeGroupType));
539     }
540 
541     MarshalNodeModifiers(node, data, fileVersion);
542 }
543 
MarshalRenderModifier(const RSRenderModifier& modifier, std::stringstream& data)544 static void MarshalRenderModifier(const RSRenderModifier& modifier, std::stringstream& data)
545 {
546     Parcel parcel;
547     parcel.SetMaxCapacity(GetParcelMaxCapacity());
548     const_cast<RSRenderModifier&>(modifier).Marshalling(parcel);
549 
550     const size_t dataSize = parcel.GetDataSize();
551     data.write(reinterpret_cast<const char*>(&dataSize), sizeof(dataSize));
552     data.write(reinterpret_cast<const char*>(parcel.GetData()), dataSize);
553 
554     // Remove all file descriptors
555     binder_size_t* object = reinterpret_cast<binder_size_t*>(parcel.GetObjectOffsets());
556     size_t objectNum = parcel.GetOffsetsSize();
557     uintptr_t parcelData = parcel.GetData();
558 
559     const size_t maxObjectNum = INT_MAX;
560     if (!object || (objectNum > maxObjectNum)) {
561         return;
562     }
563 
564     for (size_t i = 0; i < objectNum; i++) {
565         const flat_binder_object* flat = reinterpret_cast<flat_binder_object*>(parcelData + object[i]);
566         if (!flat) {
567             return;
568         }
569         if (flat->hdr.type == BINDER_TYPE_FD && flat->handle > 0) {
570             ::close(flat->handle);
571         }
572     }
573 }
574 
MarshalNodeModifiers(const RSRenderNode& node, std::stringstream& data, uint32_t fileVersion)575 void RSProfiler::MarshalNodeModifiers(const RSRenderNode& node, std::stringstream& data, uint32_t fileVersion)
576 {
577     data.write(reinterpret_cast<const char*>(&node.instanceRootNodeId_), sizeof(node.instanceRootNodeId_));
578     data.write(reinterpret_cast<const char*>(&node.firstLevelNodeId_), sizeof(node.firstLevelNodeId_));
579 
580     const uint32_t modifierCount = node.modifiers_.size();
581     data.write(reinterpret_cast<const char*>(&modifierCount), sizeof(modifierCount));
582 
583     for (const auto& [id, modifier] : node.modifiers_) {
584         if (modifier) {
585             MarshalRenderModifier(*modifier, data);
586         }
587     }
588 
589     const uint32_t drawModifierCount = node.renderContent_->drawCmdModifiers_.size();
590     data.write(reinterpret_cast<const char*>(&drawModifierCount), sizeof(drawModifierCount));
591 
592     for (const auto& [type, modifiers] : node.renderContent_->drawCmdModifiers_) {
593         const uint32_t modifierCount = modifiers.size();
594         data.write(reinterpret_cast<const char*>(&modifierCount), sizeof(modifierCount));
595         for (const auto& modifier : modifiers) {
596             if (!modifier) {
597                 continue;
598             }
599             if (auto commandList = reinterpret_cast<Drawing::DrawCmdList*>(modifier->GetDrawCmdListId())) {
600                 std::string allocData = commandList->ProfilerPushAllocators();
601                 commandList->MarshallingDrawOps();
602                 MarshalRenderModifier(*modifier, data);
603                 commandList->ProfilerPopAllocators(allocData);
604             } else {
605                 MarshalRenderModifier(*modifier, data);
606             }
607         }
608     }
609 }
610 
CreateRenderSurfaceNode(RSContext& context, NodeId id, bool isTextureExportNode, std::stringstream& data)611 static void CreateRenderSurfaceNode(RSContext& context, NodeId id, bool isTextureExportNode, std::stringstream& data)
612 {
613     uint32_t size = 0u;
614     data.read(reinterpret_cast<char*>(&size), sizeof(size));
615 
616     std::string name;
617     name.resize(size, ' ');
618     data.read(reinterpret_cast<char*>(name.data()), size);
619 
620     data.read(reinterpret_cast<char*>(&size), sizeof(size));
621     std::string bundleName;
622     bundleName.resize(size, ' ');
623     data.read(reinterpret_cast<char*>(bundleName.data()), size);
624 
625     RSSurfaceNodeType nodeType = RSSurfaceNodeType::DEFAULT;
626     data.read(reinterpret_cast<char*>(&nodeType), sizeof(nodeType));
627 
628     uint8_t backgroundAlpha = 0u;
629     data.read(reinterpret_cast<char*>(&backgroundAlpha), sizeof(backgroundAlpha));
630 
631     uint8_t globalAlpha = 0u;
632     data.read(reinterpret_cast<char*>(&globalAlpha), sizeof(globalAlpha));
633 
634     const RSSurfaceRenderNodeConfig config = { .id = id,
635         .name = name + "_",
636         .nodeType = nodeType,
637         .additionalData = nullptr,
638         .isTextureExportNode = isTextureExportNode,
639         .isSync = false };
640 
641     if (auto node = SurfaceNodeCommandHelper::CreateWithConfigInRS(config, context)) {
642         context.GetMutableNodeMap().RegisterRenderNode(node);
643         node->SetAbilityBGAlpha(backgroundAlpha);
644         node->SetGlobalAlpha(globalAlpha);
645     }
646 }
647 
UnmarshalNodes(RSContext& context, std::stringstream& data, uint32_t fileVersion)648 void RSProfiler::UnmarshalNodes(RSContext& context, std::stringstream& data, uint32_t fileVersion)
649 {
650     uint32_t count = 0;
651     data.read(reinterpret_cast<char*>(&count), sizeof(count));
652     for (uint32_t i = 0; i < count; i++) {
653         UnmarshalNode(context, data, fileVersion);
654     }
655 
656     data.read(reinterpret_cast<char*>(&count), sizeof(count));
657     for (uint32_t i = 0; i < count; i++) {
658         UnmarshalTree(context, data, fileVersion);
659     }
660 
661     auto& nodeMap = context.GetMutableNodeMap();
662     nodeMap.TraversalNodes([](const std::shared_ptr<RSBaseRenderNode>& node) {
663         if (node == nullptr) {
664             return;
665         }
666         if (Utils::IsNodeIdPatched(node->GetId())) {
667             node->SetContentDirty();
668             node->SetDirty();
669         }
670     });
671 }
672 
UnmarshalNode(RSContext& context, std::stringstream& data, uint32_t fileVersion)673 void RSProfiler::UnmarshalNode(RSContext& context, std::stringstream& data, uint32_t fileVersion)
674 {
675     RSRenderNodeType nodeType = RSRenderNodeType::UNKNOW;
676     data.read(reinterpret_cast<char*>(&nodeType), sizeof(nodeType));
677 
678     NodeId nodeId = 0;
679     data.read(reinterpret_cast<char*>(&nodeId), sizeof(nodeId));
680     nodeId = Utils::PatchNodeId(nodeId);
681 
682     bool isTextureExportNode = false;
683     data.read(reinterpret_cast<char*>(&isTextureExportNode), sizeof(isTextureExportNode));
684 
685     if (nodeType == RSRenderNodeType::RS_NODE) {
686         RootNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
687     } else if (nodeType == RSRenderNodeType::DISPLAY_NODE) {
688         RootNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
689     } else if (nodeType == RSRenderNodeType::SURFACE_NODE) {
690         CreateRenderSurfaceNode(context, nodeId, isTextureExportNode, data);
691     } else if (nodeType == RSRenderNodeType::PROXY_NODE) {
692         ProxyNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
693     } else if (nodeType == RSRenderNodeType::CANVAS_NODE) {
694         RSCanvasNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
695     } else if (nodeType == RSRenderNodeType::EFFECT_NODE) {
696         EffectNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
697     } else if (nodeType == RSRenderNodeType::ROOT_NODE) {
698         RootNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
699     } else if (nodeType == RSRenderNodeType::CANVAS_DRAWING_NODE) {
700         RSCanvasDrawingNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
701     } else {
702         RootNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
703     }
704     UnmarshalNode(context, data, nodeId, fileVersion);
705 }
706 
UnmarshalNode(RSContext& context, std::stringstream& data, NodeId nodeId, uint32_t fileVersion)707 void RSProfiler::UnmarshalNode(RSContext& context, std::stringstream& data, NodeId nodeId, uint32_t fileVersion)
708 {
709     float positionZ = 0.0f;
710     data.read(reinterpret_cast<char*>(&positionZ), sizeof(positionZ));
711     float pivotZ = 0.0f;
712     data.read(reinterpret_cast<char*>(&pivotZ), sizeof(pivotZ));
713     NodePriorityType priority = NodePriorityType::MAIN_PRIORITY;
714     data.read(reinterpret_cast<char*>(&priority), sizeof(priority));
715     bool isOnTree = false;
716     data.read(reinterpret_cast<char*>(&isOnTree), sizeof(isOnTree));
717 
718     uint8_t nodeGroupType = 0;
719     if (fileVersion >= RSFILE_VERSION_RENDER_METRICS_ADDED) {
720         data.read(reinterpret_cast<char*>(&nodeGroupType), sizeof(nodeGroupType));
721     }
722 
723     if (auto node = context.GetMutableNodeMap().GetRenderNode(nodeId)) {
724         node->GetMutableRenderProperties().SetPositionZ(positionZ);
725         node->GetMutableRenderProperties().SetPivotZ(pivotZ);
726         node->SetPriority(priority);
727         node->RSRenderNode::SetIsOnTheTree(isOnTree);
728         node->nodeGroupType_ = nodeGroupType;
729         UnmarshalNodeModifiers(*node, data, fileVersion);
730     }
731 }
732 
UnmarshalRenderModifier(std::stringstream& data)733 static RSRenderModifier* UnmarshalRenderModifier(std::stringstream& data)
734 {
735     size_t bufferSize = 0;
736     data.read(reinterpret_cast<char*>(&bufferSize), sizeof(bufferSize));
737 
738     std::vector<uint8_t> buffer;
739     buffer.resize(bufferSize);
740     data.read(reinterpret_cast<char*>(buffer.data()), buffer.size());
741 
742     uint8_t parcelMemory[sizeof(Parcel) + 1];
743     auto* parcel = new (parcelMemory + 1) Parcel;
744     parcel->SetMaxCapacity(GetParcelMaxCapacity());
745     parcel->WriteBuffer(buffer.data(), buffer.size());
746 
747     return RSRenderModifier::Unmarshalling(*parcel);
748 }
749 
UnmarshalNodeModifiers(RSRenderNode& node, std::stringstream& data, uint32_t fileVersion)750 void RSProfiler::UnmarshalNodeModifiers(RSRenderNode& node, std::stringstream& data, uint32_t fileVersion)
751 {
752     data.read(reinterpret_cast<char*>(&node.instanceRootNodeId_), sizeof(node.instanceRootNodeId_));
753     node.instanceRootNodeId_ = Utils::PatchNodeId(node.instanceRootNodeId_);
754 
755     data.read(reinterpret_cast<char*>(&node.firstLevelNodeId_), sizeof(node.firstLevelNodeId_));
756     node.firstLevelNodeId_ = Utils::PatchNodeId(node.firstLevelNodeId_);
757 
758     int32_t modifierCount = 0;
759     data.read(reinterpret_cast<char*>(&modifierCount), sizeof(modifierCount));
760     for (int32_t i = 0; i < modifierCount; i++) {
761         node.AddModifier(std::shared_ptr<RSRenderModifier>(UnmarshalRenderModifier(data)));
762     }
763 
764     uint32_t drawModifierCount = 0u;
765     data.read(reinterpret_cast<char*>(&drawModifierCount), sizeof(drawModifierCount));
766     for (uint32_t i = 0; i < drawModifierCount; i++) {
767         uint32_t modifierCount = 0u;
768         data.read(reinterpret_cast<char*>(&modifierCount), sizeof(modifierCount));
769         for (uint32_t j = 0; j < modifierCount; j++) {
770             node.AddModifier(std::shared_ptr<RSRenderModifier>(UnmarshalRenderModifier(data)));
771         }
772     }
773 
774     node.ApplyModifiers();
775 }
776 
UnmarshalTree(RSContext& context, std::stringstream& data, uint32_t fileVersion)777 void RSProfiler::UnmarshalTree(RSContext& context, std::stringstream& data, uint32_t fileVersion)
778 {
779     const auto& map = context.GetMutableNodeMap();
780 
781     NodeId nodeId = 0;
782     data.read(reinterpret_cast<char*>(&nodeId), sizeof(nodeId));
783     nodeId = Utils::PatchNodeId(nodeId);
784 
785     uint32_t count = 0;
786     data.read(reinterpret_cast<char*>(&count), sizeof(count));
787 
788     auto node = map.GetRenderNode(nodeId);
789     if (!node) {
790         return;
791     }
792     for (uint32_t i = 0; i < count; i++) {
793         NodeId nodeId = 0;
794         data.read(reinterpret_cast<char*>(&nodeId), sizeof(nodeId));
795         node->AddChild(map.GetRenderNode(Utils::PatchNodeId(nodeId)), i);
796         UnmarshalTree(context, data, fileVersion);
797     }
798 }
799 
DumpRenderProperties(const RSRenderNode& node)800 std::string RSProfiler::DumpRenderProperties(const RSRenderNode& node)
801 {
802     if (node.renderContent_) {
803         return node.renderContent_->renderProperties_.Dump();
804     }
805     return "";
806 }
807 
DumpModifiers(const RSRenderNode& node)808 std::string RSProfiler::DumpModifiers(const RSRenderNode& node)
809 {
810     if (!node.renderContent_) {
811         return "";
812     }
813 
814     std::string out;
815     out += "<";
816 
817     for (auto& [type, modifiers] : node.renderContent_->drawCmdModifiers_) {
818         out += "(";
819         out += std::to_string(static_cast<int32_t>(type));
820         out += ", ";
821         for (auto& item : modifiers) {
822             out += "[";
823             const auto propertyId = item->GetPropertyId();
824             out += std::to_string(Utils::ExtractPid(propertyId));
825             out += "|";
826             out += std::to_string(Utils::ExtractNodeId(propertyId));
827             out += " type=";
828             out += std::to_string(static_cast<int32_t>(item->GetType()));
829             out += " [modifier dump is not implemented yet]";
830             out += "]";
831         }
832         out += ")";
833     }
834 
835     out += ">";
836     return out;
837 }
838 
DumpSurfaceNode(const RSRenderNode& node)839 std::string RSProfiler::DumpSurfaceNode(const RSRenderNode& node)
840 {
841     if (node.GetType() != RSRenderNodeType::SURFACE_NODE) {
842         return "";
843     }
844 
845     std::string out;
846     const auto& surfaceNode = (static_cast<const RSSurfaceRenderNode&>(node));
847     const auto parent = node.parent_.lock();
848     out += ", Parent [" + (parent ? std::to_string(parent->GetId()) : "null") + "]";
849     out += ", Name [" + surfaceNode.GetName() + "]";
850     if (surfaceNode.GetRSSurfaceHandler()) {
851         out += ", hasConsumer: " + std::to_string(surfaceNode.GetRSSurfaceHandler()->HasConsumer());
852     }
853     std::string contextAlpha = std::to_string(surfaceNode.contextAlpha_);
854     std::string propertyAlpha = std::to_string(surfaceNode.GetRenderProperties().GetAlpha());
855     out += ", Alpha: " + propertyAlpha + " (include ContextAlpha: " + contextAlpha + ")";
856     out += ", Visible: " + std::to_string(surfaceNode.GetRenderProperties().GetVisible());
857     out += ", " + surfaceNode.GetVisibleRegion().GetRegionInfo();
858     out += ", OcclusionBg: " + std::to_string(surfaceNode.GetAbilityBgAlpha());
859     out += ", Properties: " + node.GetRenderProperties().Dump();
860     return out;
861 }
862 
863 // RSAnimationManager
FilterAnimationForPlayback(RSAnimationManager& manager)864 void RSProfiler::FilterAnimationForPlayback(RSAnimationManager& manager)
865 {
866     EraseIf(manager.animations_, [](const auto& pair) -> bool {
867         if (!Utils::IsNodeIdPatched(pair.first)) {
868             return false;
869         }
870         pair.second->Finish();
871         pair.second->Detach();
872         return true;
873     });
874 }
875 
SetTransactionTimeCorrection(double replayStartTime, double recordStartTime)876 void RSProfiler::SetTransactionTimeCorrection(double replayStartTime, double recordStartTime)
877 {
878     g_transactionTimeCorrection = static_cast<int64_t>((replayStartTime - recordStartTime) * NS_TO_S);
879     g_replayStartTimeNano = replayStartTime * NS_TO_S;
880 }
881 
GetCommandParcelList(double recordStartTime)882 std::string RSProfiler::GetCommandParcelList(double recordStartTime)
883 {
884     if (g_commandLoopIndexStart >= g_commandLoopIndexEnd) {
885         return "";
886     }
887 
888     uint32_t index = g_commandLoopIndexStart;
889     g_commandLoopIndexStart++;
890     index %= COMMAND_LOOP_SIZE;
891 
892     std::string retStr;
893 
894     uint16_t cmdCount = g_commandLoop[index].cmdCount;
895     if (cmdCount > COMMAND_PARSE_LIST_SIZE) {
896         cmdCount = COMMAND_PARSE_LIST_SIZE;
897     }
898     if (cmdCount > 0) {
899         uint16_t copyBytes = sizeof(PacketParsedCommandList) - (COMMAND_PARSE_LIST_SIZE - cmdCount) * sizeof(uint32_t);
900         retStr.resize(copyBytes, ' ');
901         Utils::Move(retStr.data(), copyBytes, &g_commandLoop[index], copyBytes);
902         g_commandLoop[index].cmdCount = 0;
903     }
904 
905     return retStr;
906 }
907 
PatchCommand(const Parcel& parcel, RSCommand* command)908 void RSProfiler::PatchCommand(const Parcel& parcel, RSCommand* command)
909 {
910     if (!IsEnabled()) {
911         return;
912     }
913     if (command == nullptr) {
914         return;
915     }
916 
917     if (g_mode == Mode::WRITE) {
918         g_commandCount++;
919         uint16_t cmdCount = g_commandParseBuffer.cmdCount;
920         if (cmdCount < COMMAND_PARSE_LIST_COUNT) {
921             constexpr uint32_t bits = 16u;
922             g_commandParseBuffer.cmdCode[cmdCount] =
923                 command->GetType() + (static_cast<uint32_t>(command->GetSubType()) << bits);
924         }
925         g_commandParseBuffer.cmdCount++;
926     }
927 
928     if (command && IsParcelMock(parcel)) {
929         command->Patch(Utils::PatchNodeId);
930     }
931 }
932 
ExecuteCommand(const RSCommand* command)933 void RSProfiler::ExecuteCommand(const RSCommand* command)
934 {
935     if (!IsEnabled()) {
936         return;
937     }
938     if (g_mode != Mode::WRITE && g_mode != Mode::READ) {
939         return;
940     }
941     if (command == nullptr) {
942         return;
943     }
944 
945     g_commandExecuteCount++;
946 }
947 
PerfTreeFlatten(const std::shared_ptr<RSRenderNode> node, std::vector<std::pair<NodeId, uint32_t>>& nodeSet, std::unordered_map<NodeId, uint32_t>& mapNode2Count, int depth)948 uint32_t RSProfiler::PerfTreeFlatten(const std::shared_ptr<RSRenderNode> node,
949     std::vector<std::pair<NodeId, uint32_t>>& nodeSet,
950     std::unordered_map<NodeId, uint32_t>& mapNode2Count, int depth)
951 {
952     if (!node) {
953         return 0;
954     }
955 
956     constexpr uint32_t depthToAnalyze = 10;
957     uint32_t drawCmdListCount = CalcNodeCmdListCount(*node);
958     uint32_t valuableChildrenCount = 0;
959     if (node->GetSortedChildren()) {
960         for (auto& child : *node->GetSortedChildren()) {
961             if (child && child->GetType() != RSRenderNodeType::EFFECT_NODE && depth < depthToAnalyze) {
962                 nodeSet.emplace_back(child->id_, depth + 1);
963             }
964         }
965         for (auto& child : *node->GetSortedChildren()) {
966             if (child) {
967                 drawCmdListCount += PerfTreeFlatten(child, nodeSet, mapNode2Count, depth + 1);
968                 valuableChildrenCount++;
969             }
970         }
971     }
972 
973     if (drawCmdListCount > 0) {
974         mapNode2Count[node->id_] = drawCmdListCount;
975     }
976     return drawCmdListCount;
977 }
978 
CalcNodeCmdListCount(RSRenderNode& node)979 uint32_t RSProfiler::CalcNodeCmdListCount(RSRenderNode& node)
980 {
981     if (!node.renderContent_) {
982         return 0;
983     }
984 
985     uint32_t nodeCmdListCount = 0;
986     for (auto& [type, modifiers] : node.renderContent_->drawCmdModifiers_) {
987         if (type >= RSModifierType::ENV_FOREGROUND_COLOR) {
988             continue;
989         }
990         for (auto& modifier : modifiers) {
991             auto propertyPtr =
992                 modifier ? std::static_pointer_cast<RSRenderProperty<Drawing::DrawCmdListPtr>>(modifier->GetProperty())
993                          : nullptr;
994             auto propertyValue = propertyPtr ? propertyPtr->Get() : nullptr;
995             if (propertyValue && propertyValue->GetOpItemSize() > 0) {
996                 nodeCmdListCount = 1;
997             }
998         }
999     }
1000     return nodeCmdListCount;
1001 }
1002 
MarshalDrawingImage(std::shared_ptr<Drawing::Image>& image, std::shared_ptr<Drawing::Data>& compressData)1003 void RSProfiler::MarshalDrawingImage(std::shared_ptr<Drawing::Image>& image,
1004     std::shared_ptr<Drawing::Data>& compressData)
1005 {
1006     if (IsEnabled() && !IsSharedMemoryEnabled()) {
1007         image = nullptr;
1008         compressData = nullptr;
1009     }
1010 }
1011 
EnableBetaRecord()1012 void RSProfiler::EnableBetaRecord()
1013 {
1014     RSSystemProperties::SetBetaRecordingMode(1);
1015 }
1016 
IsBetaRecordSavingTriggered()1017 bool RSProfiler::IsBetaRecordSavingTriggered()
1018 {
1019     constexpr uint32_t savingMode = 2u;
1020     return RSSystemProperties::GetBetaRecordingMode() == savingMode;
1021 }
1022 
IsBetaRecordEnabledWithMetrics()1023 bool RSProfiler::IsBetaRecordEnabledWithMetrics()
1024 {
1025     constexpr uint32_t metricsMode = 3u;
1026     return RSSystemProperties::GetBetaRecordingMode() == metricsMode;
1027 }
1028 
SetDrawingCanvasNodeRedraw(bool enable)1029 void RSProfiler::SetDrawingCanvasNodeRedraw(bool enable)
1030 {
1031     dcnRedraw_ = enable && IsEnabled();
1032 }
1033 
DrawingNodeAddClearOp(const std::shared_ptr<Drawing::DrawCmdList>& drawCmdList)1034 void RSProfiler::DrawingNodeAddClearOp(const std::shared_ptr<Drawing::DrawCmdList>& drawCmdList)
1035 {
1036     if (dcnRedraw_ || !drawCmdList) {
1037         return;
1038     }
1039     drawCmdList->ClearOp();
1040 }
1041 
NewAshmemDataCacheId()1042 static uint64_t NewAshmemDataCacheId()
1043 {
1044     static uint32_t id = 0u;
1045     return Utils::ComposeDataId(Utils::GetPid(), id++);
1046 }
1047 
CacheAshmemData(uint64_t id, const uint8_t* data, size_t size)1048 static void CacheAshmemData(uint64_t id, const uint8_t* data, size_t size)
1049 {
1050     if (g_mode != Mode::WRITE) {
1051         return;
1052     }
1053 
1054     if (data && (size > 0)) {
1055         Image ashmem;
1056         ashmem.data.insert(ashmem.data.end(), data, data + size);
1057         ImageCache::Add(id, std::move(ashmem));
1058     }
1059 }
1060 
GetCachedAshmemData(uint64_t id)1061 static const uint8_t* GetCachedAshmemData(uint64_t id)
1062 {
1063     const auto ashmem = (g_mode == Mode::READ) ? ImageCache::Get(id) : nullptr;
1064     return ashmem ? ashmem->data.data() : nullptr;
1065 }
1066 
WriteParcelData(Parcel& parcel)1067 void RSProfiler::WriteParcelData(Parcel& parcel)
1068 {
1069     bool isClientEnabled = RSSystemProperties::GetProfilerEnabled();
1070     if (!parcel.WriteBool(isClientEnabled)) {
1071         HRPE("Unable to write is_client_enabled");
1072         return;
1073     }
1074 
1075     if (!isClientEnabled) {
1076         return;
1077     }
1078 
1079     parcel.WriteUint64(NewAshmemDataCacheId());
1080 }
1081 
ReadParcelData(Parcel& parcel, size_t size, bool& isMalloc)1082 const void* RSProfiler::ReadParcelData(Parcel& parcel, size_t size, bool& isMalloc)
1083 {
1084     bool isClientEnabled = false;
1085     if (!parcel.ReadBool(isClientEnabled)) {
1086         HRPE("Unable to read is_client_enabled");
1087         return nullptr;
1088     }
1089     if (!isClientEnabled) {
1090         return RSMarshallingHelper::ReadFromAshmem(parcel, size, isMalloc);
1091     }
1092 
1093     const uint64_t id = parcel.ReadUint64();
1094     if (auto data = GetCachedAshmemData(id)) {
1095         constexpr uint32_t skipBytes = 24u;
1096         parcel.SkipBytes(skipBytes);
1097         isMalloc = false;
1098         return data;
1099     }
1100 
1101     auto data = RSMarshallingHelper::ReadFromAshmem(parcel, size, isMalloc);
1102     CacheAshmemData(id, reinterpret_cast<const uint8_t*>(data), size);
1103     return data;
1104 }
1105 
SkipParcelData(Parcel& parcel, size_t size)1106 bool RSProfiler::SkipParcelData(Parcel& parcel, size_t size)
1107 {
1108     bool isClientEnabled = false;
1109     if (!parcel.ReadBool(isClientEnabled)) {
1110         return false;
1111     }
1112     if (!isClientEnabled) {
1113         return false;
1114     }
1115 
1116     [[maybe_unused]] const uint64_t id = parcel.ReadUint64();
1117 
1118     if (g_mode == Mode::READ) {
1119         constexpr uint32_t skipBytes = 24u;
1120         parcel.SkipBytes(skipBytes);
1121         return true;
1122     }
1123 
1124     return false;
1125 }
1126 
GetNodeDepth(const std::shared_ptr<RSRenderNode> node)1127 uint32_t RSProfiler::GetNodeDepth(const std::shared_ptr<RSRenderNode> node)
1128 {
1129     uint32_t depth = 0;
1130     for (auto curNode = node; curNode != nullptr; depth++) {
1131         curNode = curNode ? curNode->GetParent().lock() : nullptr;
1132     }
1133     return depth;
1134 }
1135 
SendMessageBase()1136 std::string RSProfiler::SendMessageBase()
1137 {
1138     const std::lock_guard<std::mutex> guard(g_msgBaseMutex);
1139     if (g_msgBaseList.empty()) {
1140         return "";
1141     }
1142     std::string value = g_msgBaseList.front();
1143     g_msgBaseList.pop();
1144     return value;
1145 }
1146 
SendMessageBase(const std::string& msg)1147 void RSProfiler::SendMessageBase(const std::string& msg)
1148 {
1149     const std::lock_guard<std::mutex> guard(g_msgBaseMutex);
1150     g_msgBaseList.push(msg);
1151 }
1152 
AnimeGetStartTimes()1153 std::unordered_map<AnimationId, std::vector<int64_t>> &RSProfiler::AnimeGetStartTimes()
1154 {
1155     return g_animeStartMap;
1156 }
1157 
ReplayFixTrIndex(uint64_t curIndex, uint64_t& lastIndex)1158 void RSProfiler::ReplayFixTrIndex(uint64_t curIndex, uint64_t& lastIndex)
1159 {
1160     if (!IsEnabled()) {
1161         return;
1162     }
1163     if (g_mode == Mode::READ) {
1164         if (lastIndex == 0) {
1165             lastIndex = curIndex - 1;
1166         }
1167     }
1168 }
1169 
AnimeSetStartTime(AnimationId id, int64_t nanoTime)1170 int64_t RSProfiler::AnimeSetStartTime(AnimationId id, int64_t nanoTime)
1171 {
1172     if (!IsEnabled()) {
1173         return nanoTime;
1174     }
1175 
1176     if (g_mode == Mode::READ) {
1177         if (!g_animeStartMap.count(id)) {
1178             return nanoTime;
1179         }
1180         int64_t minDt = INT64_MAX, minTime = nanoTime - g_replayStartTimeNano;
1181         for (const auto recordedTime : g_animeStartMap[id]) {
1182             int64_t dt = abs(recordedTime - (nanoTime - g_replayStartTimeNano));
1183             if (dt < minDt) {
1184                 minDt = dt;
1185                 minTime = recordedTime;
1186             }
1187         }
1188         return minTime + g_replayStartTimeNano;
1189     } else if (g_mode == Mode::WRITE) {
1190         if (g_animeStartMap.count(id)) {
1191             g_animeStartMap[Utils::PatchNodeId(id)].push_back(nanoTime);
1192         } else {
1193             std::vector<int64_t> list;
1194             list.push_back(nanoTime);
1195             g_animeStartMap.insert({ Utils::PatchNodeId(id), list });
1196         }
1197     }
1198 
1199     return nanoTime;
1200 }
1201 
1202 } // namespace OHOS::Rosen