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 "message_parcel.h"
27 #include "rs_profiler.h"
28 #include "rs_profiler_cache.h"
29 #include "rs_profiler_capture_recorder.h"
30 #include "rs_profiler_file.h"
31 #include "rs_profiler_log.h"
32 #include "rs_profiler_network.h"
33 #include "rs_profiler_utils.h"
34 #include "sys_binder.h"
35
36 #include "animation/rs_animation_manager.h"
37 #include "command/rs_base_node_command.h"
38 #include "command/rs_canvas_drawing_node_command.h"
39 #include "command/rs_canvas_node_command.h"
40 #include "command/rs_effect_node_command.h"
41 #include "command/rs_proxy_node_command.h"
42 #include "command/rs_root_node_command.h"
43 #include "command/rs_surface_node_command.h"
44 #include "modifier_ng/rs_modifier_ng_type.h"
45 #include "pipeline/rs_canvas_drawing_render_node.h"
46 #include "pipeline/rs_render_node.h"
47 #include "pipeline/rs_surface_render_node.h"
48 #include "pipeline/rs_screen_render_node.h"
49 #include "transaction/rs_ashmem_helper.h"
50
51 #include "render/rs_shader_filter.h"
52 #include "ge_shader_filter.h"
53
54 namespace OHOS::Rosen {
55 std::atomic_bool RSProfiler::recordAbortRequested_ = false;
56 std::atomic_uint32_t RSProfiler::mode_ = static_cast<uint32_t>(Mode::NONE);
57 static std::vector<pid_t> g_pids;
58 static pid_t g_pid = 0;
59 static NodeId g_parentNode = 0;
60 static std::atomic<uint32_t> g_commandCount = 0; // UNMARSHALLING RSCOMMAND COUNT
61 static std::atomic<uint32_t> g_commandExecuteCount = 0; // EXECUTE RSCOMMAND COUNT
62
63 static std::mutex g_msgBaseMutex;
64 static std::queue<std::string> g_msgBaseList;
65
66 static std::mutex g_rsLogListMutex;
67 static std::queue<RSProfilerLogMsg> g_rsLogList;
68
69 static std::mutex g_mutexCommandOffsets;
70 static std::map<uint32_t, std::vector<uint32_t>> g_parcelNumber2Offset;
71
72 static uint64_t g_pauseAfterTime = 0;
73 static int64_t g_pauseCumulativeTime = 0;
74 static int64_t g_transactionTimeCorrection = 0;
75 static int64_t g_replayStartTimeNano = 0.0;
76 static double g_replaySpeed = 1.0f;
77
78 static const size_t PARCEL_MAX_CAPACITY = 234 * 1024 * 1024;
79
80 static std::unordered_map<AnimationId, std::vector<int64_t>> g_animeStartMap;
81
82 bool RSProfiler::testing_ = false;
83 std::vector<std::shared_ptr<RSRenderNode>> RSProfiler::testTree_ = std::vector<std::shared_ptr<RSRenderNode>>();
84 bool RSProfiler::enabled_ = RSSystemProperties::GetProfilerEnabled();
85 bool RSProfiler::hrpServiceEnabled_ = RSSystemProperties::GetProfilerEnabled();
86 bool RSProfiler::betaRecordingEnabled_ = RSSystemProperties::GetBetaRecordingMode() != 0;
87 std::atomic<int8_t> RSProfiler::signalFlagChanged_ = 0;
88 std::atomic_bool RSProfiler::dcnRedraw_ = false;
89 std::atomic_bool RSProfiler::renderNodeKeepDrawCmdList_ = false;
90 std::vector<RSRenderNode::WeakPtr> g_childOfDisplayNodesPostponed;
91 std::unordered_map<AnimationId, int64_t> RSProfiler::animationsTimes_;
92
93 static TextureRecordType g_textureRecordType = TextureRecordType::LZ4;
94
GetParcelMaxCapacity()95 constexpr size_t GetParcelMaxCapacity()
96 {
97 return PARCEL_MAX_CAPACITY;
98 }
99
IsEnabled()100 bool RSProfiler::IsEnabled()
101 {
102 return enabled_ || testing_;
103 }
104
IsHrpServiceEnabled()105 bool RSProfiler::IsHrpServiceEnabled()
106 {
107 return hrpServiceEnabled_;
108 }
109
IsBetaRecordEnabled()110 bool RSProfiler::IsBetaRecordEnabled()
111 {
112 #ifdef RS_PROFILER_BETA_ENABLED
113 return betaRecordingEnabled_;
114 #else
115 return false;
116 #endif
117 }
118
IsNoneMode()119 bool RSProfiler::IsNoneMode()
120 {
121 return GetMode() == Mode::NONE;
122 }
123
IsReadMode()124 bool RSProfiler::IsReadMode()
125 {
126 return GetMode() == Mode::READ;
127 }
128
IsReadEmulationMode()129 bool RSProfiler::IsReadEmulationMode()
130 {
131 return GetMode() == Mode::READ_EMUL;
132 }
133
IsWriteMode()134 bool RSProfiler::IsWriteMode()
135 {
136 return GetMode() == Mode::WRITE;
137 }
138
IsWriteEmulationMode()139 bool RSProfiler::IsWriteEmulationMode()
140 {
141 return GetMode() == Mode::WRITE_EMUL;
142 }
143
IsSavingMode()144 bool RSProfiler::IsSavingMode()
145 {
146 return GetMode() == Mode::SAVING;
147 }
148
AddLightBlursMetrics(uint32_t areaBlurs)149 void RSProfiler::AddLightBlursMetrics(uint32_t areaBlurs)
150 {
151 if (!IsEnabled() || !IsWriteMode()) {
152 return;
153 }
154
155 GetCustomMetrics().AddInt(RSPROFILER_METRIC_LIGHT_BLUR_OPERATIONS, 1);
156 GetCustomMetrics().AddInt(RSPROFILER_METRIC_BLUR_OPERATIONS, 1);
157 GetCustomMetrics().AddFloat(RSPROFILER_METRIC_BLUR_AREA_OPERATIONS, areaBlurs);
158 }
AddAnimationNodeMetrics(RSRenderNodeType type,int32_t size)159 void RSProfiler::AddAnimationNodeMetrics(RSRenderNodeType type, int32_t size)
160 {
161 if (!IsEnabled() || !IsWriteMode()) {
162 return;
163 }
164
165 GetCustomMetrics().AddInt(RSPROFILER_METRIC_ANIMATION_NODE, 1);
166 GetCustomMetrics().AddFloat(RSPROFILER_METRIC_ANIMATION_NODE_SIZE, size);
167
168 int profiler_node_type = -1;
169 switch (type) {
170 case RSRenderNodeType::SURFACE_NODE:
171 profiler_node_type = RSPROFILER_METRIC_ANIMATION_NODE_TYPE_SURFACE_NODE;
172 break;
173 case RSRenderNodeType::PROXY_NODE:
174 profiler_node_type = RSPROFILER_METRIC_ANIMATION_NODE_TYPE_PROXY_NODE;
175 break;
176 case RSRenderNodeType::CANVAS_NODE:
177 profiler_node_type = RSPROFILER_METRIC_ANIMATION_NODE_TYPE_CANVAS_NODE;
178 break;
179 case RSRenderNodeType::EFFECT_NODE:
180 profiler_node_type = RSPROFILER_METRIC_ANIMATION_NODE_TYPE_EFFECT_NODE;
181 break;
182 case RSRenderNodeType::ROOT_NODE:
183 profiler_node_type = RSPROFILER_METRIC_ANIMATION_NODE_TYPE_ROOT_NODE;
184 break;
185 case RSRenderNodeType::CANVAS_DRAWING_NODE:
186 profiler_node_type = RSPROFILER_METRIC_ANIMATION_NODE_TYPE_CANVAS_DRAWING_NODE;
187 break;
188 default: // exclude RSRenderNodeType::(RS_NODE, UNKNOW, DISPLAY_NODE)
189 break;
190 }
191
192 if (profiler_node_type >= 0) {
193 GetCustomMetrics().AddInt(profiler_node_type, 1);
194 }
195 }
196
AddAnimationStart(AnimationId id,int64_t timestamp_ns)197 void RSProfiler::AddAnimationStart(AnimationId id, int64_t timestamp_ns)
198 {
199 if (!IsEnabled() || !IsWriteMode()) {
200 return;
201 }
202 animationsTimes_[id] = timestamp_ns;
203 }
204
AddAnimationFinish(AnimationId id,int64_t timestamp_ns)205 void RSProfiler::AddAnimationFinish(AnimationId id, int64_t timestamp_ns)
206 {
207 if (!IsEnabled() || !IsWriteMode()) {
208 return;
209 }
210 if (animationsTimes_.count(id) == 1) {
211 GetCustomMetrics().AddFloat(
212 RSPROFILER_METRIC_ANIMATION_DURATION, float(timestamp_ns - animationsTimes_[id]) / 1'000'000'000.f);
213 animationsTimes_.erase(id);
214 }
215 }
216
AddHPSBlursMetrics(uint32_t areaBlurs)217 void RSProfiler::AddHPSBlursMetrics(uint32_t areaBlurs)
218 {
219 if (!IsEnabled() || !IsWriteMode()) {
220 return;
221 }
222
223 GetCustomMetrics().AddInt(RSPROFILER_METRIC_HPS_BLUR_OPERATIONS, 1);
224 GetCustomMetrics().AddInt(RSPROFILER_METRIC_BLUR_OPERATIONS, 1);
225 GetCustomMetrics().AddFloat(RSPROFILER_METRIC_BLUR_AREA_OPERATIONS, areaBlurs);
226 }
227
AddKawaseBlursMetrics(uint32_t areaBlurs)228 void RSProfiler::AddKawaseBlursMetrics(uint32_t areaBlurs)
229 {
230 if (!IsEnabled() || !IsWriteMode()) {
231 return;
232 }
233
234 GetCustomMetrics().AddInt(RSPROFILER_METRIC_KAWASE_BLUR_OPERATIONS, 1);
235 GetCustomMetrics().AddInt(RSPROFILER_METRIC_BLUR_OPERATIONS, 1);
236 GetCustomMetrics().AddFloat(RSPROFILER_METRIC_BLUR_AREA_OPERATIONS, areaBlurs);
237 }
238
AddMESABlursMetrics(uint32_t areaBlurs)239 void RSProfiler::AddMESABlursMetrics(uint32_t areaBlurs)
240 {
241 if (!IsEnabled() || !IsWriteMode()) {
242 return;
243 }
244
245 GetCustomMetrics().AddInt(RSPROFILER_METRIC_MESA_BLUR_OPERATIONS, 1);
246 GetCustomMetrics().AddInt(RSPROFILER_METRIC_BLUR_OPERATIONS, 1);
247 GetCustomMetrics().AddFloat(RSPROFILER_METRIC_BLUR_AREA_OPERATIONS, areaBlurs);
248 }
249
LogShaderCall(const std::string & shaderType,const std::shared_ptr<Drawing::Image> & srcImage,const Drawing::Rect & dstRect,const std::shared_ptr<Drawing::Image> & outImage)250 void RSProfiler::LogShaderCall(const std::string& shaderType, const std::shared_ptr<Drawing::Image>& srcImage,
251 const Drawing::Rect& dstRect, const std::shared_ptr<Drawing::Image>& outImage)
252 {
253 if (!IsEnabled() || !IsWriteMode()) {
254 return;
255 }
256
257 if (shaderType == "KAWASE_BLUR") {
258 GetCustomMetrics().AddInt(RSPROFILER_METRIC_KAWASE_BLUR_SHADER_CALLS, 1);
259 } else if (shaderType == "MESA_BLUR") {
260 GetCustomMetrics().AddInt(RSPROFILER_METRIC_MESA_BLUR_SHADER_CALLS, 1);
261 } else if (shaderType == "AIBAR") {
262 GetCustomMetrics().AddInt(RSPROFILER_METRIC_AIBAR_BLUR_SHADER_CALLS, 1);
263 } else if (shaderType == "GREY") {
264 GetCustomMetrics().AddInt(RSPROFILER_METRIC_GREY_BLUR_SHADER_CALLS, 1);
265 } else if (shaderType == "LINEAR_GRADIENT_BLUR") {
266 GetCustomMetrics().AddInt(RSPROFILER_METRIC_LINEAR_GRADIENT_BLUR_SHADER_CALLS, 1);
267 } else if (shaderType == "MAGNIFIER") {
268 GetCustomMetrics().AddInt(RSPROFILER_METRIC_MAGNIFIER_SHADER_CALLS, 1);
269 } else if (shaderType == "WATER_RIPPLE") {
270 GetCustomMetrics().AddInt(RSPROFILER_METRIC_WATER_RIPPLE_BLUR_SHADER_CALLS, 1);
271 }
272 GetCustomMetrics().AddInt(RSPROFILER_METRIC_BLUR_SHADER_CALLS, 1);
273 GetCustomMetrics().AddFloat(RSPROFILER_METRIC_BLUR_AREA_SHADER_CALLS, srcImage->GetWidth() * srcImage->GetHeight());
274 }
275
GetCommandCount()276 uint32_t RSProfiler::GetCommandCount()
277 {
278 const uint32_t count = g_commandCount;
279 g_commandCount = 0;
280 return count;
281 }
282
GetCommandExecuteCount()283 uint32_t RSProfiler::GetCommandExecuteCount()
284 {
285 const uint32_t count = g_commandExecuteCount;
286 g_commandExecuteCount = 0;
287 return count;
288 }
289
EnableSharedMemory()290 void RSProfiler::EnableSharedMemory()
291 {
292 RSMarshallingHelper::EndNoSharedMem();
293 }
294
DisableSharedMemory()295 void RSProfiler::DisableSharedMemory()
296 {
297 RSMarshallingHelper::BeginNoSharedMem(std::this_thread::get_id());
298 }
299
IsSharedMemoryEnabled()300 bool RSProfiler::IsSharedMemoryEnabled()
301 {
302 return RSMarshallingHelper::GetUseSharedMem(std::this_thread::get_id());
303 }
304
IsParcelMock(const Parcel & parcel)305 bool RSProfiler::IsParcelMock(const Parcel& parcel)
306 {
307 // gcc C++ optimization error (?): this is not working without volatile
308 const volatile auto address = reinterpret_cast<uint64_t>(&parcel);
309 return ((address & 1u) != 0);
310 }
311
IsPlaybackParcel(const Parcel & parcel)312 bool RSProfiler::IsPlaybackParcel(const Parcel& parcel)
313 {
314 return (IsReadMode() || IsReadEmulationMode())
315 && IsParcelMock(parcel);
316 }
317
CopyParcel(const MessageParcel & parcel)318 std::shared_ptr<MessageParcel> RSProfiler::CopyParcel(const MessageParcel& parcel)
319 {
320 if (!IsEnabled()) {
321 return std::make_shared<MessageParcel>();
322 }
323
324 if (IsParcelMock(parcel)) {
325 auto* buffer = new(std::nothrow) uint8_t[sizeof(MessageParcel) + 1];
326 if (!buffer) {
327 return std::make_shared<MessageParcel>();
328 }
329 auto* mpPtr = new (buffer + 1) MessageParcel;
330 return std::shared_ptr<MessageParcel>(mpPtr, [](MessageParcel* ptr) {
331 ptr->~MessageParcel();
332 auto* allocPtr = reinterpret_cast<uint8_t*>(ptr);
333 allocPtr--;
334 delete[] allocPtr;
335 });
336 }
337
338 return std::make_shared<MessageParcel>();
339 }
340
PatchPlainNodeId(const Parcel & parcel,NodeId id)341 NodeId RSProfiler::PatchPlainNodeId(const Parcel& parcel, NodeId id)
342 {
343 if (!IsEnabled()) {
344 return id;
345 }
346
347 if ((!IsReadMode() && !IsReadEmulationMode()) || !IsParcelMock(parcel)) {
348 return id;
349 }
350
351 return Utils::PatchNodeId(id);
352 }
353
PatchTypefaceId(const Parcel & parcel,std::shared_ptr<Drawing::DrawCmdList> & val)354 void RSProfiler::PatchTypefaceId(const Parcel& parcel, std::shared_ptr<Drawing::DrawCmdList>& val)
355 {
356 if (!val || !IsEnabled()) {
357 return;
358 }
359
360 if (IsReadEmulationMode()) {
361 val->PatchTypefaceIds();
362 } else if (IsReadMode()) {
363 if (IsParcelMock(parcel)) {
364 val->PatchTypefaceIds();
365 }
366 }
367 }
368
PatchPlainPid(const Parcel & parcel,pid_t pid)369 pid_t RSProfiler::PatchPlainPid(const Parcel& parcel, pid_t pid)
370 {
371 if (!IsEnabled() || (!IsReadMode() && !IsReadEmulationMode()) || !IsParcelMock(parcel)) {
372 return pid;
373 }
374
375 return Utils::GetMockPid(pid);
376 }
377
SetMode(Mode mode)378 void RSProfiler::SetMode(Mode mode)
379 {
380 mode_ = static_cast<uint32_t>(mode);
381 if (IsNoneMode()) {
382 g_pauseAfterTime = 0;
383 g_pauseCumulativeTime = 0;
384 g_replayStartTimeNano = 0;
385 }
386 }
387
GetMode()388 Mode RSProfiler::GetMode()
389 {
390 return static_cast<Mode>(mode_.load());
391 }
392
SetSubstitutingPid(const std::vector<pid_t> & pids,pid_t pid,NodeId parent)393 void RSProfiler::SetSubstitutingPid(const std::vector<pid_t>& pids, pid_t pid, NodeId parent)
394 {
395 g_pids = pids;
396 g_pid = pid;
397 g_parentNode = parent;
398 }
399
GetParentNode()400 NodeId RSProfiler::GetParentNode()
401 {
402 return g_parentNode;
403 }
404
GetPids()405 const std::vector<pid_t>& RSProfiler::GetPids()
406 {
407 return g_pids;
408 }
409
GetSubstitutingPid()410 pid_t RSProfiler::GetSubstitutingPid()
411 {
412 return g_pid;
413 }
414
PatchTime(uint64_t time)415 uint64_t RSProfiler::PatchTime(uint64_t time)
416 {
417 if (!IsEnabled()) {
418 return time;
419 }
420 if (!IsReadMode() && !IsReadEmulationMode()) {
421 return time;
422 }
423 if (time == 0.0) {
424 return 0.0;
425 }
426 if (time >= g_pauseAfterTime && g_pauseAfterTime > 0) {
427 return (static_cast<int64_t>(g_pauseAfterTime) - g_pauseCumulativeTime - g_replayStartTimeNano) *
428 BaseGetPlaybackSpeed() + g_replayStartTimeNano;
429 }
430 return (static_cast<int64_t>(time) - g_pauseCumulativeTime - g_replayStartTimeNano) *
431 BaseGetPlaybackSpeed() + g_replayStartTimeNano;
432 }
433
PatchTransactionTime(const Parcel & parcel,uint64_t time)434 uint64_t RSProfiler::PatchTransactionTime(const Parcel& parcel, uint64_t time)
435 {
436 if (!IsEnabled()) {
437 return time;
438 }
439
440 if (!IsReadMode()) {
441 return time;
442 }
443 if (time == 0.0) {
444 return 0.0;
445 }
446 if (!IsParcelMock(parcel)) {
447 return time;
448 }
449
450 return PatchTime(time + g_transactionTimeCorrection);
451 }
452
TimePauseAt(uint64_t curTime,uint64_t newPauseAfterTime,bool immediate)453 void RSProfiler::TimePauseAt(uint64_t curTime, uint64_t newPauseAfterTime, bool immediate)
454 {
455 if (g_pauseAfterTime > 0) {
456 // second time pause
457 if (curTime > g_pauseAfterTime) {
458 g_pauseCumulativeTime += static_cast<int64_t>(curTime - g_pauseAfterTime);
459 }
460 }
461 g_pauseAfterTime = newPauseAfterTime;
462 if (immediate) {
463 g_pauseCumulativeTime += static_cast<int64_t>(curTime - g_pauseAfterTime);
464 g_pauseAfterTime = curTime;
465 }
466 }
467
TimePauseResume(uint64_t curTime)468 void RSProfiler::TimePauseResume(uint64_t curTime)
469 {
470 if (g_pauseAfterTime > 0) {
471 if (curTime > g_pauseAfterTime) {
472 g_pauseCumulativeTime += static_cast<int64_t>(curTime - g_pauseAfterTime);
473 }
474 }
475 g_pauseAfterTime = 0;
476 }
477
TimePauseClear()478 void RSProfiler::TimePauseClear()
479 {
480 g_pauseCumulativeTime = 0;
481 g_pauseAfterTime = 0;
482 }
483
TimePauseGet()484 uint64_t RSProfiler::TimePauseGet()
485 {
486 return g_pauseAfterTime;
487 }
488
GetScreenNode(const RSContext & context)489 std::shared_ptr<RSScreenRenderNode> RSProfiler::GetScreenNode(const RSContext& context)
490 {
491 const std::shared_ptr<RSBaseRenderNode>& root = context.GetGlobalRootRenderNode();
492 // without these checks device might get stuck on startup
493 if (!root || !root->GetChildrenCount()) {
494 return nullptr;
495 }
496
497 const auto& children = *root->GetChildren();
498 if (children.empty()) {
499 return nullptr;
500 }
501 for (const auto& screenNode : children) { // apply multiple screen nodes
502 if (!screenNode) {
503 continue;
504 }
505 const auto& screenNodeChildren = screenNode->GetChildren();
506 if (screenNodeChildren->empty()) {
507 continue;
508 }
509 return RSBaseRenderNode::ReinterpretCast<RSScreenRenderNode>(screenNode);
510 }
511 return nullptr;
512 }
513
GetScreenRect(const RSContext & context)514 Vector4f RSProfiler::GetScreenRect(const RSContext& context)
515 {
516 std::shared_ptr<RSScreenRenderNode> node = GetScreenNode(context);
517 if (!node) {
518 return {};
519 }
520
521 const RectI rect = node->GetDirtyManager()->GetSurfaceRect();
522 return { rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom() };
523 }
524
FilterForPlayback(RSContext & context,pid_t pid)525 void RSProfiler::FilterForPlayback(RSContext& context, pid_t pid)
526 {
527 auto& map = context.GetMutableNodeMap();
528
529 auto canBeRemoved = [](NodeId node, pid_t pid) -> bool {
530 return (ExtractPid(node) == pid) && (Utils::ExtractNodeId(node) != 1);
531 };
532
533 // remove all nodes belong to given pid (by matching higher 32 bits of node id)
534 auto iter = map.renderNodeMap_.find(pid);
535 if (iter != map.renderNodeMap_.end()) {
536 auto& subMap = iter->second;
537 EraseIf(subMap, [](const auto& pair) -> bool {
538 if (Utils::ExtractNodeId(pair.first) == 1) {
539 return false;
540 }
541 // remove node from tree
542 pair.second->RemoveFromTree(false);
543 return true;
544 });
545 if (subMap.empty()) {
546 map.renderNodeMap_.erase(pid);
547 }
548 }
549
550 EraseIf(
551 map.surfaceNodeMap_, [pid, canBeRemoved](const auto& pair) -> bool { return canBeRemoved(pair.first, pid); });
552
553 EraseIf(map.residentSurfaceNodeMap_,
554 [pid, canBeRemoved](const auto& pair) -> bool { return canBeRemoved(pair.first, pid); });
555
556 EraseIf(
557 map.screenNodeMap_, [pid, canBeRemoved](const auto& pair) -> bool { return canBeRemoved(pair.first, pid); });
558
559 if (auto fallbackNode = map.GetAnimationFallbackNode()) {
560 fallbackNode->GetAnimationManager().FilterAnimationByPid(pid);
561 }
562 }
563
FilterMockNode(RSContext & context)564 void RSProfiler::FilterMockNode(RSContext& context)
565 {
566 std::unordered_set<pid_t> pidSet;
567
568 auto& nodeMap = context.GetMutableNodeMap();
569 nodeMap.TraversalNodes([&pidSet](const std::shared_ptr<RSBaseRenderNode>& node) {
570 if (node == nullptr) {
571 return;
572 }
573 if (Utils::IsNodeIdPatched(node->GetId())) {
574 pidSet.insert(Utils::ExtractPid(node->GetId()));
575 }
576 });
577
578 for (auto pid : pidSet) {
579 nodeMap.FilterNodeByPid(pid, true);
580 }
581
582 if (auto fallbackNode = nodeMap.GetAnimationFallbackNode()) {
583 // remove all fallback animations belong to given pid
584 FilterAnimationForPlayback(fallbackNode->GetAnimationManager());
585 }
586 }
587
GetSurfacesTrees(const RSContext & context,std::map<std::string,std::tuple<NodeId,std::string>> & list)588 void RSProfiler::GetSurfacesTrees(
589 const RSContext& context, std::map<std::string, std::tuple<NodeId, std::string>>& list)
590 {
591 constexpr uint32_t treeDumpDepth = 2;
592
593 list.clear();
594
595 const RSRenderNodeMap& map = const_cast<RSContext&>(context).GetMutableNodeMap();
596 for (const auto& [_, subMap] : map.renderNodeMap_) {
597 for (const auto& [_, node] : subMap) {
598 if (node->GetType() == RSRenderNodeType::SURFACE_NODE) {
599 std::string tree;
600 node->DumpTree(treeDumpDepth, tree);
601 const auto surfaceNode = node->ReinterpretCastTo<RSSurfaceRenderNode>();
602 list.insert({ surfaceNode->GetName(), { surfaceNode->GetId(), tree } });
603 }
604 }
605 }
606 }
607
GetSurfacesTrees(const RSContext & context,pid_t pid,std::map<NodeId,std::string> & list)608 void RSProfiler::GetSurfacesTrees(const RSContext& context, pid_t pid, std::map<NodeId, std::string>& list)
609 {
610 constexpr uint32_t treeDumpDepth = 2;
611
612 list.clear();
613
614 const RSRenderNodeMap& map = const_cast<RSContext&>(context).GetMutableNodeMap();
615 for (const auto& [_, subMap] : map.renderNodeMap_) {
616 for (const auto& [_, node] : subMap) {
617 if (node->GetId() == Utils::GetRootNodeId(pid)) {
618 std::string tree;
619 node->DumpTree(treeDumpDepth, tree);
620 list.insert({ node->GetId(), tree });
621 }
622 }
623 }
624 }
625
GetRenderNodeCount(const RSContext & context)626 size_t RSProfiler::GetRenderNodeCount(const RSContext& context)
627 {
628 return const_cast<RSContext&>(context).GetMutableNodeMap().GetSize();
629 }
630
GetRandomSurfaceNode(const RSContext & context)631 NodeId RSProfiler::GetRandomSurfaceNode(const RSContext& context)
632 {
633 const RSRenderNodeMap& map = const_cast<RSContext&>(context).GetMutableNodeMap();
634 for (const auto& item : map.surfaceNodeMap_) {
635 return item.first;
636 }
637 return 0;
638 }
639
MarshalNodes(const RSContext & context,std::stringstream & data,uint32_t fileVersion)640 void RSProfiler::MarshalNodes(const RSContext& context, std::stringstream& data, uint32_t fileVersion)
641 {
642 const auto& map = const_cast<RSContext&>(context).GetMutableNodeMap();
643 const uint32_t count = static_cast<uint32_t>(map.GetSize());
644 data.write(reinterpret_cast<const char*>(&count), sizeof(count));
645 const auto& rootRenderNode = context.GetGlobalRootRenderNode();
646 if (rootRenderNode == nullptr) {
647 RS_LOGE("RSProfiler::MarshalNodes rootRenderNode is nullptr");
648 return;
649 }
650
651 std::vector<std::shared_ptr<RSRenderNode>> nodes;
652 nodes.emplace_back(rootRenderNode);
653
654 for (const auto& [_, subMap] : map.renderNodeMap_) {
655 for (const auto& [_, node] : subMap) {
656 if (node != nullptr) {
657 MarshalNode(*node, data, fileVersion);
658 std::shared_ptr<RSRenderNode> parent = node->GetParent().lock();
659 if (!parent && (node != rootRenderNode)) {
660 nodes.emplace_back(node);
661 }
662 }
663 }
664 }
665
666 const uint32_t nodeCount = static_cast<uint32_t>(nodes.size());
667 data.write(reinterpret_cast<const char*>(&nodeCount), sizeof(nodeCount));
668 for (const auto& node : nodes) { // no nullptr in nodes, omit check
669 MarshalTree(*node, data, fileVersion);
670 }
671 }
672
MarshalTree(const RSRenderNode & node,std::stringstream & data,uint32_t fileVersion)673 void RSProfiler::MarshalTree(const RSRenderNode& node, std::stringstream& data, uint32_t fileVersion)
674 {
675 const NodeId nodeId = node.GetId();
676 data.write(reinterpret_cast<const char*>(&nodeId), sizeof(nodeId));
677
678 const uint32_t count = node.children_.size();
679 data.write(reinterpret_cast<const char*>(&count), sizeof(count));
680
681 for (const auto& child : node.children_) {
682 if (auto node = child.lock().get()) {
683 const NodeId nodeId = node->GetId();
684 data.write(reinterpret_cast<const char*>(&nodeId), sizeof(nodeId));
685 MarshalTree(*node, data, fileVersion);
686 }
687 }
688 }
689
MarshalNode(const RSRenderNode & node,std::stringstream & data,uint32_t fileVersion)690 void RSProfiler::MarshalNode(const RSRenderNode& node, std::stringstream& data, uint32_t fileVersion)
691 {
692 const RSRenderNodeType nodeType = node.GetType();
693 data.write(reinterpret_cast<const char*>(&nodeType), sizeof(nodeType));
694
695 const NodeId nodeId = node.GetId();
696 data.write(reinterpret_cast<const char*>(&nodeId), sizeof(nodeId));
697
698 const bool isTextureExportNode = node.GetIsTextureExportNode();
699 data.write(reinterpret_cast<const char*>(&isTextureExportNode), sizeof(isTextureExportNode));
700
701 if (node.GetType() == RSRenderNodeType::SURFACE_NODE) {
702 const auto& surfaceNode = reinterpret_cast<const RSSurfaceRenderNode&>(node);
703 const std::string name = surfaceNode.GetName();
704 uint32_t size = name.size();
705 data.write(reinterpret_cast<const char*>(&size), sizeof(size));
706 data.write(reinterpret_cast<const char*>(name.c_str()), size);
707
708 const std::string bundleName = "";
709 size = bundleName.size();
710 data.write(reinterpret_cast<const char*>(&size), sizeof(size));
711 data.write(reinterpret_cast<const char*>(bundleName.c_str()), size);
712
713 const RSSurfaceNodeType type = surfaceNode.GetSurfaceNodeType();
714 data.write(reinterpret_cast<const char*>(&type), sizeof(type));
715
716 const uint8_t backgroundAlpha = surfaceNode.GetAbilityBgAlpha();
717 data.write(reinterpret_cast<const char*>(&backgroundAlpha), sizeof(backgroundAlpha));
718
719 const uint8_t globalAlpha = surfaceNode.GetGlobalAlpha();
720 data.write(reinterpret_cast<const char*>(&globalAlpha), sizeof(globalAlpha));
721 }
722
723 const float positionZ = node.GetRenderProperties().GetPositionZ();
724 data.write(reinterpret_cast<const char*>(&positionZ), sizeof(positionZ));
725
726 const float pivotZ = node.GetRenderProperties().GetPivotZ();
727 data.write(reinterpret_cast<const char*>(&pivotZ), sizeof(pivotZ));
728
729 const NodePriorityType priority = const_cast<RSRenderNode&>(node).GetPriority();
730 data.write(reinterpret_cast<const char*>(&priority), sizeof(priority));
731
732 const bool isOnTree = node.IsOnTheTree();
733 data.write(reinterpret_cast<const char*>(&isOnTree), sizeof(isOnTree));
734
735 if (fileVersion >= RSFILE_VERSION_RENDER_METRICS_ADDED) {
736 const uint8_t nodeGroupType = node.nodeGroupType_;
737 data.write(reinterpret_cast<const char*>(&nodeGroupType), sizeof(nodeGroupType));
738 }
739
740 if (fileVersion >= RSFILE_VERSION_ISREPAINT_BOUNDARY) {
741 const bool isRepaintBoundary = node.IsRepaintBoundary();
742 data.write(reinterpret_cast<const char*>(&isRepaintBoundary), sizeof(isRepaintBoundary));
743 }
744
745 MarshalNodeModifiers(node, data, fileVersion);
746 }
747
MarshalRenderModifier(const ModifierNG::RSRenderModifier & modifier,std::stringstream & data)748 static void MarshalRenderModifier(const ModifierNG::RSRenderModifier& modifier, std::stringstream& data)
749 {
750 Parcel parcel;
751 parcel.SetMaxCapacity(GetParcelMaxCapacity());
752
753 // Parcel Code - can be any, in our case I selected -1 to support already captured subtrees
754 parcel.WriteInt32(-1);
755 // MARSHAL PARCEL VERSION
756 if (!RSMarshallingHelper::MarshallingTransactionVer(parcel)) {
757 return;
758 }
759
760 const_cast<ModifierNG::RSRenderModifier&>(modifier).Marshalling(parcel);
761 const size_t dataSize = parcel.GetDataSize();
762 data.write(reinterpret_cast<const char*>(&dataSize), sizeof(dataSize));
763 data.write(reinterpret_cast<const char*>(parcel.GetData()), dataSize);
764
765 // Remove all file descriptors
766 binder_size_t* object = reinterpret_cast<binder_size_t*>(parcel.GetObjectOffsets());
767 size_t objectNum = parcel.GetOffsetsSize();
768 uintptr_t parcelData = parcel.GetData();
769
770 const size_t maxObjectNum = INT_MAX;
771 if (!object || (objectNum > maxObjectNum)) {
772 return;
773 }
774
775 for (size_t i = 0; i < objectNum; i++) {
776 const flat_binder_object* flat = reinterpret_cast<flat_binder_object*>(parcelData + object[i]);
777 if (!flat) {
778 return;
779 }
780 if (flat->hdr.type == BINDER_TYPE_FD && flat->handle > 0) {
781 ::close(flat->handle);
782 }
783 }
784 }
785
MarshalDrawCmdModifiers(ModifierNG::RSRenderModifier & modifier,std::stringstream & data)786 static void MarshalDrawCmdModifiers(ModifierNG::RSRenderModifier& modifier, std::stringstream& data)
787 {
788 auto propertyType = ModifierNG::ModifierTypeConvertor::GetPropertyType(modifier.GetType());
789 auto oldCmdList = modifier.Getter<Drawing::DrawCmdListPtr>(propertyType, nullptr);
790 if (!oldCmdList) {
791 MarshalRenderModifier(modifier, data);
792 return;
793 }
794
795 auto newCmdList = std::make_shared<Drawing::DrawCmdList>(
796 oldCmdList->GetWidth(), oldCmdList->GetHeight(), Drawing::DrawCmdList::UnmarshalMode::IMMEDIATE);
797 oldCmdList->ProfilerMarshallingDrawOps(newCmdList.get());
798 newCmdList->PatchTypefaceIds(oldCmdList);
799 modifier.Setter<Drawing::DrawCmdListPtr>(propertyType, newCmdList);
800 MarshalRenderModifier(modifier, data);
801 modifier.Setter<Drawing::DrawCmdListPtr>(propertyType, oldCmdList);
802 }
803
MarshalNodeModifiers(const RSRenderNode & node,std::stringstream & data,uint32_t fileVersion)804 void RSProfiler::MarshalNodeModifiers(const RSRenderNode& node, std::stringstream& data, uint32_t fileVersion)
805 {
806 data.write(reinterpret_cast<const char*>(&node.instanceRootNodeId_), sizeof(node.instanceRootNodeId_));
807 data.write(reinterpret_cast<const char*>(&node.firstLevelNodeId_), sizeof(node.firstLevelNodeId_));
808
809 uint32_t modifierNGCount = 0;
810 for (const auto& slot : node.GetAllModifiers()) {
811 for (auto& modifierNG : slot) {
812 if (!modifierNG || modifierNG->GetType() == ModifierNG::RSModifierType::PARTICLE_EFFECT) {
813 continue;
814 }
815 modifierNGCount++;
816 }
817 }
818 data.write(reinterpret_cast<const char*>(&modifierNGCount), sizeof(modifierNGCount));
819 for (const auto& slot : node.GetAllModifiers()) {
820 for (auto& modifierNG : slot) {
821 if (!modifierNG || modifierNG->GetType() == ModifierNG::RSModifierType::PARTICLE_EFFECT) {
822 continue;
823 }
824 if (modifierNG->IsCustom()) {
825 MarshalDrawCmdModifiers(*modifierNG, data);
826 } else {
827 MarshalRenderModifier(*modifierNG, data);
828 }
829 }
830 }
831 }
832
CreateRenderSurfaceNode(RSContext & context,NodeId id,bool isTextureExportNode,std::stringstream & data)833 static std::string CreateRenderSurfaceNode(RSContext& context,
834 NodeId id,
835 bool isTextureExportNode,
836 std::stringstream& data)
837 {
838 constexpr uint32_t nameSizeMax = 4096;
839 uint32_t size = 0u;
840 data.read(reinterpret_cast<char*>(&size), sizeof(size));
841 if (size > nameSizeMax) {
842 return "CreateRenderSurfaceNode unmarshalling failed, file is damaged";
843 }
844
845 std::string name;
846 name.resize(size, ' ');
847 data.read(reinterpret_cast<char*>(name.data()), size);
848
849 data.read(reinterpret_cast<char*>(&size), sizeof(size));
850 if (size > nameSizeMax) {
851 return "CreateRenderSurfaceNode unmarshalling failed, file is damaged";
852 }
853 std::string bundleName;
854 bundleName.resize(size, ' ');
855 data.read(reinterpret_cast<char*>(bundleName.data()), size);
856
857 RSSurfaceNodeType nodeType = RSSurfaceNodeType::DEFAULT;
858 data.read(reinterpret_cast<char*>(&nodeType), sizeof(nodeType));
859
860 uint8_t backgroundAlpha = 0u;
861 data.read(reinterpret_cast<char*>(&backgroundAlpha), sizeof(backgroundAlpha));
862
863 uint8_t globalAlpha = 0u;
864 data.read(reinterpret_cast<char*>(&globalAlpha), sizeof(globalAlpha));
865
866 const RSSurfaceRenderNodeConfig config = { .id = id,
867 .name = name + "_",
868 .nodeType = nodeType,
869 .additionalData = nullptr,
870 .isTextureExportNode = isTextureExportNode,
871 .isSync = false };
872
873 if (auto node = SurfaceNodeCommandHelper::CreateWithConfigInRS(config, context)) {
874 context.GetMutableNodeMap().RegisterRenderNode(node);
875 node->SetAbilityBGAlpha(backgroundAlpha);
876 node->SetGlobalAlpha(globalAlpha);
877 }
878 return "";
879 }
880
UnmarshalNodes(RSContext & context,std::stringstream & data,uint32_t fileVersion)881 std::string RSProfiler::UnmarshalNodes(RSContext& context, std::stringstream& data, uint32_t fileVersion)
882 {
883 std::string errReason;
884
885 uint32_t count = 0;
886 data.read(reinterpret_cast<char*>(&count), sizeof(count));
887 for (uint32_t i = 0; i < count; i++) {
888 errReason = UnmarshalNode(context, data, fileVersion);
889 if (errReason.size()) {
890 return errReason;
891 }
892 }
893
894 data.read(reinterpret_cast<char*>(&count), sizeof(count));
895 for (uint32_t i = 0; i < count; i++) {
896 errReason = UnmarshalTree(context, data, fileVersion);
897 if (errReason.size()) {
898 return errReason;
899 }
900 }
901
902 MarkReplayNodesDirty(context);
903 return "";
904 }
905
MarkReplayNodesDirty(RSContext & context)906 void RSProfiler::MarkReplayNodesDirty(RSContext& context)
907 {
908 auto& nodeMap = context.GetMutableNodeMap();
909 nodeMap.TraversalNodes([](const std::shared_ptr<RSBaseRenderNode>& node) {
910 if (node == nullptr) {
911 return;
912 }
913 if (Utils::IsNodeIdPatched(node->GetId())) {
914 node->SetContentDirty();
915 node->SetDirty();
916 }
917 });
918 }
919
UnmarshalNode(RSContext & context,std::stringstream & data,uint32_t fileVersion)920 std::string RSProfiler::UnmarshalNode(RSContext& context, std::stringstream& data, uint32_t fileVersion)
921 {
922 RSRenderNodeType nodeType = RSRenderNodeType::UNKNOW;
923 data.read(reinterpret_cast<char*>(&nodeType), sizeof(nodeType));
924
925 NodeId nodeId = 0;
926 data.read(reinterpret_cast<char*>(&nodeId), sizeof(nodeId));
927 nodeId = Utils::PatchNodeId(nodeId);
928
929 bool isTextureExportNode = false;
930 data.read(reinterpret_cast<char*>(&isTextureExportNode), sizeof(isTextureExportNode));
931
932 if (data.eof()) {
933 return "UnmarshalNode failed, file is damaged";
934 }
935
936 if (nodeType == RSRenderNodeType::RS_NODE) {
937 RootNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
938 } else if (nodeType == RSRenderNodeType::SCREEN_NODE) {
939 RootNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
940 } else if (nodeType == RSRenderNodeType::LOGICAL_DISPLAY_NODE) {
941 RootNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
942 } else if (nodeType == RSRenderNodeType::SURFACE_NODE) {
943 std::string errReason = CreateRenderSurfaceNode(context, nodeId, isTextureExportNode, data);
944 if (errReason.size()) {
945 return errReason;
946 }
947 } else if (nodeType == RSRenderNodeType::PROXY_NODE) {
948 ProxyNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
949 } else if (nodeType == RSRenderNodeType::CANVAS_NODE) {
950 RSCanvasNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
951 } else if (nodeType == RSRenderNodeType::EFFECT_NODE) {
952 EffectNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
953 } else if (nodeType == RSRenderNodeType::ROOT_NODE) {
954 RootNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
955 } else if (nodeType == RSRenderNodeType::CANVAS_DRAWING_NODE) {
956 RSCanvasDrawingNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
957 } else {
958 RootNodeCommandHelper::Create(context, nodeId, isTextureExportNode);
959 }
960
961 return UnmarshalNode(context, data, nodeId, fileVersion);
962 }
963
UnmarshalNode(RSContext & context,std::stringstream & data,NodeId nodeId,uint32_t fileVersion)964 std::string RSProfiler::UnmarshalNode(RSContext& context, std::stringstream& data, NodeId nodeId, uint32_t fileVersion)
965 {
966 float positionZ = 0.0f;
967 data.read(reinterpret_cast<char*>(&positionZ), sizeof(positionZ));
968 float pivotZ = 0.0f;
969 data.read(reinterpret_cast<char*>(&pivotZ), sizeof(pivotZ));
970 NodePriorityType priority = NodePriorityType::MAIN_PRIORITY;
971 data.read(reinterpret_cast<char*>(&priority), sizeof(priority));
972 bool isOnTree = false;
973 data.read(reinterpret_cast<char*>(&isOnTree), sizeof(isOnTree));
974
975 uint8_t nodeGroupType = 0;
976 if (fileVersion >= RSFILE_VERSION_RENDER_METRICS_ADDED) {
977 data.read(reinterpret_cast<char*>(&nodeGroupType), sizeof(nodeGroupType));
978 }
979
980 bool isRepaintBoundary = false;
981 if (fileVersion >= RSFILE_VERSION_ISREPAINT_BOUNDARY) {
982 data.read(reinterpret_cast<char*>(&isRepaintBoundary), sizeof(isRepaintBoundary));
983 }
984
985 if (auto node = context.GetMutableNodeMap().GetRenderNode(nodeId)) {
986 node->GetMutableRenderProperties().SetPositionZ(positionZ);
987 node->GetMutableRenderProperties().SetPivotZ(pivotZ);
988 node->SetPriority(priority);
989 node->nodeGroupType_ = nodeGroupType;
990 #ifdef SUBTREE_PARALLEL_ENABLE
991 node->MarkRepaintBoundary(isRepaintBoundary);
992 #endif
993 return UnmarshalNodeModifiers(*node, data, fileVersion);
994 }
995 return "";
996 }
997
UnmarshalRenderModifier(std::stringstream & data,std::string & errReason)998 static std::shared_ptr<ModifierNG::RSRenderModifier> UnmarshalRenderModifier(
999 std::stringstream& data, std::string& errReason)
1000 {
1001 errReason = "";
1002
1003 constexpr size_t bufferSizeMax = 50'000'000;
1004 size_t bufferSize = 0;
1005 data.read(reinterpret_cast<char*>(&bufferSize), sizeof(bufferSize));
1006 if (bufferSize > bufferSizeMax) {
1007 errReason = "UnmarshalRenderModifier failed, file is damaged";
1008 return nullptr;
1009 }
1010
1011 std::vector<uint8_t> buffer;
1012 buffer.resize(bufferSize);
1013 data.read(reinterpret_cast<char*>(buffer.data()), buffer.size());
1014 if (data.eof()) {
1015 errReason = "UnmarshalRenderModifier failed, file is damaged";
1016 return nullptr;
1017 }
1018
1019 uint8_t parcelMemory[sizeof(Parcel) + 1];
1020 auto* parcel = new (parcelMemory + 1) Parcel;
1021 parcel->SetMaxCapacity(GetParcelMaxCapacity());
1022 parcel->WriteBuffer(buffer.data(), buffer.size());
1023
1024 int32_t versionPrefix = parcel->ReadInt32();
1025 if (versionPrefix == -1) {
1026 RSMarshallingHelper::UnmarshallingTransactionVer(*parcel);
1027 } else {
1028 parcel->RewindRead(0);
1029 }
1030
1031 auto ptr = ModifierNG::RSRenderModifier::Unmarshalling(*parcel);
1032 if (!ptr) {
1033 constexpr size_t minBufferSize = 2;
1034 if (buffer.size() >= minBufferSize) {
1035 const auto typeModifier = *(reinterpret_cast<ModifierNG::RSModifierType *>(&buffer[0]));
1036 errReason = ModifierNG::RSModifierTypeString::GetModifierTypeString(typeModifier);
1037 } else {
1038 errReason = "RSRenderModifier buffer too short";
1039 }
1040 errReason += ", size=" + std::to_string(buffer.size());
1041 }
1042
1043 return ptr;
1044 }
1045
SetupCanvasDrawingRenderNode(RSCanvasDrawingRenderNode & node)1046 static void SetupCanvasDrawingRenderNode(RSCanvasDrawingRenderNode& node)
1047 {
1048 int32_t width = 0;
1049 int32_t height = 0;
1050 for (uint16_t type = 0; type < ModifierNG::MODIFIER_TYPE_COUNT; type++) {
1051 auto& slot = node.GetAllModifiers()[type];
1052 if (slot.empty()) {
1053 continue;
1054 }
1055 if (!slot[0]->IsCustom()) {
1056 continue;
1057 }
1058 for (const auto& modifier : slot) {
1059 const auto commandList = modifier ? modifier->GetPropertyDrawCmdList() : nullptr;
1060 if (commandList) {
1061 width = std::max(width, commandList->GetWidth());
1062 height = std::max(height, commandList->GetHeight());
1063 }
1064 }
1065 }
1066 node.ResetSurface(width, height);
1067 }
1068
UnmarshalNodeModifiers(RSRenderNode & node,std::stringstream & data,uint32_t fileVersion)1069 std::string RSProfiler::UnmarshalNodeModifiers(RSRenderNode& node, std::stringstream& data, uint32_t fileVersion)
1070 {
1071 data.read(reinterpret_cast<char*>(&node.instanceRootNodeId_), sizeof(node.instanceRootNodeId_));
1072 node.instanceRootNodeId_ = Utils::PatchNodeId(node.instanceRootNodeId_);
1073
1074 data.read(reinterpret_cast<char*>(&node.firstLevelNodeId_), sizeof(node.firstLevelNodeId_));
1075 node.firstLevelNodeId_ = Utils::PatchNodeId(node.firstLevelNodeId_);
1076
1077 int32_t modifierCount = 0;
1078 data.read(reinterpret_cast<char*>(&modifierCount), sizeof(modifierCount));
1079 for (int32_t i = 0; i < modifierCount; i++) {
1080 std::string errModifierCode = "";
1081 auto ptr = UnmarshalRenderModifier(data, errModifierCode);
1082 if (!ptr) {
1083 RSProfiler::SendMessageBase("LOADERROR: Modifier format changed [" + errModifierCode + "]");
1084 continue;
1085 }
1086 node.AddModifier(ptr);
1087 }
1088
1089 if (data.eof()) {
1090 return "UnmarshalNodeModifiers failed, file is damaged";
1091 }
1092
1093 if (node.GetType() == RSRenderNodeType::CANVAS_DRAWING_NODE) {
1094 SetupCanvasDrawingRenderNode(static_cast<RSCanvasDrawingRenderNode&>(node));
1095 }
1096
1097 node.ApplyModifiers();
1098 return "";
1099 }
1100
UnmarshalTree(RSContext & context,std::stringstream & data,uint32_t fileVersion)1101 std::string RSProfiler::UnmarshalTree(RSContext& context, std::stringstream& data, uint32_t fileVersion)
1102 {
1103 const auto& map = context.GetMutableNodeMap();
1104
1105 NodeId nodeId = 0;
1106 data.read(reinterpret_cast<char*>(&nodeId), sizeof(nodeId));
1107 nodeId = Utils::PatchNodeId(nodeId);
1108
1109 uint32_t count = 0;
1110 data.read(reinterpret_cast<char*>(&count), sizeof(count));
1111
1112 auto node = map.GetRenderNode(nodeId);
1113 if (!node) {
1114 return "Error nodeId was not found";
1115 }
1116 for (uint32_t i = 0; i < count; i++) {
1117 NodeId nodeId = 0;
1118 data.read(reinterpret_cast<char*>(&nodeId), sizeof(nodeId));
1119 if (node) {
1120 node->AddChild(map.GetRenderNode(Utils::PatchNodeId(nodeId)), i);
1121 }
1122 UnmarshalTree(context, data, fileVersion);
1123 }
1124 return "";
1125 }
1126
DumpRenderProperties(const RSRenderNode & node)1127 std::string RSProfiler::DumpRenderProperties(const RSRenderNode& node)
1128 {
1129 return node.renderProperties_.Dump();
1130 }
1131
DumpModifiers(const RSRenderNode & node)1132 std::string RSProfiler::DumpModifiers(const RSRenderNode& node)
1133 {
1134 std::string out;
1135 out += "<";
1136 for (uint16_t type = 0; type < ModifierNG::MODIFIER_TYPE_COUNT; type++) {
1137 auto& slot = node.GetAllModifiers()[type];
1138 if (slot.empty()) {
1139 continue;
1140 }
1141 if (!slot[0]->IsCustom()) {
1142 continue;
1143 }
1144 out += "(";
1145 out += std::to_string(type);
1146 out += ", ";
1147 for (auto& modifier : slot) {
1148 out += "[";
1149 const auto modifierId = modifier->GetId();
1150 out += std::to_string(Utils::ExtractPid(modifierId));
1151 out += "|";
1152 out += std::to_string(Utils::ExtractNodeId(modifierId));
1153 out += " type=";
1154 out += std::to_string(type);
1155 out += " [modifier dump is not implemented yet]";
1156 out += "]";
1157 }
1158 out += ")";
1159 }
1160 out += ">";
1161 return out;
1162 }
1163
DumpSurfaceNode(const RSRenderNode & node)1164 std::string RSProfiler::DumpSurfaceNode(const RSRenderNode& node)
1165 {
1166 if (node.GetType() != RSRenderNodeType::SURFACE_NODE) {
1167 return "";
1168 }
1169
1170 std::string out;
1171 const auto& surfaceNode = (static_cast<const RSSurfaceRenderNode&>(node));
1172 const auto parent = node.parent_.lock();
1173 out += ", Parent [" + (parent ? std::to_string(parent->GetId()) : "null") + "]";
1174 out += ", Name [" + surfaceNode.GetName() + "]";
1175 if (surfaceNode.GetRSSurfaceHandler()) {
1176 out += ", hasConsumer: " + std::to_string(surfaceNode.GetRSSurfaceHandler()->HasConsumer());
1177 }
1178 std::string contextAlpha = std::to_string(surfaceNode.contextAlpha_);
1179 std::string propertyAlpha = std::to_string(surfaceNode.GetRenderProperties().GetAlpha());
1180 out += ", Alpha: " + propertyAlpha + " (include ContextAlpha: " + contextAlpha + ")";
1181 out += ", Visible: " + std::to_string(surfaceNode.GetRenderProperties().GetVisible());
1182 out += ", " + surfaceNode.GetVisibleRegion().GetRegionInfo();
1183 out += ", OcclusionBg: " + std::to_string(surfaceNode.GetAbilityBgAlpha());
1184 out += ", Properties: " + node.GetRenderProperties().Dump();
1185 return out;
1186 }
1187
1188 // RSAnimationManager
FilterAnimationForPlayback(RSAnimationManager & manager)1189 void RSProfiler::FilterAnimationForPlayback(RSAnimationManager& manager)
1190 {
1191 EraseIf(manager.animations_, [](const auto& pair) -> bool {
1192 if (!Utils::IsNodeIdPatched(pair.first)) {
1193 return false;
1194 }
1195 pair.second->Finish();
1196 pair.second->Detach();
1197 return true;
1198 });
1199 }
1200
SetTransactionTimeCorrection(double replayStartTime,double recordStartTime)1201 void RSProfiler::SetTransactionTimeCorrection(double replayStartTime, double recordStartTime)
1202 {
1203 g_transactionTimeCorrection = static_cast<int64_t>((replayStartTime - recordStartTime) * NS_TO_S);
1204 g_replayStartTimeNano = replayStartTime * NS_TO_S;
1205 }
1206
GetParcelCommandList()1207 std::string RSProfiler::GetParcelCommandList()
1208 {
1209 const std::lock_guard<std::mutex> guard(g_mutexCommandOffsets);
1210 if (g_parcelNumber2Offset.size()) {
1211 const auto it = g_parcelNumber2Offset.begin();
1212 std::stringstream stream(std::ios::in | std::ios::out | std::ios::binary);
1213 stream.write(reinterpret_cast<const char*>(&it->first), sizeof(it->first));
1214 stream.write(reinterpret_cast<const char*>(it->second.data()), it->second.size() * sizeof(uint32_t));
1215 g_parcelNumber2Offset.erase(it);
1216 return stream.str();
1217 }
1218 return "";
1219 }
1220
PushOffset(std::vector<uint32_t> & commandOffsets,uint32_t offset)1221 void RSProfiler::PushOffset(std::vector<uint32_t>& commandOffsets, uint32_t offset)
1222 {
1223 if (!IsEnabled()) {
1224 return;
1225 }
1226 if (IsWriteMode()) {
1227 commandOffsets.push_back(offset);
1228 }
1229 }
1230
TransactionUnmarshallingStart(const Parcel & parcel,uint32_t parcelNumber)1231 void RSProfiler::TransactionUnmarshallingStart(const Parcel& parcel, uint32_t parcelNumber)
1232 {
1233 std::stringstream stream(std::ios::in | std::ios::out | std::ios::binary);
1234 stream.write(reinterpret_cast<const char*>(&parcelNumber), sizeof(parcelNumber));
1235 SendRSLogBase(RSProfilerLogType::PARCEL_UNMARSHALLING_START, stream.str());
1236 }
1237
PushOffsets(const Parcel & parcel,uint32_t parcelNumber,std::vector<uint32_t> & commandOffsets)1238 void RSProfiler::PushOffsets(const Parcel& parcel, uint32_t parcelNumber, std::vector<uint32_t>& commandOffsets)
1239 {
1240 if (!IsEnabled()) {
1241 return;
1242 }
1243 if (!parcelNumber) {
1244 return;
1245 }
1246 if (IsWriteMode()) {
1247 const std::lock_guard<std::mutex> guard(g_mutexCommandOffsets);
1248 g_parcelNumber2Offset[parcelNumber] = commandOffsets;
1249
1250 std::stringstream stream(std::ios::in | std::ios::out | std::ios::binary);
1251 stream.write(reinterpret_cast<const char*>(&parcelNumber), sizeof(parcelNumber));
1252 stream.write(reinterpret_cast<const char*>(commandOffsets.data()), commandOffsets.size() * sizeof(uint32_t));
1253 SendRSLogBase(RSProfilerLogType::PARCEL_UNMARSHALLING_END, stream.str());
1254 }
1255 }
1256
PatchCommand(const Parcel & parcel,RSCommand * command)1257 void RSProfiler::PatchCommand(const Parcel& parcel, RSCommand* command)
1258 {
1259 if (!IsEnabled()) {
1260 return;
1261 }
1262 if (command == nullptr) {
1263 return;
1264 }
1265
1266 if (command && IsParcelMock(parcel)) {
1267 command->Patch(Utils::PatchNodeId);
1268 }
1269
1270 if (IsWriteMode()) {
1271 g_commandCount++;
1272 }
1273 }
1274
ExecuteCommand(const RSCommand * command)1275 void RSProfiler::ExecuteCommand(const RSCommand* command)
1276 {
1277 if (!IsEnabled()) {
1278 return;
1279 }
1280 if (!IsWriteMode() && !IsReadMode()) {
1281 return;
1282 }
1283 if (command == nullptr) {
1284 return;
1285 }
1286
1287 g_commandExecuteCount++;
1288 }
1289
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)1290 uint32_t RSProfiler::PerfTreeFlatten(const std::shared_ptr<RSRenderNode> node,
1291 std::vector<std::pair<NodeId, uint32_t>>& nodeSet,
1292 std::unordered_map<NodeId, uint32_t>& mapNode2Count, uint32_t depth)
1293 {
1294 if (!node) {
1295 return 0;
1296 }
1297
1298 constexpr uint32_t depthToAnalyze = 10;
1299 uint32_t drawCmdListCount = CalcNodeCmdListCount(*node);
1300 if (node->GetSortedChildren()) {
1301 uint32_t valuableChildrenCount = 0;
1302 for (auto& child : *node->GetSortedChildren()) {
1303 if (child && child->GetType() != RSRenderNodeType::EFFECT_NODE && depth < depthToAnalyze) {
1304 nodeSet.emplace_back(child->id_, depth + 1);
1305 }
1306 }
1307 for (auto& child : *node->GetSortedChildren()) {
1308 if (child) {
1309 drawCmdListCount += PerfTreeFlatten(child, nodeSet, mapNode2Count, depth + 1);
1310 valuableChildrenCount++;
1311 }
1312 }
1313 }
1314
1315 if (drawCmdListCount > 0) {
1316 mapNode2Count[node->id_] = drawCmdListCount;
1317 }
1318 return drawCmdListCount;
1319 }
1320
CalcNodeCmdListCount(RSRenderNode & node)1321 uint32_t RSProfiler::CalcNodeCmdListCount(RSRenderNode& node)
1322 {
1323 uint32_t nodeCmdListCount = 0;
1324 for (uint16_t type = 0; type < ModifierNG::MODIFIER_TYPE_COUNT; type++) {
1325 auto& slot = node.GetAllModifiers()[type];
1326 if (slot.empty()) {
1327 continue;
1328 }
1329 if (!slot[0]->IsCustom()) {
1330 continue;
1331 }
1332 for (auto& modifier : slot) {
1333 std::shared_ptr<RSRenderProperty<Drawing::DrawCmdListPtr>> propertyPtr = nullptr;
1334 if (modifier != nullptr) {
1335 propertyPtr = std::static_pointer_cast<RSRenderProperty<Drawing::DrawCmdListPtr>>(
1336 modifier->GetProperty(ModifierNG::ModifierTypeConvertor::GetPropertyType(modifier->GetType())));
1337 }
1338 auto propertyValue = propertyPtr ? propertyPtr->Get() : nullptr;
1339 if (propertyValue && propertyValue->GetOpItemSize() > 0) {
1340 nodeCmdListCount = 1;
1341 }
1342 }
1343 }
1344 return nodeCmdListCount;
1345 }
1346
MarshalDrawingImage(std::shared_ptr<Drawing::Image> & image,std::shared_ptr<Drawing::Data> & compressData)1347 void RSProfiler::MarshalDrawingImage(std::shared_ptr<Drawing::Image>& image,
1348 std::shared_ptr<Drawing::Data>& compressData)
1349 {
1350 if (IsEnabled() && !IsSharedMemoryEnabled()) {
1351 image = nullptr;
1352 compressData = nullptr;
1353 }
1354 }
1355
EnableBetaRecord()1356 void RSProfiler::EnableBetaRecord()
1357 {
1358 RSSystemProperties::SetBetaRecordingMode(1);
1359 }
1360
IsBetaRecordSavingTriggered()1361 bool RSProfiler::IsBetaRecordSavingTriggered()
1362 {
1363 constexpr uint32_t savingMode = 2u;
1364 return RSSystemProperties::GetBetaRecordingMode() == savingMode;
1365 }
1366
IsBetaRecordEnabledWithMetrics()1367 bool RSProfiler::IsBetaRecordEnabledWithMetrics()
1368 {
1369 constexpr uint32_t metricsMode = 3u;
1370 return RSSystemProperties::GetBetaRecordingMode() == metricsMode;
1371 }
1372
SetDrawingCanvasNodeRedraw(bool enable)1373 void RSProfiler::SetDrawingCanvasNodeRedraw(bool enable)
1374 {
1375 dcnRedraw_ = enable && IsEnabled();
1376 }
1377
DrawingNodeAddClearOp(const std::shared_ptr<Drawing::DrawCmdList> & drawCmdList)1378 void RSProfiler::DrawingNodeAddClearOp(const std::shared_ptr<Drawing::DrawCmdList>& drawCmdList)
1379 {
1380 if (dcnRedraw_ || !drawCmdList) {
1381 return;
1382 }
1383 drawCmdList->ClearOp();
1384 }
1385
SetRenderNodeKeepDrawCmd(bool enable)1386 void RSProfiler::SetRenderNodeKeepDrawCmd(bool enable)
1387 {
1388 renderNodeKeepDrawCmdList_ = enable && IsEnabled();
1389 }
1390
KeepDrawCmd(bool & drawCmdListNeedSync)1391 void RSProfiler::KeepDrawCmd(bool& drawCmdListNeedSync)
1392 {
1393 drawCmdListNeedSync = !renderNodeKeepDrawCmdList_;
1394 }
1395
NewAshmemDataCacheId()1396 static uint64_t NewAshmemDataCacheId()
1397 {
1398 static std::atomic_uint32_t id = 0u;
1399 return Utils::ComposeDataId(Utils::GetPid(), id++);
1400 }
1401
CacheAshmemData(uint64_t id,const uint8_t * data,size_t size)1402 static void CacheAshmemData(uint64_t id, const uint8_t* data, size_t size)
1403 {
1404 if (RSProfiler::IsWriteMode() && data && (size > 0)) {
1405 Image ashmem;
1406 ashmem.data.insert(ashmem.data.end(), data, data + size);
1407 ImageCache::Add(id, std::move(ashmem));
1408 }
1409 }
1410
GetCachedAshmemData(uint64_t id)1411 static const uint8_t* GetCachedAshmemData(uint64_t id)
1412 {
1413 const auto ashmem = RSProfiler::IsReadMode() ? ImageCache::Get(id) : nullptr;
1414 return ashmem ? ashmem->data.data() : nullptr;
1415 }
1416
WriteParcelData(Parcel & parcel)1417 void RSProfiler::WriteParcelData(Parcel& parcel)
1418 {
1419 bool isClientEnabled = RSSystemProperties::GetProfilerEnabled();
1420 if (!parcel.WriteBool(isClientEnabled)) {
1421 HRPE("Unable to write is_client_enabled");
1422 return;
1423 }
1424
1425 if (!isClientEnabled) {
1426 return;
1427 }
1428
1429 if (!parcel.WriteUint64(NewAshmemDataCacheId())) {
1430 HRPE("Unable to write NewAshmemDataCacheId failed");
1431 return;
1432 }
1433 }
1434
ReadParcelData(Parcel & parcel,size_t size,bool & isMalloc)1435 const void* RSProfiler::ReadParcelData(Parcel& parcel, size_t size, bool& isMalloc)
1436 {
1437 bool isClientEnabled = false;
1438 if (!parcel.ReadBool(isClientEnabled)) {
1439 HRPE("Unable to read is_client_enabled");
1440 return nullptr;
1441 }
1442 if (!isClientEnabled) {
1443 return RSMarshallingHelper::ReadFromAshmem(parcel, size, isMalloc);
1444 }
1445
1446 const uint64_t id = parcel.ReadUint64();
1447 if (auto data = GetCachedAshmemData(id)) {
1448 constexpr uint32_t skipBytes = 24u;
1449 parcel.SkipBytes(skipBytes);
1450 isMalloc = false;
1451 return data;
1452 }
1453
1454 auto data = RSMarshallingHelper::ReadFromAshmem(parcel, size, isMalloc);
1455 CacheAshmemData(id, reinterpret_cast<const uint8_t*>(data), size);
1456 return data;
1457 }
1458
SkipParcelData(Parcel & parcel,size_t size)1459 bool RSProfiler::SkipParcelData(Parcel& parcel, size_t size)
1460 {
1461 bool isClientEnabled = false;
1462 if (!parcel.ReadBool(isClientEnabled)) {
1463 HRPE("RSProfiler::SkipParcelData read isClientEnabled failed");
1464 return false;
1465 }
1466 if (!isClientEnabled) {
1467 return false;
1468 }
1469
1470 [[maybe_unused]] const uint64_t id = parcel.ReadUint64();
1471
1472 if (IsReadMode()) {
1473 constexpr uint32_t skipBytes = 24u;
1474 parcel.SkipBytes(skipBytes);
1475 return true;
1476 }
1477
1478 return false;
1479 }
1480
GetNodeDepth(const std::shared_ptr<RSRenderNode> node)1481 uint32_t RSProfiler::GetNodeDepth(const std::shared_ptr<RSRenderNode> node)
1482 {
1483 uint32_t depth = 0;
1484 for (auto curNode = node; curNode != nullptr; depth++) {
1485 curNode = curNode ? curNode->GetParent().lock() : nullptr;
1486 }
1487 return depth;
1488 }
1489
ReceiveMessageBase()1490 std::string RSProfiler::ReceiveMessageBase()
1491 {
1492 const std::lock_guard<std::mutex> guard(g_msgBaseMutex);
1493 if (g_msgBaseList.empty()) {
1494 return "";
1495 }
1496 std::string value = g_msgBaseList.front();
1497 g_msgBaseList.pop();
1498 return value;
1499 }
1500
SendMessageBase(const std::string & msg)1501 void RSProfiler::SendMessageBase(const std::string& msg)
1502 {
1503 const std::lock_guard<std::mutex> guard(g_msgBaseMutex);
1504 g_msgBaseList.push(msg);
1505 }
1506
AnimeGetStartTimes()1507 std::unordered_map<AnimationId, std::vector<int64_t>>& RSProfiler::AnimeGetStartTimes()
1508 {
1509 return g_animeStartMap;
1510 }
1511
ReplayFixTrIndex(uint64_t curIndex,uint64_t & lastIndex)1512 void RSProfiler::ReplayFixTrIndex(uint64_t curIndex, uint64_t& lastIndex)
1513 {
1514 if (!IsEnabled()) {
1515 return;
1516 }
1517 if (IsReadMode()) {
1518 if (lastIndex == 0) {
1519 lastIndex = curIndex - 1;
1520 }
1521 }
1522 }
1523
AnimeSetStartTime(AnimationId id,int64_t nanoTime)1524 int64_t RSProfiler::AnimeSetStartTime(AnimationId id, int64_t nanoTime)
1525 {
1526 if (!IsEnabled()) {
1527 return nanoTime;
1528 }
1529
1530 if (IsReadMode()) {
1531 if (!g_animeStartMap.count(id)) {
1532 return nanoTime;
1533 }
1534 int64_t minDt = INT64_MAX, minTime = nanoTime - g_replayStartTimeNano;
1535 for (const auto recordedTime : g_animeStartMap[id]) {
1536 int64_t dt = abs(recordedTime - (nanoTime - g_replayStartTimeNano));
1537 if (dt < minDt) {
1538 minDt = dt;
1539 minTime = recordedTime;
1540 }
1541 }
1542 return minTime + g_replayStartTimeNano;
1543 } else if (IsWriteMode()) {
1544 if (g_animeStartMap.count(id)) {
1545 g_animeStartMap[Utils::PatchNodeId(id)].push_back(nanoTime);
1546 } else {
1547 std::vector<int64_t> list;
1548 list.push_back(nanoTime);
1549 g_animeStartMap.insert({ Utils::PatchNodeId(id), list });
1550 }
1551 }
1552
1553 return nanoTime;
1554 }
1555
ProcessAddChild(RSRenderNode * parent,RSRenderNode::SharedPtr child,int index)1556 bool RSProfiler::ProcessAddChild(RSRenderNode* parent, RSRenderNode::SharedPtr child, int index)
1557 {
1558 if (!parent || !child || !IsEnabled()) {
1559 return false;
1560 }
1561 if (!IsReadMode()) {
1562 return false;
1563 }
1564
1565 if (parent->GetType() == RSRenderNodeType::SCREEN_NODE &&
1566 ! (child->GetId() & Utils::ComposeNodeId(Utils::GetMockPid(0), 0))) {
1567 // BLOCK LOCK-SCREEN ATTACH TO SCREEN
1568 g_childOfDisplayNodesPostponed.clear();
1569 g_childOfDisplayNodesPostponed.emplace_back(child);
1570 return true;
1571 }
1572 return false;
1573 }
1574
GetChildOfDisplayNodesPostponed()1575 std::vector<RSRenderNode::WeakPtr>& RSProfiler::GetChildOfDisplayNodesPostponed()
1576 {
1577 return g_childOfDisplayNodesPostponed;
1578 }
1579
RequestRecordAbort()1580 void RSProfiler::RequestRecordAbort()
1581 {
1582 recordAbortRequested_ = true;
1583 }
1584
IsRecordAbortRequested()1585 bool RSProfiler::IsRecordAbortRequested()
1586 {
1587 return recordAbortRequested_;
1588 }
1589
BaseSetPlaybackSpeed(double speed)1590 bool RSProfiler::BaseSetPlaybackSpeed(double speed)
1591 {
1592 float invSpeed = 1.0f;
1593 if (speed <= .0f) {
1594 return false;
1595 } else {
1596 invSpeed /= speed > 0.0f ? speed : 1.0f;
1597 }
1598
1599 if (IsReadMode()) {
1600 if (Utils::Now() >= g_pauseAfterTime && g_pauseAfterTime > 0) {
1601 // paused can change speed but need adjust start time then
1602 int64_t curTime = static_cast<int64_t>(g_pauseAfterTime) - g_pauseCumulativeTime - g_replayStartTimeNano;
1603 g_pauseCumulativeTime = static_cast<int64_t>(g_pauseAfterTime) - g_replayStartTimeNano -
1604 curTime * g_replaySpeed * invSpeed;
1605 g_replaySpeed = speed;
1606 return true;
1607 }
1608 // change of speed when replay in progress is not possible
1609 return false;
1610 }
1611 g_replaySpeed = speed;
1612 return true;
1613 }
1614
BaseGetPlaybackSpeed()1615 double RSProfiler::BaseGetPlaybackSpeed()
1616 {
1617 return g_replaySpeed;
1618 }
1619
MarshalSubTreeLo(RSContext & context,std::stringstream & data,const RSRenderNode & node,uint32_t fileVersion)1620 void RSProfiler::MarshalSubTreeLo(RSContext& context, std::stringstream& data,
1621 const RSRenderNode& node, uint32_t fileVersion)
1622 {
1623 NodeId nodeId = node.GetId();
1624 data.write(reinterpret_cast<const char*>(&nodeId), sizeof(nodeId));
1625
1626 MarshalNode(node, data, fileVersion);
1627
1628 const uint32_t count = node.children_.size();
1629 data.write(reinterpret_cast<const char*>(&count), sizeof(count));
1630 for (const auto& child : node.children_) {
1631 if (auto childNode = child.lock().get()) {
1632 MarshalSubTreeLo(context, data, *childNode, fileVersion);
1633 }
1634 }
1635 }
1636
UnmarshalSubTreeLo(RSContext & context,std::stringstream & data,RSRenderNode & attachNode,uint32_t fileVersion)1637 std::string RSProfiler::UnmarshalSubTreeLo(RSContext& context, std::stringstream& data,
1638 RSRenderNode& attachNode, uint32_t fileVersion)
1639 {
1640 NodeId nodeId;
1641 data.read(reinterpret_cast<char*>(&nodeId), sizeof(nodeId));
1642
1643 std::string errorReason = UnmarshalNode(context, data, fileVersion);
1644 if (errorReason.size()) {
1645 return errorReason;
1646 }
1647
1648 auto node = context.GetMutableNodeMap().GetRenderNode(Utils::PatchNodeId(nodeId));
1649 if (!node) {
1650 return "Failed to create node";
1651 }
1652
1653 attachNode.AddChild(node);
1654
1655 uint32_t childCount;
1656 data.read(reinterpret_cast<char*>(&childCount), sizeof(childCount));
1657 for (uint32_t i = 0; i < childCount; i++) {
1658 errorReason = UnmarshalSubTreeLo(context, data, *node, fileVersion);
1659 if (errorReason.size()) {
1660 return errorReason;
1661 }
1662 }
1663 return errorReason;
1664 }
1665
GetTextureRecordType()1666 TextureRecordType RSProfiler::GetTextureRecordType()
1667 {
1668 if (IsBetaRecordEnabled()) {
1669 return TextureRecordType::ONE_PIXEL;
1670 }
1671 return g_textureRecordType;
1672 }
1673
SetTextureRecordType(TextureRecordType type)1674 void RSProfiler::SetTextureRecordType(TextureRecordType type)
1675 {
1676 g_textureRecordType = type;
1677 }
1678
IfNeedToSkipDuringReplay(Parcel & parcel,uint32_t skipBytes)1679 bool RSProfiler::IfNeedToSkipDuringReplay(Parcel& parcel, uint32_t skipBytes)
1680 {
1681 if (!IsEnabled()) {
1682 return false;
1683 }
1684 if (!IsParcelMock(parcel)) {
1685 return false;
1686 }
1687 if (IsReadEmulationMode() || IsReadMode()) {
1688 parcel.SkipBytes(skipBytes);
1689 return true;
1690 }
1691 return false;
1692 }
1693
SurfaceOnDrawMatchOptimize(bool & useNodeMatchOptimize)1694 void RSProfiler::SurfaceOnDrawMatchOptimize(bool& useNodeMatchOptimize)
1695 {
1696 if (!IsEnabled()) {
1697 return;
1698 }
1699 if (IsReadEmulationMode() || IsReadMode()) {
1700 useNodeMatchOptimize = true;
1701 }
1702 }
1703
MetricRenderNodeInc(bool isOnTree)1704 void RSProfiler::MetricRenderNodeInc(bool isOnTree)
1705 {
1706 if (!IsEnabled() || !IsWriteMode()) {
1707 return;
1708 }
1709 if (isOnTree) {
1710 GetCustomMetrics().AddInt(RSPROFILER_METRIC_ONTREE_NODE_COUNT, 1);
1711 } else {
1712 GetCustomMetrics().AddInt(RSPROFILER_METRIC_OFFTREE_NODE_COUNT, 1);
1713 }
1714 }
1715
MetricRenderNodeDec(bool isOnTree)1716 void RSProfiler::MetricRenderNodeDec(bool isOnTree)
1717 {
1718 if (!IsEnabled() || !IsWriteMode()) {
1719 return;
1720 }
1721 if (isOnTree) {
1722 GetCustomMetrics().SubInt(RSPROFILER_METRIC_ONTREE_NODE_COUNT, 1);
1723 } else {
1724 GetCustomMetrics().SubInt(RSPROFILER_METRIC_OFFTREE_NODE_COUNT, 1);
1725 }
1726 }
1727
MetricRenderNodeChange(bool isOnTree)1728 void RSProfiler::MetricRenderNodeChange(bool isOnTree)
1729 {
1730 if (!IsEnabled() || !IsWriteMode()) {
1731 return;
1732 }
1733 if (isOnTree) {
1734 GetCustomMetrics().AddInt(RSPROFILER_METRIC_ONTREE_NODE_COUNT, 1);
1735 GetCustomMetrics().SubInt(RSPROFILER_METRIC_OFFTREE_NODE_COUNT, 1);
1736 } else {
1737 GetCustomMetrics().AddInt(RSPROFILER_METRIC_OFFTREE_NODE_COUNT, 1);
1738 GetCustomMetrics().SubInt(RSPROFILER_METRIC_ONTREE_NODE_COUNT, 1);
1739 }
1740 }
1741
MetricRenderNodeInit(RSContext * context)1742 void RSProfiler::MetricRenderNodeInit(RSContext* context)
1743 {
1744 if (!context) {
1745 return;
1746 }
1747 GetCustomMetrics().SetZero(RSPROFILER_METRIC_ONTREE_NODE_COUNT);
1748 GetCustomMetrics().SetZero(RSPROFILER_METRIC_OFFTREE_NODE_COUNT);
1749 auto globalRootNodeId = context->GetGlobalRootRenderNode()->GetId();
1750 auto& nodeMap = context->GetMutableNodeMap();
1751 nodeMap.TraversalNodes([globalRootNodeId](const std::shared_ptr<RSBaseRenderNode>& node) {
1752 if (node == nullptr) {
1753 return;
1754 }
1755 auto parentPtr = node->GetParent().lock();
1756 for (; parentPtr && parentPtr->GetId() != globalRootNodeId; parentPtr = parentPtr->GetParent().lock())
1757 ;
1758 if (parentPtr != nullptr) {
1759 GetCustomMetrics().AddInt(RSPROFILER_METRIC_ONTREE_NODE_COUNT, 1);
1760 } else {
1761 GetCustomMetrics().AddInt(RSPROFILER_METRIC_OFFTREE_NODE_COUNT, 1);
1762 }
1763 });
1764 }
1765
RSLogOutput(RSProfilerLogType type,const char * format,va_list argptr)1766 void RSProfiler::RSLogOutput(RSProfilerLogType type, const char* format, va_list argptr)
1767 {
1768 if (!IsEnabled() || !(IsWriteMode() || IsReadEmulationMode())) {
1769 return;
1770 }
1771
1772 // no access to vsnprintf_s_p in inner api of hilog - have to write naive code myself
1773 constexpr int maxSize = 1024;
1774 char format2[maxSize] = {0}; // zero ending always present
1775 const char* ptr1 = format;
1776 char* ptr2 = format2;
1777 const auto effectiveSize = maxSize - 3; // max 3 chars can be added in one iteration
1778 constexpr int publicLen = 8; // publicLen = strlen("{public}");
1779 for (; *ptr1 && ptr2 - format2 < effectiveSize && ptr1 - format < effectiveSize - publicLen;) {
1780 if (*ptr1 == '%') {
1781 if (*(ptr1 + 1) == '%') {
1782 // %% translates to %%
1783 *ptr2++ = *ptr1++;
1784 *ptr2++ = *ptr1++;
1785 } else if (!memcmp(ptr1 + 1, "{public}", publicLen)) {
1786 // %{public} translates to %
1787 *ptr2++ = *ptr1++;
1788 ptr1 += publicLen;
1789 } else {
1790 // abcd%{private} translates to abcd{private} - all subsequent vars are skipped
1791 strcat_s(ptr2, effectiveSize - (ptr2 - format2), "{private}");
1792 ptr2 = format2 + strlen(format2);
1793 break;
1794 }
1795 } else {
1796 // other symbols are just copied
1797 *ptr2++ = *ptr1++;
1798 }
1799 }
1800 *ptr2++ = 0;
1801
1802 char outStr[maxSize] = {0};
1803 if (vsprintf_s(outStr, sizeof(outStr), format2, argptr) > 0) {
1804 SendRSLogBase(type, std::string(outStr));
1805 }
1806 }
1807
ReceiveRSLogBase()1808 RSProfilerLogMsg RSProfiler::ReceiveRSLogBase()
1809 {
1810 const std::lock_guard<std::mutex> guard(g_rsLogListMutex);
1811 if (g_rsLogList.empty()) {
1812 return RSProfilerLogMsg();
1813 }
1814 auto value = g_rsLogList.front();
1815 g_rsLogList.pop();
1816 return value;
1817 }
1818
SendRSLogBase(RSProfilerLogType type,const std::string & msg)1819 void RSProfiler::SendRSLogBase(RSProfilerLogType type, const std::string& msg)
1820 {
1821 if (IsReadEmulationMode()) {
1822 if (type == RSProfilerLogType::WARNING) {
1823 RSProfiler::SendMessageBase("RS_LOGW: " + msg);
1824 } else if (type == RSProfilerLogType::ERROR) {
1825 RSProfiler::SendMessageBase("RS_LOGE: " + msg);
1826 }
1827 } else {
1828 const std::lock_guard<std::mutex> guard(g_rsLogListMutex);
1829 g_rsLogList.push(RSProfilerLogMsg(type, Utils::Now(), msg));
1830 }
1831 }
1832
ResetCustomMetrics()1833 void RSProfiler::ResetCustomMetrics()
1834 {
1835 RSProfilerCustomMetrics& customMetrics = GetCustomMetrics();
1836 customMetrics.Reset();
1837 }
1838
GetCustomMetrics()1839 RSProfilerCustomMetrics& RSProfiler::GetCustomMetrics()
1840 {
1841 static RSProfilerCustomMetrics s_customMetrics;
1842 return s_customMetrics;
1843 }
1844
IsRecordingMode()1845 bool RSProfiler::IsRecordingMode()
1846 {
1847 return IsEnabled() && IsWriteMode();
1848 }
1849
1850 } // namespace OHOS::Rosen
1851