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