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