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 <cstddef>
17 #include <fstream>
18 #include <filesystem>
19 #include <numeric>
20 #include <system_error>
21
22 #include "rs_profiler.h"
23 #include "rs_profiler_file.h"
24 #include "rs_profiler_archive.h"
25 #include "rs_profiler_cache.h"
26 #include "rs_profiler_capture_recorder.h"
27 #include "rs_profiler_capturedata.h"
28 #include "rs_profiler_command.h"
29 #include "rs_profiler_file.h"
30 #include "rs_profiler_json.h"
31 #include "rs_profiler_log.h"
32 #include "rs_profiler_network.h"
33 #include "rs_profiler_packet.h"
34 #include "rs_profiler_settings.h"
35 #include "rs_profiler_telemetry.h"
36 #include "params/rs_screen_render_params.h"
37 #include "pipeline/main_thread/rs_main_thread.h"
38 #include "pipeline/rs_render_node_gc.h"
39 #include "pipeline/main_thread/rs_render_service_connection.h"
40 #include "pipeline/render_thread/rs_uni_render_util.h"
41 #include "render/rs_typeface_cache.h"
42
43 namespace OHOS::Rosen {
44
45 const RSProfiler::CommandRegistry RSProfiler::COMMANDS = {
46 { "rstree_kill_node", KillNode },
47 { "rstree_setparent", AttachChild },
48 { "rstree_node_mod", DumpNodeModifiers },
49 { "rstree_node_prop", DumpNodeProperties },
50 { "rstree_kill_pid", KillPid },
51 { "rstree_prepare_replay", PlaybackPrepare },
52 { "rstree_save_frame", TestSaveFrame },
53 { "rstree_load_frame", TestLoadFrame },
54 { "rssubtree_save", TestSaveSubTree },
55 { "rssubtree_load", TestLoadSubTree },
56 { "rssubtree_clear", TestClearSubTree },
57 { "rstree_switch", TestSwitch },
58 { "rstree_dump_json", DumpTreeToJson },
59 { "rstree_clear_filter", ClearFilter },
60 { "rstree_blink_node", BlinkNode },
61 { "rstree_node_cache", PrintNodeCache },
62 { "rstree_node_cache_all", PrintNodeCacheAll },
63 { "rsrecord_start", RecordStart },
64 { "rsrecord_stop", RecordStop },
65 { "rsrecord_compression", RecordCompression },
66 { "rsrecord_replay_prepare", PlaybackPrepareFirstFrame },
67 { "rsrecord_replay", PlaybackStart },
68 { "rsrecord_replay_stop", PlaybackStop },
69 { "rsrecord_pause_now", PlaybackPause },
70 { "rsrecord_pause_at", PlaybackPauseAt },
71 { "rsrecord_pause_resume", PlaybackResume },
72 { "rsrecord_pause_clear", PlaybackPauseClear },
73 { "rsrecord_sendbinary", RecordSendBinary },
74 { "rsrecord_metrics", RecordMetrics },
75 { "rssurface_pid", DumpNodeSurface },
76 { "rscon_print", DumpConnections },
77 { "save_rdc", SaveRdc },
78 { "save_skp", SaveSkp },
79 { "save_offscreen", SaveOffscreenSkp },
80 { "save_component", SaveComponentSkp },
81 { "save_imgcache", SaveSkpImgCache },
82 { "save_oncapture", SaveSkpOnCapture },
83 { "save_extended", SaveSkpExtended },
84 { "info", GetDeviceInfo },
85 { "freq", GetDeviceFrequency },
86 { "set", SetSystemParameter },
87 { "get", GetSystemParameter },
88 { "params", DumpSystemParameters },
89 { "get_perf_tree", GetPerfTree },
90 { "calc_perf_node", CalcPerfNode },
91 { "calc_perf_node_all", CalcPerfNodeAll },
92 { "socket_shutdown", SocketShutdown },
93 { "version", Version },
94 { "file_version", FileVersion },
95 { "drawing_canvas", DumpDrawingCanvasNodes },
96 { "drawing_canvas_enable", DrawingCanvasRedrawEnable },
97 { "keep_draw_cmd", RenderNodeKeepDrawCmd },
98 { "rsrecord_replay_speed", PlaybackSetSpeed },
99 { "rsrecord_replay_immediate", PlaybackSetImmediate },
100 { "build_test_tree", BuildTestTree },
101 { "clear_test_tree", ClearTestTree },
102 };
103
Invoke(const std::vector<std::string> & line)104 void RSProfiler::Invoke(const std::vector<std::string>& line)
105 {
106 if (line.empty() || line[0].empty()) {
107 return;
108 }
109
110 const auto delegate = COMMANDS.find(line[0]);
111 if (delegate == COMMANDS.end()) {
112 Respond("Command has not been found: " + line[0]);
113 return;
114 }
115
116 const ArgList args = (line.size() > 1) ? ArgList({ line.begin() + 1, line.end() }) : ArgList();
117 delegate->second(args);
118 }
119
RecordCompression(const ArgList & args)120 void RSProfiler::RecordCompression(const ArgList& args)
121 {
122 int type = args.Int64(0);
123 if (type < 0 || type > static_cast<int>(TextureRecordType::NO_COMPRESSION)) {
124 type = static_cast<int>(TextureRecordType::NO_COMPRESSION);
125 }
126 SetTextureRecordType(static_cast<TextureRecordType>(type));
127 SendMessage("Texture Compression Level %d", type);
128 }
129
SaveSkp(const ArgList & args)130 void RSProfiler::SaveSkp(const ArgList& args)
131 {
132 const auto nodeId = args.Node();
133 RSCaptureRecorder::GetInstance().SetDrawingCanvasNodeId(nodeId);
134 if (nodeId == 0) {
135 RSSystemProperties::SetInstantRecording(true);
136 SendMessage("Recording full frame .skp");
137 } else {
138 SendMessage("Recording .skp for DrawingCanvasNode: id= %" PRId64 "", nodeId);
139 }
140 AwakeRenderServiceThread();
141 }
142
SetSkpAndClear()143 static void SetSkpAndClear()
144 {
145 RSCaptureRecorder::GetInstance().SetCaptureTypeClear(true);
146 RSSystemProperties::SetInstantRecording(true);
147 }
148
SaveSkpImgCache(const ArgList & args)149 void RSProfiler::SaveSkpImgCache(const ArgList& args)
150 {
151 const auto option = args.Uint32();
152 if (option == 0) {
153 RSCaptureRecorder::GetInstance().SetCaptureType(SkpCaptureType::DEFAULT);
154 SetSkpAndClear();
155 SendMessage("Recording full frame .skp, default capturing of caсhed content");
156 } else if (option == 1) {
157 RSCaptureRecorder::GetInstance().SetCaptureType(SkpCaptureType::IMG_CACHED);
158 SetSkpAndClear();
159 SendMessage("Recording full frame .skp, drawing of cached img");
160 } else {
161 SendMessage("Invalid argument for: skp_imgcache");
162 }
163 AwakeRenderServiceThread();
164 }
165
SaveSkpOnCapture(const ArgList & args)166 void RSProfiler::SaveSkpOnCapture(const ArgList& args)
167 {
168 const auto option = args.Node();
169 if (option != 0) {
170 SendMessage("There's no argument for the command: skp_oncapture");
171 return;
172 }
173 RSCaptureRecorder::GetInstance().SetCaptureType(SkpCaptureType::ON_CAPTURE);
174 SetSkpAndClear();
175 SendMessage("Recording full frame .skp, OnCapture call for mirrored node");
176 AwakeRenderServiceThread();
177 }
178
SaveSkpExtended(const ArgList & args)179 void RSProfiler::SaveSkpExtended(const ArgList& args)
180 {
181 const auto option = args.Node();
182 if (option != 0) {
183 SendMessage("There's no argument for the command: skp_extended");
184 return;
185 }
186 RSCaptureRecorder::GetInstance().SetCaptureType(SkpCaptureType::EXTENDED);
187 SetSkpAndClear();
188 SendMessage("Recording full frame .skp, offscreen rendering for extended screen");
189 AwakeRenderServiceThread();
190 }
191
SaveOffscreenSkp(const ArgList & args)192 void RSProfiler::SaveOffscreenSkp(const ArgList& args)
193 {
194 if (!context_) {
195 return;
196 }
197 const auto nodeIdArg = args.Node();
198 SendMessage("Trying to playback the drawing commands for node: %" PRId64 "", nodeIdArg);
199 if (nodeIdArg == 0) {
200 SendMessage("Pass correct node id in args: save_offscreen <node_id>");
201 return;
202 }
203 const auto& map = context_->GetMutableNodeMap();
204 map.TraversalNodes([nodeIdArg](const std::shared_ptr<RSBaseRenderNode>& node) {
205 if (!node || (node->GetId() != nodeIdArg)) {
206 return;
207 }
208 if (node->IsOnTheTree()) {
209 SendMessage("Node is on tree, pick off-screen node");
210 return;
211 }
212 SendMessage("Node found, trying to capture");
213 auto drawable = std::reinterpret_pointer_cast<DrawableV2::RSRenderNodeDrawable>(node->GetRenderDrawable());
214 if (drawable == nullptr) {
215 return;
216 }
217 auto& drawableRenderParams = drawable->GetRenderParams();
218 if (drawableRenderParams == nullptr) {
219 return;
220 }
221 auto nodeRect = drawableRenderParams->GetAbsDrawRect();
222 if (auto canvasRec = RSCaptureRecorder::GetInstance().TryOffscreenCanvasCapture(
223 nodeRect.GetWidth(), nodeRect.GetHeight())) {
224 RSPaintFilterCanvas paintFilterCanvas(canvasRec);
225 drawable->OnDraw(paintFilterCanvas);
226 RSCaptureRecorder::GetInstance().EndOffscreenCanvasCapture();
227 }
228 });
229 }
230
SaveComponentSkp(const ArgList & args)231 void RSProfiler::SaveComponentSkp(const ArgList& args)
232 {
233 RSCaptureRecorder::GetInstance().SetComponentScreenshotFlag(true);
234 SendMessage("Capturing for the next \"Component Screenshot\" is set.");
235 }
236
SetSystemParameter(const ArgList & args)237 void RSProfiler::SetSystemParameter(const ArgList& args)
238 {
239 if (!SystemParameter::Set(args.String(0), args.String(1))) {
240 Respond("There is no such a system parameter");
241 }
242 }
243
GetSystemParameter(const ArgList & args)244 void RSProfiler::GetSystemParameter(const ArgList& args)
245 {
246 const auto parameter = SystemParameter::Find(args.String());
247 Respond(parameter ? parameter->ToString() : "There is no such a system parameter");
248 }
249
DumpSystemParameters(const ArgList & args)250 void RSProfiler::DumpSystemParameters(const ArgList& args)
251 {
252 Respond(SystemParameter::Dump());
253 }
254
DumpNodeModifiers(const ArgList & args)255 void RSProfiler::DumpNodeModifiers(const ArgList& args)
256 {
257 if (const auto node = GetRenderNode(args.Node())) {
258 Respond("Modifiers=" + DumpModifiers(*node));
259 }
260 }
261
DumpNodeProperties(const ArgList & args)262 void RSProfiler::DumpNodeProperties(const ArgList& args)
263 {
264 if (const auto node = GetRenderNode(args.Node())) {
265 Respond("RenderProperties=" + DumpRenderProperties(*node));
266 }
267 }
268
PlaybackSetSpeed(const ArgList & args)269 void RSProfiler::PlaybackSetSpeed(const ArgList& args)
270 {
271 const auto speed = args.Fp64();
272 if (BaseSetPlaybackSpeed(speed)) {
273 Respond("Playback speed: " + std::to_string(speed));
274 } else {
275 Respond("Playback speed: change rejected");
276 }
277 }
278
DrawingCanvasRedrawEnable(const ArgList & args)279 void RSProfiler::DrawingCanvasRedrawEnable(const ArgList& args)
280 {
281 const auto enable = args.Uint64(); // 0 - disabled, >0 - enabled
282 RSProfiler::SetDrawingCanvasNodeRedraw(enable > 0);
283 }
284
RenderNodeKeepDrawCmd(const ArgList & args)285 void RSProfiler::RenderNodeKeepDrawCmd(const ArgList& args)
286 {
287 const auto enable = args.Uint64(); // 0 - disabled, >0 - enabled
288 SendMessage("Set: KeepDrawCmdList to: %s", enable > 0 ? "true" : "false");
289 RSProfiler::SetRenderNodeKeepDrawCmd(enable > 0);
290 }
291
ClearFilter(const ArgList & args)292 void RSProfiler::ClearFilter(const ArgList& args)
293 {
294 const auto node = GetRenderNode(args.Node());
295 if (!node) {
296 Respond("error: node not found");
297 return;
298 }
299
300 node->GetMutableRenderProperties().backgroundFilter_ = nullptr;
301 Respond("OK");
302 AwakeRenderServiceThread();
303 }
304
KillNode(const ArgList & args)305 void RSProfiler::KillNode(const ArgList& args)
306 {
307 if (const auto node = GetRenderNode(args.Node())) {
308 node->RemoveFromTree(false);
309 AwakeRenderServiceThread();
310 Respond("OK");
311 }
312 }
313
AttachChild(const ArgList & args)314 void RSProfiler::AttachChild(const ArgList& args)
315 {
316 auto child = GetRenderNode(args.Uint64(0));
317 auto parent = GetRenderNode(args.Uint64(1));
318 if (parent && child) {
319 parent->AddChild(child);
320 AwakeRenderServiceThread();
321 Respond("OK");
322 }
323 }
324
GetDeviceInfo(const ArgList & args)325 void RSProfiler::GetDeviceInfo(const ArgList& args)
326 {
327 Respond(RSTelemetry::GetDeviceInfoString());
328 }
329
GetDeviceFrequency(const ArgList & args)330 void RSProfiler::GetDeviceFrequency(const ArgList& args)
331 {
332 Respond(RSTelemetry::GetDeviceFrequencyString());
333 Respond(RSTelemetry::GetCpuAffinityString());
334 }
335
PrintNodeCache(const ArgList & args)336 void RSProfiler::PrintNodeCache(const ArgList& args)
337 {
338 NodeId nodeId = args.Uint64();
339 auto node = GetRenderNode(nodeId);
340 if (node == nullptr) {
341 Respond("node not found");
342 return;
343 }
344 PrintNodeCacheLo(node);
345 }
346
PrintNodeCacheAll(const ArgList & args)347 void RSProfiler::PrintNodeCacheAll(const ArgList& args)
348 {
349 auto& nodeMap = RSMainThread::Instance()->GetContext().GetMutableNodeMap();
350 nodeMap.TraversalNodes([](const std::shared_ptr<RSBaseRenderNode>& node) {
351 if (node == nullptr) {
352 return;
353 }
354 PrintNodeCacheLo(node);
355 });
356 }
357
SocketShutdown(const ArgList & args)358 void RSProfiler::SocketShutdown(const ArgList& args)
359 {
360 Network::ForceShutdown();
361 }
362
Version(const ArgList & args)363 void RSProfiler::Version(const ArgList& args)
364 {
365 Respond("Version: " + std::to_string(RSFILE_VERSION_LATEST));
366 }
367
FileVersion(const ArgList & args)368 void RSProfiler::FileVersion(const ArgList& args)
369 {
370 Respond("File version: " + std::to_string(RSFILE_VERSION_LATEST));
371 }
372
RecordSendBinary(const ArgList & args)373 void RSProfiler::RecordSendBinary(const ArgList& args)
374 {
375 bool flag = args.Int8(0);
376 Network::SetBlockBinary(!flag);
377 if (flag) {
378 SendMessage("Result: data will be sent to client during recording"); // DO NOT TOUCH!
379 } else {
380 SendMessage("Result: data will NOT be sent to client during recording"); // DO NOT TOUCH!
381 }
382 }
383
PlaybackPauseClear(const ArgList & args)384 void RSProfiler::PlaybackPauseClear(const ArgList& args)
385 {
386 TimePauseClear();
387 Respond("OK");
388 }
389
PlaybackResume(const ArgList & args)390 void RSProfiler::PlaybackResume(const ArgList& args)
391 {
392 if (!IsPlaying()) {
393 return;
394 }
395
396 TimePauseResume(Utils::Now());
397 ResetAnimationStamp();
398 Respond("OK");
399 }
400
RsMetricGetList()401 std::string RSProfiler::RsMetricGetList()
402 {
403 auto& customMetrics = GetCustomMetrics();
404 return customMetrics.GetList();
405 }
406
RecordMetrics(const ArgList & args)407 void RSProfiler::RecordMetrics(const ArgList& args)
408 {
409 std::string response = RsMetricGetList();
410 Respond("METRICS: " + response);
411 }
412
413
414 } // namespace OHOS::Rosen
415