• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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