• 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 "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 "pipeline/rs_canvas_drawing_render_node.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 std::atomic_bool RSProfiler::recordAbortRequested_ = false;
51 std::atomic_uint32_t RSProfiler::mode_ = static_cast<uint32_t>(Mode::NONE);
52 static std::vector<pid_t> g_pids;
53 static pid_t g_pid = 0;
54 static NodeId g_parentNode = 0;
55 static std::atomic<uint32_t> g_commandCount = 0;        // UNMARSHALLING RSCOMMAND COUNT
56 static std::atomic<uint32_t> g_commandExecuteCount = 0; // EXECUTE RSCOMMAND COUNT
57 
58 static std::mutex g_msgBaseMutex;
59 static std::queue<std::string> g_msgBaseList;
60 
61 static std::mutex g_mutexCommandOffsets;
62 static std::map<uint32_t, std::vector<uint32_t>> g_parcelNumber2Offset;
63 
64 static uint64_t g_pauseAfterTime = 0;
65 static int64_t g_pauseCumulativeTime = 0;
66 static int64_t g_transactionTimeCorrection = 0;
67 static int64_t g_replayStartTimeNano = 0.0;
68 static double g_replaySpeed = 1.0f;
69 
70 static const size_t PARCEL_MAX_CAPACITY = 234 * 1024 * 1024;
71 
72 static std::unordered_map<AnimationId, std::vector<int64_t>> g_animeStartMap;
73 
74 bool RSProfiler::testing_ = false;
75 bool RSProfiler::enabled_ = RSSystemProperties::GetProfilerEnabled();
76 bool RSProfiler::betaRecordingEnabled_ = RSSystemProperties::GetBetaRecordingMode() != 0;
77 int8_t RSProfiler::signalFlagChanged_ = 0;
78 std::atomic_bool RSProfiler::dcnRedraw_ = false;
79 std::vector<RSRenderNode::WeakPtr> g_childOfDisplayNodesPostponed;
80 
GetParcelMaxCapacity()81 constexpr size_t GetParcelMaxCapacity()
82 {
83     return PARCEL_MAX_CAPACITY;
84 }
85 
IsEnabled()86 bool RSProfiler::IsEnabled()
87 {
88     return enabled_ || testing_;
89 }
90 
IsBetaRecordEnabled()91 bool RSProfiler::IsBetaRecordEnabled()
92 {
93 #ifdef RS_PROFILER_BETA_ENABLED
94     return betaRecordingEnabled_;
95 #else
96     return false;
97 #endif
98 }
99 
IsNoneMode()100 bool RSProfiler::IsNoneMode()
101 {
102     return GetMode() == Mode::NONE;
103 }
104 
IsReadMode()105 bool RSProfiler::IsReadMode()
106 {
107     return GetMode() == Mode::READ;
108 }
109 
IsReadEmulationMode()110 bool RSProfiler::IsReadEmulationMode()
111 {
112     return GetMode() == Mode::READ_EMUL;
113 }
114 
IsWriteMode()115 bool RSProfiler::IsWriteMode()
116 {
117     return GetMode() == Mode::WRITE;
118 }
119 
IsWriteEmulationMode()120 bool RSProfiler::IsWriteEmulationMode()
121 {
122     return GetMode() == Mode::WRITE_EMUL;
123 }
124 
IsSavingMode()125 bool RSProfiler::IsSavingMode()
126 {
127     return GetMode() == Mode::SAVING;
128 }
129 
GetCommandCount()130 uint32_t RSProfiler::GetCommandCount()
131 {
132     const uint32_t count = g_commandCount;
133     g_commandCount = 0;
134     return count;
135 }
136 
GetCommandExecuteCount()137 uint32_t RSProfiler::GetCommandExecuteCount()
138 {
139     const uint32_t count = g_commandExecuteCount;
140     g_commandExecuteCount = 0;
141     return count;
142 }
143 
EnableSharedMemory()144 void RSProfiler::EnableSharedMemory()
145 {
146     RSMarshallingHelper::EndNoSharedMem();
147 }
148 
DisableSharedMemory()149 void RSProfiler::DisableSharedMemory()
150 {
151     RSMarshallingHelper::BeginNoSharedMem(std::this_thread::get_id());
152 }
153 
IsSharedMemoryEnabled()154 bool RSProfiler::IsSharedMemoryEnabled()
155 {
156     return RSMarshallingHelper::GetUseSharedMem(std::this_thread::get_id());
157 }
158 
IsParcelMock(const Parcel & parcel)159 bool RSProfiler::IsParcelMock(const Parcel& parcel)
160 {
161     // gcc C++ optimization error (?): this is not working without volatile
162     const volatile auto address = reinterpret_cast<uint64_t>(&parcel);
163     return ((address & 1u) != 0);
164 }
165 
CopyParcel(const MessageParcel & parcel)166 std::shared_ptr<MessageParcel> RSProfiler::CopyParcel(const MessageParcel& parcel)
167 {
168     if (!IsEnabled()) {
169         return std::make_shared<MessageParcel>();
170     }
171 
172     if (IsParcelMock(parcel)) {
173         auto* buffer = new(std::nothrow) uint8_t[sizeof(MessageParcel) + 1];
174         if (!buffer) {
175             return std::make_shared<MessageParcel>();
176         }
177         auto* mpPtr = new (buffer + 1) MessageParcel;
178         return std::shared_ptr<MessageParcel>(mpPtr, [](MessageParcel* ptr) {
179             ptr->~MessageParcel();
180             auto* allocPtr = reinterpret_cast<uint8_t*>(ptr);
181             allocPtr--;
182             delete[] allocPtr;
183         });
184     }
185 
186     return std::make_shared<MessageParcel>();
187 }
188 
PatchPlainNodeId(const Parcel & parcel,NodeId id)189 NodeId RSProfiler::PatchPlainNodeId(const Parcel& parcel, NodeId id)
190 {
191     if (!IsEnabled()) {
192         return id;
193     }
194 
195     if ((!IsReadMode() && !IsReadEmulationMode()) || !IsParcelMock(parcel)) {
196         return id;
197     }
198 
199     return Utils::PatchNodeId(id);
200 }
201 
PatchTypefaceId(const Parcel & parcel,std::shared_ptr<Drawing::DrawCmdList> & val)202 void RSProfiler::PatchTypefaceId(const Parcel& parcel, std::shared_ptr<Drawing::DrawCmdList>& val)
203 {
204     if (!val || !IsEnabled()) {
205         return;
206     }
207 
208     if (IsReadEmulationMode()) {
209         val->PatchTypefaceIds();
210     } else if (IsReadMode()) {
211         if (IsParcelMock(parcel)) {
212             val->PatchTypefaceIds();
213         }
214     }
215 }
216 
PatchPlainPid(const Parcel & parcel,pid_t pid)217 pid_t RSProfiler::PatchPlainPid(const Parcel& parcel, pid_t pid)
218 {
219     if (!IsEnabled() || (!IsReadMode() && !IsReadEmulationMode()) || !IsParcelMock(parcel)) {
220         return pid;
221     }
222 
223     return Utils::GetMockPid(pid);
224 }
225 
SetMode(Mode mode)226 void RSProfiler::SetMode(Mode mode)
227 {
228     mode_ = static_cast<uint32_t>(mode);
229     if (IsNoneMode()) {
230         g_pauseAfterTime = 0;
231         g_pauseCumulativeTime = 0;
232         g_replayStartTimeNano = 0;
233     }
234 }
235 
GetMode()236 Mode RSProfiler::GetMode()
237 {
238     return static_cast<Mode>(mode_.load());
239 }
240 
SetSubstitutingPid(const std::vector<pid_t> & pids,pid_t pid,NodeId parent)241 void RSProfiler::SetSubstitutingPid(const std::vector<pid_t>& pids, pid_t pid, NodeId parent)
242 {
243     g_pids = pids;
244     g_pid = pid;
245     g_parentNode = parent;
246 }
247 
GetParentNode()248 NodeId RSProfiler::GetParentNode()
249 {
250     return g_parentNode;
251 }
252 
GetPids()253 const std::vector<pid_t>& RSProfiler::GetPids()
254 {
255     return g_pids;
256 }
257 
GetSubstitutingPid()258 pid_t RSProfiler::GetSubstitutingPid()
259 {
260     return g_pid;
261 }
262 
PatchTime(uint64_t time)263 uint64_t RSProfiler::PatchTime(uint64_t time)
264 {
265     if (!IsEnabled()) {
266         return time;
267     }
268     if (!IsReadMode() && !IsReadEmulationMode()) {
269         return time;
270     }
271     if (time == 0.0) {
272         return 0.0;
273     }
274     if (time >= g_pauseAfterTime && g_pauseAfterTime > 0) {
275         return (static_cast<int64_t>(g_pauseAfterTime) - g_pauseCumulativeTime - g_replayStartTimeNano) *
276             BaseGetPlaybackSpeed() + g_replayStartTimeNano;
277     }
278     return (static_cast<int64_t>(time) - g_pauseCumulativeTime - g_replayStartTimeNano) *
279         BaseGetPlaybackSpeed() + g_replayStartTimeNano;
280 }
281 
PatchTransactionTime(const Parcel & parcel,uint64_t time)282 uint64_t RSProfiler::PatchTransactionTime(const Parcel& parcel, uint64_t time)
283 {
284     if (!IsEnabled()) {
285         return time;
286     }
287 
288     if (!IsReadMode()) {
289         return time;
290     }
291     if (time == 0.0) {
292         return 0.0;
293     }
294     if (!IsParcelMock(parcel)) {
295         return time;
296     }
297 
298     return PatchTime(time + g_transactionTimeCorrection);
299 }
300 
TimePauseAt(uint64_t curTime,uint64_t newPauseAfterTime,bool immediate)301 void RSProfiler::TimePauseAt(uint64_t curTime, uint64_t newPauseAfterTime, bool immediate)
302 {
303     if (g_pauseAfterTime > 0) {
304         // second time pause
305         if (curTime > g_pauseAfterTime) {
306             g_pauseCumulativeTime += static_cast<int64_t>(curTime - g_pauseAfterTime);
307         }
308     }
309     g_pauseAfterTime = newPauseAfterTime;
310     if (immediate) {
311         g_pauseCumulativeTime += static_cast<int64_t>(curTime - g_pauseAfterTime);
312         g_pauseAfterTime = curTime;
313     }
314 }
315 
TimePauseResume(uint64_t curTime)316 void RSProfiler::TimePauseResume(uint64_t curTime)
317 {
318     if (g_pauseAfterTime > 0) {
319         if (curTime > g_pauseAfterTime) {
320             g_pauseCumulativeTime += curTime - g_pauseAfterTime;
321         }
322     }
323     g_pauseAfterTime = 0;
324 }
325 
TimePauseClear()326 void RSProfiler::TimePauseClear()
327 {
328     g_pauseCumulativeTime = 0;
329     g_pauseAfterTime = 0;
330 }
331 
TimePauseGet()332 uint64_t RSProfiler::TimePauseGet()
333 {
334     return g_pauseAfterTime;
335 }
336 
GetDisplayNode(const RSContext & context)337 std::shared_ptr<RSDisplayRenderNode> RSProfiler::GetDisplayNode(const RSContext& context)
338 {
339     const std::shared_ptr<RSBaseRenderNode>& root = context.GetGlobalRootRenderNode();
340     // without these checks device might get stuck on startup
341     if (!root || (root->GetChildrenCount() != 1)) {
342         return nullptr;
343     }
344 
345     return RSBaseRenderNode::ReinterpretCast<RSDisplayRenderNode>(root->GetSortedChildren()->front());
346 }
347 
GetScreenRect(const RSContext & context)348 Vector4f RSProfiler::GetScreenRect(const RSContext& context)
349 {
350     std::shared_ptr<RSDisplayRenderNode> node = GetDisplayNode(context);
351     if (!node) {
352         return {};
353     }
354 
355     const RectI rect = node->GetDirtyManager()->GetSurfaceRect();
356     return { rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom() };
357 }
358 
FilterForPlayback(RSContext & context,pid_t pid)359 void RSProfiler::FilterForPlayback(RSContext& context, pid_t pid)
360 {
361     auto& map = context.GetMutableNodeMap();
362 
363     auto canBeRemoved = [](NodeId node, pid_t pid) -> bool {
364         return (ExtractPid(node) == pid) && (Utils::ExtractNodeId(node) != 1);
365     };
366 
367     // remove all nodes belong to given pid (by matching higher 32 bits of node id)
368     auto iter = map.renderNodeMap_.find(pid);
369     if (iter != map.renderNodeMap_.end()) {
370         auto& subMap = iter->second;
371         EraseIf(subMap, [](const auto& pair) -> bool {
372             if (Utils::ExtractNodeId(pair.first) == 1) {
373                 return false;
374             }
375             // remove node from tree
376             pair.second->RemoveFromTree(false);
377             return true;
378         });
379         if (subMap.empty()) {
380             map.renderNodeMap_.erase(pid);
381         }
382     }
383 
384     EraseIf(
385         map.surfaceNodeMap_, [pid, canBeRemoved](const auto& pair) -> bool { return canBeRemoved(pair.first, pid); });
386 
387     EraseIf(map.residentSurfaceNodeMap_,
388         [pid, canBeRemoved](const auto& pair) -> bool { return canBeRemoved(pair.first, pid); });
389 
390     EraseIf(
391         map.displayNodeMap_, [pid, canBeRemoved](const auto& pair) -> bool { return canBeRemoved(pair.first, pid); });
392 
393     if (auto fallbackNode = map.GetAnimationFallbackNode()) {
394         fallbackNode->GetAnimationManager().FilterAnimationByPid(pid);
395     }
396 }
397 
FilterMockNode(RSContext & context)398 void RSProfiler::FilterMockNode(RSContext& context)
399 {
400     std::unordered_set<pid_t> pidSet;
401 
402     auto& nodeMap = context.GetMutableNodeMap();
403     nodeMap.TraversalNodes([&pidSet](const std::shared_ptr<RSBaseRenderNode>& node) {
404         if (node == nullptr) {
405             return;
406         }
407         if (Utils::IsNodeIdPatched(node->GetId())) {
408             pidSet.insert(Utils::ExtractPid(node->GetId()));
409         }
410     });
411 
412     for (auto pid : pidSet) {
413         nodeMap.FilterNodeByPid(pid);
414     }
415 
416     if (auto fallbackNode = nodeMap.GetAnimationFallbackNode()) {
417         // remove all fallback animations belong to given pid
418         FilterAnimationForPlayback(fallbackNode->GetAnimationManager());
419     }
420 }
421 
GetSurfacesTrees(const RSContext & context,std::map<std::string,std::tuple<NodeId,std::string>> & list)422 void RSProfiler::GetSurfacesTrees(
423     const RSContext& context, std::map<std::string, std::tuple<NodeId, std::string>>& list)
424 {
425     constexpr uint32_t treeDumpDepth = 2;
426 
427     list.clear();
428 
429     const RSRenderNodeMap& map = const_cast<RSContext&>(context).GetMutableNodeMap();
430     for (const auto& [_, subMap] : map.renderNodeMap_) {
431         for (const auto& [_, node] : subMap) {
432             if (node->GetType() == RSRenderNodeType::SURFACE_NODE) {
433                 std::string tree;
434                 node->DumpTree(treeDumpDepth, tree);
435                 const auto surfaceNode = node->ReinterpretCastTo<RSSurfaceRenderNode>();
436                 list.insert({ surfaceNode->GetName(), { surfaceNode->GetId(), tree } });
437             }
438         }
439     }
440 }
441 
GetSurfacesTrees(const RSContext & context,pid_t pid,std::map<NodeId,std::string> & list)442 void RSProfiler::GetSurfacesTrees(const RSContext& context, pid_t pid, std::map<NodeId, std::string>& list)
443 {
444     constexpr uint32_t treeDumpDepth = 2;
445 
446     list.clear();
447 
448     const RSRenderNodeMap& map = const_cast<RSContext&>(context).GetMutableNodeMap();
449     for (const auto& [_, subMap] : map.renderNodeMap_) {
450         for (const auto& [_, node] : subMap) {
451             if (node->GetId() == Utils::GetRootNodeId(pid)) {
452                 std::string tree;
453                 node->DumpTree(treeDumpDepth, tree);
454                 list.insert({ node->GetId(), tree });
455             }
456         }
457     }
458 }
459 
GetRenderNodeCount(const RSContext & context)460 size_t RSProfiler::GetRenderNodeCount(const RSContext& context)
461 {
462     return const_cast<RSContext&>(context).GetMutableNodeMap().GetSize();
463 }
464 
GetRandomSurfaceNode(const RSContext & context)465 NodeId RSProfiler::GetRandomSurfaceNode(const RSContext& context)
466 {
467     const RSRenderNodeMap& map = const_cast<RSContext&>(context).GetMutableNodeMap();
468     for (const auto& item : map.surfaceNodeMap_) {
469         return item.first;
470     }
471     return 0;
472 }
473 
MarshalNodes(const RSContext & context,std::stringstream & data,uint32_t fileVersion)474 void RSProfiler::MarshalNodes(const RSContext& context, std::stringstream& data, uint32_t fileVersion)
475 {
476     const auto& map = const_cast<RSContext&>(context).GetMutableNodeMap();
477     const uint32_t count = static_cast<uint32_t>(map.GetSize());
478     data.write(reinterpret_cast<const char*>(&count), sizeof(count));
479     const auto& rootRenderNode = context.GetGlobalRootRenderNode();
480     if (rootRenderNode == nullptr) {
481         RS_LOGE("RSProfiler::MarshalNodes rootRenderNode is nullptr");
482         return;
483     }
484 
485     std::vector<std::shared_ptr<RSRenderNode>> nodes;
486     nodes.emplace_back(rootRenderNode);
487 
488     for (const auto& [_, subMap] : map.renderNodeMap_) {
489         for (const auto& [_, node] : subMap) {
490             if (node != nullptr) {
491                 MarshalNode(*node, data, fileVersion);
492                 std::shared_ptr<RSRenderNode> parent = node->GetParent().lock();
493                 if (!parent && (node != rootRenderNode)) {
494                     nodes.emplace_back(node);
495                 }
496             }
497         }
498     }
499 
500     const uint32_t nodeCount = static_cast<uint32_t>(nodes.size());
501     data.write(reinterpret_cast<const char*>(&nodeCount), sizeof(nodeCount));
502     for (const auto& node : nodes) { // no nullptr in nodes, omit check
503         MarshalTree(*node, data, fileVersion);
504     }
505 }
506 
MarshalTree(const RSRenderNode & node,std::stringstream & data,uint32_t fileVersion)507 void RSProfiler::MarshalTree(const RSRenderNode& node, std::stringstream& data, uint32_t fileVersion)
508 {
509     const NodeId nodeId = node.GetId();
510     data.write(reinterpret_cast<const char*>(&nodeId), sizeof(nodeId));
511 
512     const uint32_t count = node.children_.size();
513     data.write(reinterpret_cast<const char*>(&count), sizeof(count));
514 
515     for (const auto& child : node.children_) {
516         if (auto node = child.lock().get()) {
517             const NodeId nodeId = node->GetId();
518             data.write(reinterpret_cast<const char*>(&nodeId), sizeof(nodeId));
519             MarshalTree(*node, data, fileVersion);
520         }
521     }
522 }
523 
MarshalNode(const RSRenderNode & node,std::stringstream & data,uint32_t fileVersion)524 void RSProfiler::MarshalNode(const RSRenderNode& node, std::stringstream& data, uint32_t fileVersion)
525 {
526     const RSRenderNodeType nodeType = node.GetType();
527     data.write(reinterpret_cast<const char*>(&nodeType), sizeof(nodeType));
528 
529     const NodeId nodeId = node.GetId();
530     data.write(reinterpret_cast<const char*>(&nodeId), sizeof(nodeId));
531 
532     const bool isTextureExportNode = node.GetIsTextureExportNode();
533     data.write(reinterpret_cast<const char*>(&isTextureExportNode), sizeof(isTextureExportNode));
534 
535     if (node.GetType() == RSRenderNodeType::SURFACE_NODE) {
536         const auto& surfaceNode = reinterpret_cast<const RSSurfaceRenderNode&>(node);
537         const std::string name = surfaceNode.GetName();
538         uint32_t size = name.size();
539         data.write(reinterpret_cast<const char*>(&size), sizeof(size));
540         data.write(reinterpret_cast<const char*>(name.c_str()), size);
541 
542         const std::string bundleName = "";
543         size = bundleName.size();
544         data.write(reinterpret_cast<const char*>(&size), sizeof(size));
545         data.write(reinterpret_cast<const char*>(bundleName.c_str()), size);
546 
547         const RSSurfaceNodeType type = surfaceNode.GetSurfaceNodeType();
548         data.write(reinterpret_cast<const char*>(&type), sizeof(type));
549 
550         const uint8_t backgroundAlpha = surfaceNode.GetAbilityBgAlpha();
551         data.write(reinterpret_cast<const char*>(&backgroundAlpha), sizeof(backgroundAlpha));
552 
553         const uint8_t globalAlpha = surfaceNode.GetGlobalAlpha();
554         data.write(reinterpret_cast<const char*>(&globalAlpha), sizeof(globalAlpha));
555     }
556 
557     const float positionZ = node.GetRenderProperties().GetPositionZ();
558     data.write(reinterpret_cast<const char*>(&positionZ), sizeof(positionZ));
559 
560     const float pivotZ = node.GetRenderProperties().GetPivotZ();
561     data.write(reinterpret_cast<const char*>(&pivotZ), sizeof(pivotZ));
562 
563     const NodePriorityType priority = const_cast<RSRenderNode&>(node).GetPriority();
564     data.write(reinterpret_cast<const char*>(&priority), sizeof(priority));
565 
566     const bool isOnTree = node.IsOnTheTree();
567     data.write(reinterpret_cast<const char*>(&isOnTree), sizeof(isOnTree));
568 
569     if (fileVersion >= RSFILE_VERSION_RENDER_METRICS_ADDED) {
570         const uint8_t nodeGroupType = node.nodeGroupType_;
571         data.write(reinterpret_cast<const char*>(&nodeGroupType), sizeof(nodeGroupType));
572     }
573 
574     MarshalNodeModifiers(node, data, fileVersion);
575 }
576 
MarshalRenderModifier(const RSRenderModifier & modifier,std::stringstream & data)577 static void MarshalRenderModifier(const RSRenderModifier& modifier, std::stringstream& data)
578 {
579     Parcel parcel;
580     parcel.SetMaxCapacity(GetParcelMaxCapacity());
581     const_cast<RSRenderModifier&>(modifier).Marshalling(parcel);
582 
583     const size_t dataSize = parcel.GetDataSize();
584     data.write(reinterpret_cast<const char*>(&dataSize), sizeof(dataSize));
585     data.write(reinterpret_cast<const char*>(parcel.GetData()), dataSize);
586 
587     // Remove all file descriptors
588     binder_size_t* object = reinterpret_cast<binder_size_t*>(parcel.GetObjectOffsets());
589     size_t objectNum = parcel.GetOffsetsSize();
590     uintptr_t parcelData = parcel.GetData();
591 
592     const size_t maxObjectNum = INT_MAX;
593     if (!object || (objectNum > maxObjectNum)) {
594         return;
595     }
596 
597     for (size_t i = 0; i < objectNum; i++) {
598         const flat_binder_object* flat = reinterpret_cast<flat_binder_object*>(parcelData + object[i]);
599         if (!flat) {
600             return;
601         }
602         if (flat->hdr.type == BINDER_TYPE_FD && flat->handle > 0) {
603             ::close(flat->handle);
604         }
605     }
606 }
607 
MarshalDrawCmdModifiers(const RSRenderContent::DrawCmdContainer & container,std::stringstream & data,uint32_t fileVersion)608 static void MarshalDrawCmdModifiers(
609     const RSRenderContent::DrawCmdContainer& container, std::stringstream& data, uint32_t fileVersion)
610 {
611     const uint32_t drawModifierCount = container.size();
612     data.write(reinterpret_cast<const char*>(&drawModifierCount), sizeof(drawModifierCount));
613 
614     for (const auto& [type, modifiers] : container) {
615         const uint32_t modifierCount = modifiers.size();
616         data.write(reinterpret_cast<const char*>(&modifierCount), sizeof(modifierCount));
617         for (const auto& modifier : modifiers) {
618             if (!modifier) {
619                 continue;
620             }
621             if (auto commandList = reinterpret_cast<Drawing::DrawCmdList*>(modifier->GetDrawCmdListId())) {
622                 std::string allocData = commandList->ProfilerPushAllocators();
623                 commandList->MarshallingDrawOps();
624                 MarshalRenderModifier(*modifier, data);
625                 commandList->ProfilerPopAllocators(allocData);
626             } else {
627                 MarshalRenderModifier(*modifier, data);
628             }
629         }
630     }
631 }
632 
GetDrawCmdModifiers(const RSCanvasDrawingRenderNode & node)633 static RSRenderContent::DrawCmdContainer GetDrawCmdModifiers(const RSCanvasDrawingRenderNode& node)
634 {
635     const auto drawable = node.GetRenderDrawable();
636     auto image = drawable ? drawable->Snapshot() : nullptr;
637     if (!image) {
638         return node.GetDrawCmdModifiers();
639     }
640 
641     const int32_t width = image->GetWidth();
642     const int32_t height = image->GetHeight();
643 
644     const Drawing::Rect rect(0, 0, static_cast<float>(width), static_cast<float>(height));
645     auto drawOp = std::make_shared<Drawing::DrawImageRectOpItem>(*image, rect, rect,
646         Drawing::SamplingOptions(Drawing::FilterMode::LINEAR, Drawing::MipmapMode::LINEAR),
647         Drawing::SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT, Drawing::Paint());
648 
649     auto cmdList = std::make_shared<Drawing::DrawCmdList>(width, height, Drawing::DrawCmdList::UnmarshalMode::DEFERRED);
650     cmdList->AddDrawOp(drawOp);
651 
652     auto property = std::make_shared<RSRenderProperty<Drawing::DrawCmdListPtr>>(cmdList, 0);
653     auto modifier = std::make_shared<RSDrawCmdListRenderModifier>(property);
654     modifier->SetType(RSModifierType::CONTENT_STYLE);
655 
656     RSRenderContent::DrawCmdContainer container = node.GetDrawCmdModifiers();
657     container[modifier->GetType()].emplace_back(modifier);
658     return container;
659 }
660 
MarshalNodeModifiers(const RSRenderNode & node,std::stringstream & data,uint32_t fileVersion)661 void RSProfiler::MarshalNodeModifiers(const RSRenderNode& node, std::stringstream& data, uint32_t fileVersion)
662 {
663     data.write(reinterpret_cast<const char*>(&node.instanceRootNodeId_), sizeof(node.instanceRootNodeId_));
664     data.write(reinterpret_cast<const char*>(&node.firstLevelNodeId_), sizeof(node.firstLevelNodeId_));
665 
666     const uint32_t modifierCount = node.modifiers_.size();
667     data.write(reinterpret_cast<const char*>(&modifierCount), sizeof(modifierCount));
668 
669     for (const auto& [id, modifier] : node.modifiers_) {
670         if (modifier) {
671             MarshalRenderModifier(*modifier, data);
672         }
673     }
674 
675     if (node.GetType () == RSRenderNodeType::CANVAS_DRAWING_NODE) {
676         auto& canvasDrawingNode = static_cast<const RSCanvasDrawingRenderNode&>(node);
677         MarshalDrawCmdModifiers(GetDrawCmdModifiers(canvasDrawingNode), data, fileVersion);
678     } else {
679         MarshalDrawCmdModifiers(node.GetDrawCmdModifiers(), data, fileVersion);
680     }
681 }
682 
CreateRenderSurfaceNode(RSContext & context,NodeId id,bool isTextureExportNode,std::stringstream & data)683 static std::string CreateRenderSurfaceNode(RSContext& context,
684                                            NodeId id,
685                                            bool isTextureExportNode,
686                                            std::stringstream& data)
687 {
688     constexpr uint32_t nameSizeMax = 4096;
689     uint32_t size = 0u;
690     data.read(reinterpret_cast<char*>(&size), sizeof(size));
691     if (size > nameSizeMax) {
692         return "CreateRenderSurfaceNode unmarshalling failed, file is damaged";
693     }
694 
695     std::string name;
696     name.resize(size, ' ');
697     data.read(reinterpret_cast<char*>(name.data()), size);
698 
699     data.read(reinterpret_cast<char*>(&size), sizeof(size));
700     if (size > nameSizeMax) {
701         return "CreateRenderSurfaceNode unmarshalling failed, file is damaged";
702     }
703     std::string bundleName;
704     bundleName.resize(size, ' ');
705     data.read(reinterpret_cast<char*>(bundleName.data()), size);
706 
707     RSSurfaceNodeType nodeType = RSSurfaceNodeType::DEFAULT;
708     data.read(reinterpret_cast<char*>(&nodeType), sizeof(nodeType));
709 
710     uint8_t backgroundAlpha = 0u;
711     data.read(reinterpret_cast<char*>(&backgroundAlpha), sizeof(backgroundAlpha));
712 
713     uint8_t globalAlpha = 0u;
714     data.read(reinterpret_cast<char*>(&globalAlpha), sizeof(globalAlpha));
715 
716     const RSSurfaceRenderNodeConfig config = { .id = id,
717         .name = name + "_",
718         .nodeType = nodeType,
719         .additionalData = nullptr,
720         .isTextureExportNode = isTextureExportNode,
721         .isSync = false };
722 
723     if (auto node = SurfaceNodeCommandHelper::CreateWithConfigInRS(config, context)) {
724         context.GetMutableNodeMap().RegisterRenderNode(node);
725         node->SetAbilityBGAlpha(backgroundAlpha);
726         node->SetGlobalAlpha(globalAlpha);
727     }
728     return "";
729 }
730 
UnmarshalNodes(RSContext & context,std::stringstream & data,uint32_t fileVersion)731 std::string RSProfiler::UnmarshalNodes(RSContext& context, std::stringstream& data, uint32_t fileVersion)
732 {
733     std::string errReason;
734 
735     uint32_t count = 0;
736     data.read(reinterpret_cast<char*>(&count), sizeof(count));
737     for (uint32_t i = 0; i < count; i++) {
738         errReason = UnmarshalNode(context, data, fileVersion);
739         if (errReason.size()) {
740             return errReason;
741         }
742     }
743 
744     data.read(reinterpret_cast<char*>(&count), sizeof(count));
745     for (uint32_t i = 0; i < count; i++) {
746         errReason = UnmarshalTree(context, data, fileVersion);
747         if (errReason.size()) {
748             return errReason;
749         }
750     }
751 
752     auto& nodeMap = context.GetMutableNodeMap();
753     nodeMap.TraversalNodes([](const std::shared_ptr<RSBaseRenderNode>& node) {
754         if (node == nullptr) {
755             return;
756         }
757         if (Utils::IsNodeIdPatched(node->GetId())) {
758             node->SetContentDirty();
759             node->SetDirty();
760         }
761     });
762 
763     return "";
764 }
765 
UnmarshalNode(RSContext & context,std::stringstream & data,uint32_t fileVersion)766 std::string RSProfiler::UnmarshalNode(RSContext& context, std::stringstream& data, uint32_t fileVersion)
767 {
768     RSRenderNodeType nodeType = RSRenderNodeType::UNKNOW;
769     data.read(reinterpret_cast<char*>(&nodeType), sizeof(nodeType));
770 
771     NodeId nodeId = 0;
772     data.read(reinterpret_cast<char*>(&nodeId), sizeof(nodeId));
773     nodeId = Utils::PatchNodeId(nodeId);
774 
775     bool isTextureExportNode = false;
776     data.read(reinterpret_cast<char*>(&isTextureExportNode), sizeof(isTextureExportNode));
777 
778     if (data.eof()) {
779         return "UnmarshalNode failed, file is damaged";
780     }
781 
782     if (nodeType == RSRenderNodeType::RS_NODE) {
783         RootNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
784     } else if (nodeType == RSRenderNodeType::DISPLAY_NODE) {
785         RootNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
786     } else if (nodeType == RSRenderNodeType::SURFACE_NODE) {
787         std::string errReason = CreateRenderSurfaceNode(context, nodeId, isTextureExportNode, data);
788         if (errReason.size()) {
789             return errReason;
790         }
791     } else if (nodeType == RSRenderNodeType::PROXY_NODE) {
792         ProxyNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
793     } else if (nodeType == RSRenderNodeType::CANVAS_NODE) {
794         RSCanvasNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
795     } else if (nodeType == RSRenderNodeType::EFFECT_NODE) {
796         EffectNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
797     } else if (nodeType == RSRenderNodeType::ROOT_NODE) {
798         RootNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
799     } else if (nodeType == RSRenderNodeType::CANVAS_DRAWING_NODE) {
800         RSCanvasDrawingNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
801     } else {
802         RootNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
803     }
804 
805     return UnmarshalNode(context, data, nodeId, fileVersion);
806 }
807 
UnmarshalNode(RSContext & context,std::stringstream & data,NodeId nodeId,uint32_t fileVersion)808 std::string RSProfiler::UnmarshalNode(RSContext& context, std::stringstream& data, NodeId nodeId, uint32_t fileVersion)
809 {
810     float positionZ = 0.0f;
811     data.read(reinterpret_cast<char*>(&positionZ), sizeof(positionZ));
812     float pivotZ = 0.0f;
813     data.read(reinterpret_cast<char*>(&pivotZ), sizeof(pivotZ));
814     NodePriorityType priority = NodePriorityType::MAIN_PRIORITY;
815     data.read(reinterpret_cast<char*>(&priority), sizeof(priority));
816     bool isOnTree = false;
817     data.read(reinterpret_cast<char*>(&isOnTree), sizeof(isOnTree));
818 
819     uint8_t nodeGroupType = 0;
820     if (fileVersion >= RSFILE_VERSION_RENDER_METRICS_ADDED) {
821         data.read(reinterpret_cast<char*>(&nodeGroupType), sizeof(nodeGroupType));
822     }
823 
824     if (auto node = context.GetMutableNodeMap().GetRenderNode(nodeId)) {
825         node->GetMutableRenderProperties().SetPositionZ(positionZ);
826         node->GetMutableRenderProperties().SetPivotZ(pivotZ);
827         node->SetPriority(priority);
828         node->RSRenderNode::SetIsOnTheTree(isOnTree);
829         node->nodeGroupType_ = nodeGroupType;
830         return UnmarshalNodeModifiers(*node, data, fileVersion);
831     }
832     return "";
833 }
834 
UnmarshalRenderModifier(std::stringstream & data,std::string & errReason)835 static RSRenderModifier* UnmarshalRenderModifier(std::stringstream& data, std::string& errReason)
836 {
837     errReason = "";
838 
839     constexpr size_t bufferSizeMax = 50'000'000;
840     size_t bufferSize = 0;
841     data.read(reinterpret_cast<char*>(&bufferSize), sizeof(bufferSize));
842     if (bufferSize > bufferSizeMax) {
843         errReason = "UnmarshalRenderModifier failed, file is damaged";
844         return nullptr;
845     }
846 
847     std::vector<uint8_t> buffer;
848     buffer.resize(bufferSize);
849     data.read(reinterpret_cast<char*>(buffer.data()), buffer.size());
850     if (data.eof()) {
851         errReason = "UnmarshalRenderModifier failed, file is damaged";
852         return nullptr;
853     }
854 
855     uint8_t parcelMemory[sizeof(Parcel) + 1];
856     auto* parcel = new (parcelMemory + 1) Parcel;
857     parcel->SetMaxCapacity(GetParcelMaxCapacity());
858     parcel->WriteBuffer(buffer.data(), buffer.size());
859 
860     auto ptr = RSRenderModifier::Unmarshalling(*parcel);
861     if (!ptr) {
862         constexpr size_t minBufferSize = 2;
863         if (buffer.size() >= minBufferSize) {
864             const auto typeModifier = *(reinterpret_cast<RSModifierType *>(&buffer[0]));
865             errReason = RSModifierTypeString().GetModifierTypeString(typeModifier);
866         } else {
867             errReason = "RSRenderModifier buffer too short";
868         }
869         errReason += ", size=" + std::to_string(buffer.size());
870     }
871 
872     return ptr;
873 }
874 
SetupCanvasDrawingRenderNode(RSCanvasDrawingRenderNode & node)875 static void SetupCanvasDrawingRenderNode(RSCanvasDrawingRenderNode& node)
876 {
877     int32_t width = 0;
878     int32_t height = 0;
879     for (const auto& [type, modifiers] : node.GetDrawCmdModifiers()) {
880         for (const auto& modifier : modifiers) {
881             const auto commandList = modifier ? modifier->GetPropertyDrawCmdList() : nullptr;
882             if (commandList) {
883                 width = std::max(width, commandList->GetWidth());
884                 height = std::max(height, commandList->GetHeight());
885             }
886         }
887     }
888 
889     node.ResetSurface(width, height);
890 }
891 
UnmarshalNodeModifiers(RSRenderNode & node,std::stringstream & data,uint32_t fileVersion)892 std::string RSProfiler::UnmarshalNodeModifiers(RSRenderNode& node, std::stringstream& data, uint32_t fileVersion)
893 {
894     data.read(reinterpret_cast<char*>(&node.instanceRootNodeId_), sizeof(node.instanceRootNodeId_));
895     node.instanceRootNodeId_ = Utils::PatchNodeId(node.instanceRootNodeId_);
896 
897     data.read(reinterpret_cast<char*>(&node.firstLevelNodeId_), sizeof(node.firstLevelNodeId_));
898     node.firstLevelNodeId_ = Utils::PatchNodeId(node.firstLevelNodeId_);
899 
900     int32_t modifierCount = 0;
901     data.read(reinterpret_cast<char*>(&modifierCount), sizeof(modifierCount));
902     for (int32_t i = 0; i < modifierCount; i++) {
903         std::string errModifierCode = "";
904         auto ptr = UnmarshalRenderModifier(data, errModifierCode);
905         if (!ptr) {
906             return "Modifier format changed [" + errModifierCode + "]";
907         }
908         node.AddModifier(std::shared_ptr<RSRenderModifier>(ptr));
909     }
910 
911     uint32_t drawModifierCount = 0u;
912     data.read(reinterpret_cast<char*>(&drawModifierCount), sizeof(drawModifierCount));
913     for (uint32_t i = 0; i < drawModifierCount; i++) {
914         uint32_t modifierCount = 0u;
915         data.read(reinterpret_cast<char*>(&modifierCount), sizeof(modifierCount));
916         for (uint32_t j = 0; j < modifierCount; j++) {
917             std::string errModifierCode = "";
918             auto ptr = UnmarshalRenderModifier(data, errModifierCode);
919             if (!ptr) {
920                 return "DrawModifier format changed [" + errModifierCode + "]";
921             }
922             node.AddModifier(std::shared_ptr<RSRenderModifier>(ptr));
923         }
924     }
925     if (data.eof()) {
926         return "UnmarshalNodeModifiers failed, file is damaged";
927     }
928 
929     if (node.GetType() == RSRenderNodeType::CANVAS_DRAWING_NODE) {
930         SetupCanvasDrawingRenderNode(static_cast<RSCanvasDrawingRenderNode&>(node));
931     }
932 
933     node.ApplyModifiers();
934     return "";
935 }
936 
UnmarshalTree(RSContext & context,std::stringstream & data,uint32_t fileVersion)937 std::string RSProfiler::UnmarshalTree(RSContext& context, std::stringstream& data, uint32_t fileVersion)
938 {
939     const auto& map = context.GetMutableNodeMap();
940 
941     NodeId nodeId = 0;
942     data.read(reinterpret_cast<char*>(&nodeId), sizeof(nodeId));
943     nodeId = Utils::PatchNodeId(nodeId);
944 
945     uint32_t count = 0;
946     data.read(reinterpret_cast<char*>(&count), sizeof(count));
947 
948     auto node = map.GetRenderNode(nodeId);
949     if (!node) {
950         return "Error nodeId was not found";
951     }
952     for (uint32_t i = 0; i < count; i++) {
953         NodeId nodeId = 0;
954         data.read(reinterpret_cast<char*>(&nodeId), sizeof(nodeId));
955         if (node) {
956             node->AddChild(map.GetRenderNode(Utils::PatchNodeId(nodeId)), i);
957         }
958         UnmarshalTree(context, data, fileVersion);
959     }
960     return "";
961 }
962 
DumpRenderProperties(const RSRenderNode & node)963 std::string RSProfiler::DumpRenderProperties(const RSRenderNode& node)
964 {
965     if (node.renderContent_) {
966         return node.renderContent_->renderProperties_.Dump();
967     }
968     return "";
969 }
970 
DumpModifiers(const RSRenderNode & node)971 std::string RSProfiler::DumpModifiers(const RSRenderNode& node)
972 {
973     if (!node.renderContent_) {
974         return "";
975     }
976 
977     std::string out;
978     out += "<";
979 
980     for (auto& [type, modifiers] : node.renderContent_->drawCmdModifiers_) {
981         out += "(";
982         out += std::to_string(static_cast<int32_t>(type));
983         out += ", ";
984         for (auto& item : modifiers) {
985             out += "[";
986             const auto propertyId = item->GetPropertyId();
987             out += std::to_string(Utils::ExtractPid(propertyId));
988             out += "|";
989             out += std::to_string(Utils::ExtractNodeId(propertyId));
990             out += " type=";
991             out += std::to_string(static_cast<int32_t>(item->GetType()));
992             out += " [modifier dump is not implemented yet]";
993             out += "]";
994         }
995         out += ")";
996     }
997 
998     out += ">";
999     return out;
1000 }
1001 
DumpSurfaceNode(const RSRenderNode & node)1002 std::string RSProfiler::DumpSurfaceNode(const RSRenderNode& node)
1003 {
1004     if (node.GetType() != RSRenderNodeType::SURFACE_NODE) {
1005         return "";
1006     }
1007 
1008     std::string out;
1009     const auto& surfaceNode = (static_cast<const RSSurfaceRenderNode&>(node));
1010     const auto parent = node.parent_.lock();
1011     out += ", Parent [" + (parent ? std::to_string(parent->GetId()) : "null") + "]";
1012     out += ", Name [" + surfaceNode.GetName() + "]";
1013     if (surfaceNode.GetRSSurfaceHandler()) {
1014         out += ", hasConsumer: " + std::to_string(surfaceNode.GetRSSurfaceHandler()->HasConsumer());
1015     }
1016     std::string contextAlpha = std::to_string(surfaceNode.contextAlpha_);
1017     std::string propertyAlpha = std::to_string(surfaceNode.GetRenderProperties().GetAlpha());
1018     out += ", Alpha: " + propertyAlpha + " (include ContextAlpha: " + contextAlpha + ")";
1019     out += ", Visible: " + std::to_string(surfaceNode.GetRenderProperties().GetVisible());
1020     out += ", " + surfaceNode.GetVisibleRegion().GetRegionInfo();
1021     out += ", OcclusionBg: " + std::to_string(surfaceNode.GetAbilityBgAlpha());
1022     out += ", Properties: " + node.GetRenderProperties().Dump();
1023     return out;
1024 }
1025 
1026 // RSAnimationManager
FilterAnimationForPlayback(RSAnimationManager & manager)1027 void RSProfiler::FilterAnimationForPlayback(RSAnimationManager& manager)
1028 {
1029     EraseIf(manager.animations_, [](const auto& pair) -> bool {
1030         if (!Utils::IsNodeIdPatched(pair.first)) {
1031             return false;
1032         }
1033         pair.second->Finish();
1034         pair.second->Detach();
1035         return true;
1036     });
1037 }
1038 
SetTransactionTimeCorrection(double replayStartTime,double recordStartTime)1039 void RSProfiler::SetTransactionTimeCorrection(double replayStartTime, double recordStartTime)
1040 {
1041     g_transactionTimeCorrection = static_cast<int64_t>((replayStartTime - recordStartTime) * NS_TO_S);
1042     g_replayStartTimeNano = replayStartTime * NS_TO_S;
1043 }
1044 
GetParcelCommandList()1045 std::string RSProfiler::GetParcelCommandList()
1046 {
1047     const std::lock_guard<std::mutex> guard(g_mutexCommandOffsets);
1048     if (g_parcelNumber2Offset.size()) {
1049         const auto it = g_parcelNumber2Offset.begin();
1050         std::stringstream stream(std::ios::in | std::ios::out | std::ios::binary);
1051         stream.write(reinterpret_cast<const char*>(&it->first), sizeof(it->first));
1052         stream.write(reinterpret_cast<const char*>(it->second.data()), it->second.size() * sizeof(uint32_t));
1053         g_parcelNumber2Offset.erase(it);
1054         return stream.str();
1055     }
1056     return "";
1057 }
1058 
PushOffset(std::vector<uint32_t> & commandOffsets,uint32_t offset)1059 void RSProfiler::PushOffset(std::vector<uint32_t>& commandOffsets, uint32_t offset)
1060 {
1061     if (!IsEnabled()) {
1062         return;
1063     }
1064     if (IsWriteMode()) {
1065         commandOffsets.push_back(offset);
1066     }
1067 }
1068 
PushOffsets(const Parcel & parcel,uint32_t parcelNumber,std::vector<uint32_t> & commandOffsets)1069 void RSProfiler::PushOffsets(const Parcel& parcel, uint32_t parcelNumber, std::vector<uint32_t>& commandOffsets)
1070 {
1071     if (!IsEnabled()) {
1072         return;
1073     }
1074     if (!parcelNumber) {
1075         return;
1076     }
1077     if (IsWriteMode()) {
1078         const std::lock_guard<std::mutex> guard(g_mutexCommandOffsets);
1079         g_parcelNumber2Offset[parcelNumber] = commandOffsets;
1080     }
1081 }
1082 
PatchCommand(const Parcel & parcel,RSCommand * command)1083 void RSProfiler::PatchCommand(const Parcel& parcel, RSCommand* command)
1084 {
1085     if (!IsEnabled()) {
1086         return;
1087     }
1088     if (command == nullptr) {
1089         return;
1090     }
1091 
1092     if (command && IsParcelMock(parcel)) {
1093         command->Patch(Utils::PatchNodeId);
1094     }
1095 
1096     if (IsWriteMode()) {
1097         g_commandCount++;
1098     }
1099 }
1100 
ExecuteCommand(const RSCommand * command)1101 void RSProfiler::ExecuteCommand(const RSCommand* command)
1102 {
1103     if (!IsEnabled()) {
1104         return;
1105     }
1106     if (!IsWriteMode() && !IsReadMode()) {
1107         return;
1108     }
1109     if (command == nullptr) {
1110         return;
1111     }
1112 
1113     g_commandExecuteCount++;
1114 }
1115 
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)1116 uint32_t RSProfiler::PerfTreeFlatten(const std::shared_ptr<RSRenderNode> node,
1117     std::vector<std::pair<NodeId, uint32_t>>& nodeSet,
1118     std::unordered_map<NodeId, uint32_t>& mapNode2Count, uint32_t depth)
1119 {
1120     if (!node) {
1121         return 0;
1122     }
1123 
1124     constexpr uint32_t depthToAnalyze = 10;
1125     uint32_t drawCmdListCount = CalcNodeCmdListCount(*node);
1126     if (node->GetSortedChildren()) {
1127         uint32_t valuableChildrenCount = 0;
1128         for (auto& child : *node->GetSortedChildren()) {
1129             if (child && child->GetType() != RSRenderNodeType::EFFECT_NODE && depth < depthToAnalyze) {
1130                 nodeSet.emplace_back(child->id_, depth + 1);
1131             }
1132         }
1133         for (auto& child : *node->GetSortedChildren()) {
1134             if (child) {
1135                 drawCmdListCount += PerfTreeFlatten(child, nodeSet, mapNode2Count, depth + 1);
1136                 valuableChildrenCount++;
1137             }
1138         }
1139     }
1140 
1141     if (drawCmdListCount > 0) {
1142         mapNode2Count[node->id_] = drawCmdListCount;
1143     }
1144     return drawCmdListCount;
1145 }
1146 
CalcNodeCmdListCount(RSRenderNode & node)1147 uint32_t RSProfiler::CalcNodeCmdListCount(RSRenderNode& node)
1148 {
1149     if (!node.renderContent_) {
1150         return 0;
1151     }
1152 
1153     uint32_t nodeCmdListCount = 0;
1154     for (auto& [type, modifiers] : node.renderContent_->drawCmdModifiers_) {
1155         if (type >= RSModifierType::ENV_FOREGROUND_COLOR) {
1156             continue;
1157         }
1158         for (auto& modifier : modifiers) {
1159             auto propertyPtr =
1160                 modifier ? std::static_pointer_cast<RSRenderProperty<Drawing::DrawCmdListPtr>>(modifier->GetProperty())
1161                          : nullptr;
1162             auto propertyValue = propertyPtr ? propertyPtr->Get() : nullptr;
1163             if (propertyValue && propertyValue->GetOpItemSize() > 0) {
1164                 nodeCmdListCount = 1;
1165             }
1166         }
1167     }
1168     return nodeCmdListCount;
1169 }
1170 
MarshalDrawingImage(std::shared_ptr<Drawing::Image> & image,std::shared_ptr<Drawing::Data> & compressData)1171 void RSProfiler::MarshalDrawingImage(std::shared_ptr<Drawing::Image>& image,
1172     std::shared_ptr<Drawing::Data>& compressData)
1173 {
1174     if (IsEnabled() && !IsSharedMemoryEnabled()) {
1175         image = nullptr;
1176         compressData = nullptr;
1177     }
1178 }
1179 
EnableBetaRecord()1180 void RSProfiler::EnableBetaRecord()
1181 {
1182     RSSystemProperties::SetBetaRecordingMode(1);
1183 }
1184 
IsBetaRecordSavingTriggered()1185 bool RSProfiler::IsBetaRecordSavingTriggered()
1186 {
1187     constexpr uint32_t savingMode = 2u;
1188     return RSSystemProperties::GetBetaRecordingMode() == savingMode;
1189 }
1190 
IsBetaRecordEnabledWithMetrics()1191 bool RSProfiler::IsBetaRecordEnabledWithMetrics()
1192 {
1193     constexpr uint32_t metricsMode = 3u;
1194     return RSSystemProperties::GetBetaRecordingMode() == metricsMode;
1195 }
1196 
SetDrawingCanvasNodeRedraw(bool enable)1197 void RSProfiler::SetDrawingCanvasNodeRedraw(bool enable)
1198 {
1199     dcnRedraw_ = enable && IsEnabled();
1200 }
1201 
DrawingNodeAddClearOp(const std::shared_ptr<Drawing::DrawCmdList> & drawCmdList)1202 void RSProfiler::DrawingNodeAddClearOp(const std::shared_ptr<Drawing::DrawCmdList>& drawCmdList)
1203 {
1204     if (dcnRedraw_ || !drawCmdList) {
1205         return;
1206     }
1207     drawCmdList->ClearOp();
1208 }
1209 
NewAshmemDataCacheId()1210 static uint64_t NewAshmemDataCacheId()
1211 {
1212     static std::atomic_uint32_t id = 0u;
1213     return Utils::ComposeDataId(Utils::GetPid(), id++);
1214 }
1215 
CacheAshmemData(uint64_t id,const uint8_t * data,size_t size)1216 static void CacheAshmemData(uint64_t id, const uint8_t* data, size_t size)
1217 {
1218     if (RSProfiler::IsWriteMode() && data && (size > 0)) {
1219         Image ashmem;
1220         ashmem.data.insert(ashmem.data.end(), data, data + size);
1221         ImageCache::Add(id, std::move(ashmem));
1222     }
1223 }
1224 
GetCachedAshmemData(uint64_t id)1225 static const uint8_t* GetCachedAshmemData(uint64_t id)
1226 {
1227     const auto ashmem = RSProfiler::IsReadMode() ? ImageCache::Get(id) : nullptr;
1228     return ashmem ? ashmem->data.data() : nullptr;
1229 }
1230 
WriteParcelData(Parcel & parcel)1231 void RSProfiler::WriteParcelData(Parcel& parcel)
1232 {
1233     bool isClientEnabled = RSSystemProperties::GetProfilerEnabled();
1234     if (!parcel.WriteBool(isClientEnabled)) {
1235         HRPE("Unable to write is_client_enabled");
1236         return;
1237     }
1238 
1239     if (!isClientEnabled) {
1240         return;
1241     }
1242 
1243     if (!parcel.WriteUint64(NewAshmemDataCacheId())) {
1244         HRPE("Unable to write NewAshmemDataCacheId failed");
1245         return;
1246     }
1247 }
1248 
ReadParcelData(Parcel & parcel,size_t size,bool & isMalloc)1249 const void* RSProfiler::ReadParcelData(Parcel& parcel, size_t size, bool& isMalloc)
1250 {
1251     bool isClientEnabled = false;
1252     if (!parcel.ReadBool(isClientEnabled)) {
1253         HRPE("Unable to read is_client_enabled");
1254         return nullptr;
1255     }
1256     if (!isClientEnabled) {
1257         return RSMarshallingHelper::ReadFromAshmem(parcel, size, isMalloc);
1258     }
1259 
1260     const uint64_t id = parcel.ReadUint64();
1261     if (auto data = GetCachedAshmemData(id)) {
1262         constexpr uint32_t skipBytes = 24u;
1263         parcel.SkipBytes(skipBytes);
1264         isMalloc = false;
1265         return data;
1266     }
1267 
1268     auto data = RSMarshallingHelper::ReadFromAshmem(parcel, size, isMalloc);
1269     CacheAshmemData(id, reinterpret_cast<const uint8_t*>(data), size);
1270     return data;
1271 }
1272 
SkipParcelData(Parcel & parcel,size_t size)1273 bool RSProfiler::SkipParcelData(Parcel& parcel, size_t size)
1274 {
1275     bool isClientEnabled = false;
1276     if (!parcel.ReadBool(isClientEnabled)) {
1277         HRPE("RSProfiler::SkipParcelData read isClientEnabled failed");
1278         return false;
1279     }
1280     if (!isClientEnabled) {
1281         return false;
1282     }
1283 
1284     [[maybe_unused]] const uint64_t id = parcel.ReadUint64();
1285 
1286     if (IsReadMode()) {
1287         constexpr uint32_t skipBytes = 24u;
1288         parcel.SkipBytes(skipBytes);
1289         return true;
1290     }
1291 
1292     return false;
1293 }
1294 
GetNodeDepth(const std::shared_ptr<RSRenderNode> node)1295 uint32_t RSProfiler::GetNodeDepth(const std::shared_ptr<RSRenderNode> node)
1296 {
1297     uint32_t depth = 0;
1298     for (auto curNode = node; curNode != nullptr; depth++) {
1299         curNode = curNode ? curNode->GetParent().lock() : nullptr;
1300     }
1301     return depth;
1302 }
1303 
SendMessageBase()1304 std::string RSProfiler::SendMessageBase()
1305 {
1306     const std::lock_guard<std::mutex> guard(g_msgBaseMutex);
1307     if (g_msgBaseList.empty()) {
1308         return "";
1309     }
1310     std::string value = g_msgBaseList.front();
1311     g_msgBaseList.pop();
1312     return value;
1313 }
1314 
SendMessageBase(const std::string & msg)1315 void RSProfiler::SendMessageBase(const std::string& msg)
1316 {
1317     const std::lock_guard<std::mutex> guard(g_msgBaseMutex);
1318     g_msgBaseList.push(msg);
1319 }
1320 
AnimeGetStartTimes()1321 std::unordered_map<AnimationId, std::vector<int64_t>>& RSProfiler::AnimeGetStartTimes()
1322 {
1323     return g_animeStartMap;
1324 }
1325 
ReplayFixTrIndex(uint64_t curIndex,uint64_t & lastIndex)1326 void RSProfiler::ReplayFixTrIndex(uint64_t curIndex, uint64_t& lastIndex)
1327 {
1328     if (!IsEnabled()) {
1329         return;
1330     }
1331     if (IsReadMode()) {
1332         if (lastIndex == 0) {
1333             lastIndex = curIndex - 1;
1334         }
1335     }
1336 }
1337 
AnimeSetStartTime(AnimationId id,int64_t nanoTime)1338 int64_t RSProfiler::AnimeSetStartTime(AnimationId id, int64_t nanoTime)
1339 {
1340     if (!IsEnabled()) {
1341         return nanoTime;
1342     }
1343 
1344     if (IsReadMode()) {
1345         if (!g_animeStartMap.count(id)) {
1346             return nanoTime;
1347         }
1348         int64_t minDt = INT64_MAX, minTime = nanoTime - g_replayStartTimeNano;
1349         for (const auto recordedTime : g_animeStartMap[id]) {
1350             int64_t dt = abs(recordedTime - (nanoTime - g_replayStartTimeNano));
1351             if (dt < minDt) {
1352                 minDt = dt;
1353                 minTime = recordedTime;
1354             }
1355         }
1356         return minTime + g_replayStartTimeNano;
1357     } else if (IsWriteMode()) {
1358         if (g_animeStartMap.count(id)) {
1359             g_animeStartMap[Utils::PatchNodeId(id)].push_back(nanoTime);
1360         } else {
1361             std::vector<int64_t> list;
1362             list.push_back(nanoTime);
1363             g_animeStartMap.insert({ Utils::PatchNodeId(id), list });
1364         }
1365     }
1366 
1367     return nanoTime;
1368 }
1369 
ProcessAddChild(RSRenderNode * parent,RSRenderNode::SharedPtr child,int index)1370 bool RSProfiler::ProcessAddChild(RSRenderNode* parent, RSRenderNode::SharedPtr child, int index)
1371 {
1372     if (!parent || !child || !IsEnabled()) {
1373         return false;
1374     }
1375     if (!IsReadMode()) {
1376         return false;
1377     }
1378 
1379     if (parent->GetType() == RSRenderNodeType::DISPLAY_NODE &&
1380         ! (child->GetId() & Utils::ComposeNodeId(Utils::GetMockPid(0), 0))) {
1381         // BLOCK LOCK-SCREEN ATTACH TO DISPLAY
1382         g_childOfDisplayNodesPostponed.clear();
1383         g_childOfDisplayNodesPostponed.emplace_back(child);
1384         return true;
1385     }
1386     return false;
1387 }
1388 
GetChildOfDisplayNodesPostponed()1389 std::vector<RSRenderNode::WeakPtr>& RSProfiler::GetChildOfDisplayNodesPostponed()
1390 {
1391     return g_childOfDisplayNodesPostponed;
1392 }
1393 
RequestRecordAbort()1394 void RSProfiler::RequestRecordAbort()
1395 {
1396     recordAbortRequested_ = true;
1397 }
1398 
IsRecordAbortRequested()1399 bool RSProfiler::IsRecordAbortRequested()
1400 {
1401     return recordAbortRequested_;
1402 }
1403 
BaseSetPlaybackSpeed(double speed)1404 bool RSProfiler::BaseSetPlaybackSpeed(double speed)
1405 {
1406     float invSpeed = 1.0f;
1407     if (speed <= .0f) {
1408         return false;
1409     } else {
1410         invSpeed /= speed > 0.0f ? speed : 1.0f;
1411     }
1412 
1413     if (IsReadMode()) {
1414         if (Utils::Now() >= g_pauseAfterTime && g_pauseAfterTime > 0) {
1415             // paused can change speed but need adjust start time then
1416             int64_t curTime = static_cast<int64_t>(g_pauseAfterTime) - g_pauseCumulativeTime - g_replayStartTimeNano;
1417             g_pauseCumulativeTime = static_cast<int64_t>(g_pauseAfterTime) - g_replayStartTimeNano -
1418                     curTime * g_replaySpeed * invSpeed;
1419             g_replaySpeed = speed;
1420             return true;
1421         }
1422         // change of speed when replay in progress is not possible
1423         return false;
1424     }
1425     g_replaySpeed = speed;
1426     return true;
1427 }
1428 
BaseGetPlaybackSpeed()1429 double RSProfiler::BaseGetPlaybackSpeed()
1430 {
1431     return g_replaySpeed;
1432 }
1433 
MarshalSubTreeLo(RSContext & context,std::stringstream & data,const RSRenderNode & node,uint32_t fileVersion)1434 void RSProfiler::MarshalSubTreeLo(RSContext& context, std::stringstream& data,
1435     const RSRenderNode& node, uint32_t fileVersion)
1436 {
1437     NodeId nodeId = node.GetId();
1438     data.write(reinterpret_cast<const char*>(&nodeId), sizeof(nodeId));
1439 
1440     MarshalNode(node, data, fileVersion);
1441 
1442     const uint32_t count = node.children_.size();
1443     data.write(reinterpret_cast<const char*>(&count), sizeof(count));
1444     for (const auto& child : node.children_) {
1445         if (auto childNode = child.lock().get()) {
1446             MarshalSubTreeLo(context, data, *childNode, fileVersion);
1447         }
1448     }
1449 }
1450 
UnmarshalSubTreeLo(RSContext & context,std::stringstream & data,RSRenderNode & attachNode,uint32_t fileVersion)1451 std::string RSProfiler::UnmarshalSubTreeLo(RSContext& context, std::stringstream& data,
1452     RSRenderNode& attachNode, uint32_t fileVersion)
1453 {
1454     NodeId nodeId;
1455     data.read(reinterpret_cast<char*>(&nodeId), sizeof(nodeId));
1456 
1457     std::string errorReason = UnmarshalNode(context, data, fileVersion);
1458     if (errorReason.size()) {
1459         return errorReason;
1460     }
1461 
1462     auto node = context.GetMutableNodeMap().GetRenderNode(Utils::PatchNodeId(nodeId));
1463     if (!node) {
1464         return "Failed to create node";
1465     }
1466 
1467     attachNode.AddChild(node);
1468 
1469     uint32_t childCount;
1470     data.read(reinterpret_cast<char*>(&childCount), sizeof(childCount));
1471     for (uint32_t i = 0; i < childCount; i++) {
1472         UnmarshalSubTreeLo(context, data, *node, fileVersion);
1473         if (errorReason.size()) {
1474             return errorReason;
1475         }
1476     }
1477     return errorReason;
1478 }
1479 } // namespace OHOS::Rosen