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