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