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