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