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 <filesystem>
17 #include <numeric>
18 
19 #include "foundation/graphic/graphic_2d/utils/log/rs_trace.h"
20 #include "rs_profiler.h"
21 #include "rs_profiler_archive.h"
22 #include "rs_profiler_cache.h"
23 #include "rs_profiler_capture_recorder.h"
24 #include "rs_profiler_capturedata.h"
25 #include "rs_profiler_file.h"
26 #include "rs_profiler_json.h"
27 #include "rs_profiler_network.h"
28 #include "rs_profiler_settings.h"
29 #include "rs_profiler_telemetry.h"
30 #include "rs_profiler_utils.h"
31 #include "rs_profiler_packet.h"
32 
33 #include "params/rs_display_render_params.h"
34 #include "pipeline/rs_main_thread.h"
35 #include "pipeline/rs_render_service_connection.h"
36 #include "pipeline/rs_uni_render_util.h"
37 
38 namespace OHOS::Rosen {
39 
40 // (user): Move to RSProfiler
41 static RSRenderService* g_renderService = nullptr;
42 static std::atomic<int32_t> g_renderServiceCpuId = 0;
43 static std::atomic<int32_t> g_renderServiceRenderCpuId = 0;
44 static RSMainThread* g_mainThread = nullptr;
45 static RSContext* g_context = nullptr;
46 static uint64_t g_frameBeginTimestamp = 0u;
47 static uint64_t g_frameRenderBeginTimestamp = 0u;
48 static double g_dirtyRegionPercentage = 0.0;
49 static bool g_rdcSent = true;
50 
51 static std::atomic<uint32_t> g_lastCacheImageCount = 0;
52 
53 static RSFile g_recordFile {};
54 static double g_recordStartTime = 0.0;
55 static uint32_t g_frameNumber = 0;
56 
57 static RSFile g_playbackFile {};
58 static double g_playbackStartTime = 0.0;
59 static NodeId g_playbackParentNodeId = 0;
60 static int g_playbackPid = 0;
61 static bool g_playbackShouldBeTerminated = true;
62 static double g_playbackPauseTime = 0;
63 static int g_playbackWaitFrames = 0;
64 
65 static std::unordered_set<NodeId> g_nodeSetPerf;
66 static std::unordered_map<NodeId, int> g_mapNode2Count;
67 static NodeId g_calcPerfNode = 0;
68 static int g_calcPerfNodeTry = 0;
69 static bool g_calcPerfNodeExcludeDown = false;
70 
71 constexpr int CALC_PERF_NODE_TIME_COUNT = 64; // increased to improve reliability of perfomance measurement
72 static uint64_t g_calcPerfNodeTime[CALC_PERF_NODE_TIME_COUNT];
73 static NodeId g_calcPerfNodeParent = 0;
74 static int g_calcPerfNodeIndex = 0;
75 static int g_nodeSetPerfCalcIndex = -1;
76 static std::string g_testDataFrame;
77 static std::vector<RSRenderNode::SharedPtr> g_childOfDisplayNodes;
78 
79 #pragma pack(push, 1)
80 struct AlignedMessageParcel {
81     uint8_t pad = 0u;
82     MessageParcel parcel;
83 };
84 #pragma pack(pop)
85 
DeviceInfoToCaptureData(double time,const DeviceInfo & in,RSCaptureData & out)86 void DeviceInfoToCaptureData(double time, const DeviceInfo& in, RSCaptureData& out)
87 {
88     std::string frequency;
89     std::string load;
90     for (uint32_t i = 0; i < in.cpu.cores; i++) {
91         frequency += std::to_string(in.cpu.coreFrequencyLoad[i].current);
92         load += std::to_string(in.cpu.coreFrequencyLoad[i].load);
93         if (i + 1 < in.cpu.cores) {
94             frequency += ";";
95             load += ";";
96         }
97     }
98 
99     out.SetTime(static_cast<float>(time));
100     out.SetProperty(RSCaptureData::KEY_CPU_TEMP, in.cpu.temperature);
101     out.SetProperty(RSCaptureData::KEY_CPU_CURRENT, in.cpu.current);
102     out.SetProperty(RSCaptureData::KEY_CPU_LOAD, load);
103     out.SetProperty(RSCaptureData::KEY_CPU_FREQ, frequency);
104     out.SetProperty(RSCaptureData::KEY_GPU_LOAD, in.gpu.frequencyLoad.load);
105     out.SetProperty(RSCaptureData::KEY_GPU_FREQ, in.gpu.frequencyLoad.current);
106 }
107 
GetPid(const std::shared_ptr<RSRenderNode> & node)108 static pid_t GetPid(const std::shared_ptr<RSRenderNode>& node)
109 {
110     return node ? Utils::ExtractPid(node->GetId()) : 0;
111 }
112 
GetNodeId(const std::shared_ptr<RSRenderNode> & node)113 static NodeId GetNodeId(const std::shared_ptr<RSRenderNode>& node)
114 {
115     return node ? Utils::ExtractNodeId(node->GetId()) : 0;
116 }
117 
SendTelemetry(double time)118 static void SendTelemetry(double time)
119 {
120     if (time >= 0.0) {
121         RSCaptureData captureData;
122         DeviceInfoToCaptureData(time, RSTelemetry::GetDeviceInfo(), captureData);
123         Network::SendCaptureData(captureData);
124     }
125 }
126 
127 /*
128     To visualize the damage region (as it's set for KHR_partial_update), you can set the following variable:
129     'hdc shell param set rosen.dirtyregiondebug.enabled 6'
130 */
SetDirtyRegion(const Occlusion::Region & dirtyRegion)131 void RSProfiler::SetDirtyRegion(const Occlusion::Region& dirtyRegion)
132 {
133     if (!IsRecording()) {
134         return;
135     }
136 
137     const double maxPercentValue = 100.0;
138     g_dirtyRegionPercentage = maxPercentValue;
139 
140     if (!g_context) {
141         return;
142     }
143     std::shared_ptr<RSDisplayRenderNode> displayNode = GetDisplayNode(*g_context);
144     if (!displayNode) {
145         return;
146     }
147     auto params = static_cast<RSDisplayRenderParams*>(displayNode->GetRenderParams().get());
148     if (!params) {
149         return;
150     }
151 
152     auto screenInfo = params->GetScreenInfo();
153     const uint64_t displayWidth = screenInfo.width;
154     const uint64_t displayHeight = screenInfo.height;
155     const uint64_t displayArea = displayWidth * displayHeight;
156 
157     auto rects = RSUniRenderUtil::ScreenIntersectDirtyRects(dirtyRegion, screenInfo);
158     uint64_t dirtyRegionArea = 0;
159     for (const auto& rect : rects) {
160         dirtyRegionArea += static_cast<uint64_t>(rect.GetWidth() * rect.GetHeight());
161     }
162 
163     if (displayArea > 0) {
164         g_dirtyRegionPercentage =
165             maxPercentValue * static_cast<double>(dirtyRegionArea) / static_cast<double>(displayArea);
166     }
167     if (g_dirtyRegionPercentage > maxPercentValue) {
168         g_dirtyRegionPercentage = maxPercentValue;
169     }
170 }
171 
Init(RSRenderService * renderService)172 void RSProfiler::Init(RSRenderService* renderService)
173 {
174     if (!IsEnabled()) {
175         return;
176     }
177 
178     g_renderService = renderService;
179     g_mainThread = g_renderService ? g_renderService->mainThread_ : nullptr;
180     g_context = g_mainThread ? g_mainThread->context_.get() : nullptr;
181 
182     if (!IsBetaRecordEnabled()) {
183         static auto const networkRunLambda = []() {
184             Network::Run();
185         };
186         static std::thread const thread(networkRunLambda);
187     }
188 }
189 
OnCreateConnection(pid_t pid)190 void RSProfiler::OnCreateConnection(pid_t pid)
191 {
192     if (!IsEnabled()) {
193         return;
194     }
195 
196     if (IsRecording()) {
197         g_recordFile.AddHeaderPid(pid);
198     }
199 }
200 
OnRemoteRequest(RSIRenderServiceConnection * connection,uint32_t code,MessageParcel & parcel,MessageParcel &,MessageOption & option)201 void RSProfiler::OnRemoteRequest(RSIRenderServiceConnection* connection, uint32_t code, MessageParcel& parcel,
202     MessageParcel& /*reply*/, MessageOption& option)
203 {
204     if (!IsEnabled()) {
205         return;
206     }
207 
208     if (IsRecording() && (g_recordStartTime > 0.0)) {
209         const pid_t pid = GetConnectionPid(connection);
210         const auto& pids = g_recordFile.GetHeaderPids();
211         if (std::find(std::begin(pids), std::end(pids), pid) != std::end(pids)) {
212             const double deltaTime = Now() - g_recordStartTime;
213 
214             std::stringstream stream(std::ios::in | std::ios::out | std::ios::binary);
215 
216             char headerType = 1; // parcel data
217             stream.write(reinterpret_cast<const char*>(&headerType), sizeof(headerType));
218             stream.write(reinterpret_cast<const char*>(&deltaTime), sizeof(deltaTime));
219 
220             // set sending pid
221             stream.write(reinterpret_cast<const char*>(&pid), sizeof(pid));
222             stream.write(reinterpret_cast<const char*>(&code), sizeof(code));
223 
224             const size_t dataSize = parcel.GetDataSize();
225             stream.write(reinterpret_cast<const char*>(&dataSize), sizeof(dataSize));
226             stream.write(reinterpret_cast<const char*>(parcel.GetData()), dataSize);
227 
228             const int32_t flags = option.GetFlags();
229             stream.write(reinterpret_cast<const char*>(&flags), sizeof(flags));
230             const int32_t waitTime = option.GetWaitTime();
231             stream.write(reinterpret_cast<const char*>(&waitTime), sizeof(waitTime));
232 
233             const std::string out = stream.str();
234             constexpr size_t headerOffset = 8 + 1;
235             if (out.size() >= headerOffset) {
236                 g_recordFile.WriteRSData(deltaTime, out.data() + headerOffset, out.size() - headerOffset);
237             }
238             Network::SendBinary(out.data(), out.size());
239         }
240     }
241 
242     if (IsLoadSaveFirstScreenInProgress()) {
243         // saving screen right now
244     }
245     if (IsPlaying()) {
246         SetTransactionTimeCorrection(g_playbackStartTime, g_playbackFile.GetWriteTime());
247         SetSubstitutingPid(g_playbackFile.GetHeaderPids(), g_playbackPid, g_playbackParentNodeId);
248         SetMode(Mode::READ);
249     } else if (IsRecording()) {
250         SetMode(Mode::WRITE);
251     } else {
252         SetMode(Mode::NONE);
253     }
254 }
255 
OnRecvParcel(const MessageParcel * parcel,RSTransactionData * data)256 void RSProfiler::OnRecvParcel(const MessageParcel* parcel, RSTransactionData* data)
257 {
258     if (!IsEnabled()) {
259         return;
260     }
261 
262     if (parcel && IsParcelMock(*parcel)) {
263         data->SetSendingPid(Utils::GetMockPid(data->GetSendingPid()));
264     }
265 }
266 
CreateMockConnection(pid_t pid)267 void RSProfiler::CreateMockConnection(pid_t pid)
268 {
269     if (!IsEnabled() || !g_renderService) {
270         return;
271     }
272 
273     auto tokenObj = new IRemoteStub<RSIConnectionToken>();
274 
275     sptr<RSIRenderServiceConnection> newConn(new RSRenderServiceConnection(pid, g_renderService, g_mainThread,
276         g_renderService->screenManager_, tokenObj, g_renderService->appVSyncDistributor_));
277 
278     sptr<RSIRenderServiceConnection> tmp;
279 
280     std::unique_lock<std::mutex> lock(g_renderService->mutex_);
281     // if connections_ has the same token one, replace it.
282     if (g_renderService->connections_.count(tokenObj) > 0) {
283         tmp = g_renderService->connections_.at(tokenObj);
284     }
285     g_renderService->connections_[tokenObj] = newConn;
286     lock.unlock();
287     g_mainThread->AddTransactionDataPidInfo(pid);
288 }
289 
GetConnection(pid_t pid)290 RSRenderServiceConnection* RSProfiler::GetConnection(pid_t pid)
291 {
292     if (!g_renderService) {
293         return nullptr;
294     }
295 
296     for (const auto& pair : g_renderService->connections_) {
297         auto connection = static_cast<RSRenderServiceConnection*>(pair.second.GetRefPtr());
298         if (connection->remotePid_ == pid) {
299             return connection;
300         }
301     }
302 
303     return nullptr;
304 }
305 
GetConnectionPid(RSIRenderServiceConnection * connection)306 pid_t RSProfiler::GetConnectionPid(RSIRenderServiceConnection* connection)
307 {
308     if (!g_renderService || !connection) {
309         return 0;
310     }
311 
312     for (const auto& pair : g_renderService->connections_) {
313         auto renderServiceConnection = static_cast<RSRenderServiceConnection*>(pair.second.GetRefPtr());
314         if (renderServiceConnection == connection) {
315             return renderServiceConnection->remotePid_;
316         }
317     }
318 
319     return 0;
320 }
321 
GetConnectionsPids()322 std::vector<pid_t> RSProfiler::GetConnectionsPids()
323 {
324     if (!g_renderService) {
325         return {};
326     }
327 
328     std::vector<pid_t> pids;
329     pids.reserve(g_renderService->connections_.size());
330     for (const auto& pair : g_renderService->connections_) {
331         pids.push_back(static_cast<RSRenderServiceConnection*>(pair.second.GetRefPtr())->remotePid_);
332     }
333     return pids;
334 }
335 
OnProcessCommand()336 void RSProfiler::OnProcessCommand()
337 {
338     if (!IsEnabled()) {
339         return;
340     }
341 
342     if (IsPlaying()) {
343         ResetAnimationStamp();
344     }
345 }
346 
OnRenderBegin()347 void RSProfiler::OnRenderBegin()
348 {
349     if (!IsEnabled()) {
350         return;
351     }
352     RS_LOGD("RSProfiler::OnRenderBegin(): enabled"); // NOLINT
353     g_renderServiceCpuId = Utils::GetCpuId();
354 }
355 
OnRenderEnd()356 void RSProfiler::OnRenderEnd()
357 {
358     if (!IsEnabled()) {
359         return;
360     }
361 
362     g_renderServiceCpuId = Utils::GetCpuId();
363 }
364 
OnParallelRenderBegin()365 void RSProfiler::OnParallelRenderBegin()
366 {
367     if (!IsEnabled()) {
368         return;
369     }
370 
371     if (g_calcPerfNode > 0) {
372         // force render thread to be on fastest CPU
373         constexpr uint32_t spamCount = 10'000;
374         std::vector<int> data;
375         data.resize(spamCount);
376         for (uint32_t i = 0; i < spamCount; i++) {
377             for (uint32_t j = i + 1; j < spamCount; j++) {
378                 std::swap(data[i], data[j]);
379             }
380         }
381 
382         constexpr uint32_t trashCashStep = 64;
383         constexpr uint32_t newCount = spamCount * trashCashStep;
384         constexpr int trashNum = 0x7F;
385         data.resize(newCount);
386         for (uint32_t i = 0; i < spamCount; i++) {
387             data[i * trashCashStep] = trashNum;
388         }
389     }
390 
391     g_frameRenderBeginTimestamp = RawNowNano();
392 }
393 
OnParallelRenderEnd(uint32_t frameNumber)394 void RSProfiler::OnParallelRenderEnd(uint32_t frameNumber)
395 {
396     const uint64_t frameLengthNanosecs = RawNowNano() - g_frameRenderBeginTimestamp;
397     CalcNodeWeigthOnFrameEnd(frameLengthNanosecs);
398 
399     if (!IsRecording() || (g_recordStartTime <= 0.0)) {
400         return;
401     }
402 
403     const double currentTime = static_cast<double>(g_frameRenderBeginTimestamp) * 1e-9;
404     const double timeSinceRecordStart = currentTime - g_recordStartTime;
405 
406     if (timeSinceRecordStart > 0.0) {
407         RSCaptureData captureData;
408         captureData.SetTime(timeSinceRecordStart);
409         captureData.SetProperty(RSCaptureData::KEY_RENDER_FRAME_NUMBER, frameNumber);
410         captureData.SetProperty(RSCaptureData::KEY_RENDER_FRAME_LEN, frameLengthNanosecs);
411 
412         std::vector<char> out;
413         DataWriter archive(out);
414         char headerType = static_cast<char>(PackageID::RS_PROFILER_RENDER_METRICS);
415         archive.Serialize(headerType);
416         captureData.Serialize(archive);
417 
418         Network::SendBinary(out.data(), out.size());
419         g_recordFile.WriteRSMetrics(0, timeSinceRecordStart, out.data(), out.size());
420     }
421 }
422 
ShouldBlockHWCNode()423 bool RSProfiler::ShouldBlockHWCNode()
424 {
425     if (!IsEnabled()) {
426         return false;
427     }
428 
429     return GetMode() == Mode::READ;
430 }
431 
OnFrameBegin()432 void RSProfiler::OnFrameBegin()
433 {
434     if (!IsEnabled()) {
435         return;
436     }
437 
438     g_frameBeginTimestamp = RawNowNano();
439     g_renderServiceCpuId = Utils::GetCpuId();
440     g_frameNumber++;
441 
442     StartBetaRecord();
443 }
444 
OnFrameEnd()445 void RSProfiler::OnFrameEnd()
446 {
447     if (!IsEnabled()) {
448         return;
449     }
450 
451     g_renderServiceCpuId = Utils::GetCpuId();
452     ProcessCommands();
453     ProcessSendingRdc();
454     RecordUpdate();
455 
456     UpdateDirtyRegionBetaRecord(g_dirtyRegionPercentage);
457     UpdateBetaRecord();
458 
459     g_renderServiceCpuId = Utils::GetCpuId();
460 }
461 
CalcNodeWeigthOnFrameEnd(uint64_t frameLength)462 void RSProfiler::CalcNodeWeigthOnFrameEnd(uint64_t frameLength)
463 {
464     g_renderServiceRenderCpuId = Utils::GetCpuId();
465 
466     if (g_calcPerfNode == 0 || g_calcPerfNodeTry < 0 || g_calcPerfNodeTry > CALC_PERF_NODE_TIME_COUNT) {
467         return;
468     }
469 
470     g_calcPerfNodeTime[g_calcPerfNodeTry] = frameLength;
471     g_calcPerfNodeTry++;
472     if (g_calcPerfNodeTry < CALC_PERF_NODE_TIME_COUNT) {
473         AwakeRenderServiceThreadResetCaches();
474         return;
475     }
476 
477     constexpr NodeId renderEntireFrame = 1;
478 
479     std::sort(std::begin(g_calcPerfNodeTime), std::end(g_calcPerfNodeTime));
480     constexpr int32_t middle = CALC_PERF_NODE_TIME_COUNT / 2;
481     Respond("CALC_PERF_NODE_RESULT: " + std::to_string(g_calcPerfNode) + " " + "cnt=" +
482             std::to_string(g_mapNode2Count[g_calcPerfNode]) + " " + std::to_string(g_calcPerfNodeTime[middle]));
483     Network::SendRSTreeSingleNodePerf(g_calcPerfNode, g_calcPerfNodeTime[middle]);
484 
485     if (g_calcPerfNode != renderEntireFrame) {
486         auto parent = GetRenderNode(g_calcPerfNodeParent);
487         auto child = parent ? GetRenderNode(g_calcPerfNode) : nullptr;
488         if (child) {
489             parent->AddChild(child, g_calcPerfNodeIndex);
490         }
491     }
492 
493     g_calcPerfNode = 0;
494     g_calcPerfNodeParent = 0;
495     g_calcPerfNodeIndex = 0;
496     g_calcPerfNodeTry = 0;
497 
498     if (g_nodeSetPerfCalcIndex >= 0) {
499         g_nodeSetPerfCalcIndex++;
500         CalcPerfNodeAllStep();
501     }
502 
503     AwakeRenderServiceThread();
504     g_renderServiceCpuId = Utils::GetCpuId();
505 }
506 
RenderServiceTreeDump(JsonWriter & out)507 void RSProfiler::RenderServiceTreeDump(JsonWriter& out)
508 {
509     RS_TRACE_NAME("GetDumpTreeJSON");
510 
511     if (!g_context) {
512         return;
513     }
514 
515     auto& animation = out["Animation Node"];
516     animation.PushArray();
517     for (auto& [nodeId, _] : g_context->animatingNodeList_) {
518         animation.Append(nodeId);
519     }
520     animation.PopArray();
521 
522     auto& root = out["Root node"];
523     const auto rootNode = g_context->GetGlobalRootRenderNode();
524     if (rootNode) {
525         DumpNode(*rootNode, root);
526     } else {
527         root.PushObject();
528         root.PopObject();
529     }
530 }
531 
RawNowNano()532 uint64_t RSProfiler::RawNowNano()
533 {
534     return Utils::Now();
535 }
536 
NowNano()537 uint64_t RSProfiler::NowNano()
538 {
539     return PatchTime(RawNowNano());
540 }
541 
Now()542 double RSProfiler::Now()
543 {
544     return Utils::ToSeconds(NowNano());
545 }
546 
IsRecording()547 bool RSProfiler::IsRecording()
548 {
549     return IsEnabled() && g_recordFile.IsOpen();
550 }
551 
IsPlaying()552 bool RSProfiler::IsPlaying()
553 {
554     return IsEnabled() && g_playbackFile.IsOpen();
555 }
556 
ScheduleTask(std::function<void ()> && task)557 void RSProfiler::ScheduleTask(std::function<void()> && task)
558 {
559     if (g_mainThread) {
560         g_mainThread->PostTask(std::move(task));
561     }
562 }
563 
RequestNextVSync()564 void RSProfiler::RequestNextVSync()
565 {
566     if (g_mainThread) {
567         g_mainThread->RequestNextVSync();
568     }
569     ScheduleTask([]() { g_mainThread->RequestNextVSync(); });
570 }
571 
AwakeRenderServiceThread()572 void RSProfiler::AwakeRenderServiceThread()
573 {
574     if (g_mainThread) {
575         g_mainThread->RequestNextVSync();
576         g_mainThread->SetAccessibilityConfigChanged();
577         g_mainThread->SetDirtyFlag();
578     }
579     ScheduleTask([]() {
580         g_mainThread->SetAccessibilityConfigChanged();
581         g_mainThread->SetDirtyFlag();
582         g_mainThread->RequestNextVSync();
583     });
584 }
585 
AwakeRenderServiceThreadResetCaches()586 void RSProfiler::AwakeRenderServiceThreadResetCaches()
587 {
588     RSMainThread::Instance()->PostTask([]() {
589         RSMainThread::Instance()->SetAccessibilityConfigChanged();
590 
591         auto& nodeMap = RSMainThread::Instance()->GetContext().GetMutableNodeMap();
592         nodeMap.TraversalNodes([](const std::shared_ptr<RSBaseRenderNode>& node) {
593             if (node == nullptr) {
594                 return;
595             }
596             node->SetSubTreeDirty(true);
597             node->SetContentDirty();
598             node->SetDirty();
599         });
600 
601         nodeMap.TraverseSurfaceNodes([](const std::shared_ptr<RSSurfaceRenderNode>& surfaceNode) mutable {
602             if (surfaceNode == nullptr) {
603                 return;
604             }
605             surfaceNode->NeedClearBufferCache();
606             surfaceNode->GetRSSurfaceHandler()->ResetBufferAvailableCount();
607             surfaceNode->GetRSSurfaceHandler()->CleanCache();
608             surfaceNode->UpdateBufferInfo(nullptr, {}, nullptr, nullptr);
609             surfaceNode->SetNotifyRTBufferAvailable(false);
610             surfaceNode->SetContentDirty();
611             surfaceNode->ResetHardwareEnabledStates();
612         });
613 
614         RSMainThread::Instance()->RequestNextVSync();
615     });
616 }
617 
618 
ResetAnimationStamp()619 void RSProfiler::ResetAnimationStamp()
620 {
621     if (g_mainThread && g_context) {
622         g_mainThread->lastAnimateTimestamp_ = g_context->GetCurrentTimestamp();
623     }
624 }
625 
GetRenderNode(uint64_t id)626 std::shared_ptr<RSRenderNode> RSProfiler::GetRenderNode(uint64_t id)
627 {
628     return g_context ? g_context->GetMutableNodeMap().GetRenderNode(id) : nullptr;
629 }
630 
IsLoadSaveFirstScreenInProgress()631 bool RSProfiler::IsLoadSaveFirstScreenInProgress()
632 {
633     return (GetMode() == Mode::WRITE_EMUL || GetMode() == Mode::READ_EMUL);
634 }
635 
HiddenSpaceTurnOn()636 void RSProfiler::HiddenSpaceTurnOn()
637 {
638     if (!g_childOfDisplayNodes.empty()) {
639         HiddenSpaceTurnOff();
640     }
641 
642     const auto& rootRenderNode = g_context->GetGlobalRootRenderNode();
643     auto& children = *rootRenderNode->GetChildren();
644     if (children.empty()) {
645         return;
646     }
647     if (auto& displayNode = children.front()) {
648         if (auto rootNode = GetRenderNode(Utils::PatchNodeId(0))) {
649             g_childOfDisplayNodes = *displayNode->GetChildren();
650 
651             displayNode->ClearChildren();
652             displayNode->AddChild(rootNode);
653         }
654     }
655 
656     g_mainThread->SetDirtyFlag();
657     AwakeRenderServiceThread();
658 }
659 
HiddenSpaceTurnOff()660 void RSProfiler::HiddenSpaceTurnOff()
661 {
662     const auto& rootRenderNode = g_context->GetGlobalRootRenderNode();
663     const auto& children = *rootRenderNode->GetChildren();
664     if (children.empty()) {
665         return;
666     }
667     if (auto& displayNode = children.front()) {
668         displayNode->ClearChildren();
669         for (const auto& child : g_childOfDisplayNodes) {
670             displayNode->AddChild(child);
671         }
672         FilterMockNode(*g_context);
673         g_childOfDisplayNodes.clear();
674     }
675 
676     g_mainThread->SetDirtyFlag();
677 
678     AwakeRenderServiceThread();
679 }
680 
FirstFrameMarshalling()681 std::string RSProfiler::FirstFrameMarshalling()
682 {
683     std::stringstream stream;
684     SetMode(Mode::WRITE_EMUL);
685     DisableSharedMemory();
686     MarshalNodes(*g_context, stream);
687     EnableSharedMemory();
688     SetMode(Mode::NONE);
689 
690     const int32_t focusPid = g_mainThread->focusAppPid_;
691     stream.write(reinterpret_cast<const char*>(&focusPid), sizeof(focusPid));
692 
693     const int32_t focusUid = g_mainThread->focusAppUid_;
694     stream.write(reinterpret_cast<const char*>(&focusUid), sizeof(focusUid));
695 
696     const uint64_t focusNodeId = g_mainThread->focusNodeId_;
697     stream.write(reinterpret_cast<const char*>(&focusNodeId), sizeof(focusNodeId));
698 
699     const std::string bundleName = g_mainThread->focusAppBundleName_;
700     size_t size = bundleName.size();
701     stream.write(reinterpret_cast<const char*>(&size), sizeof(size));
702     stream.write(reinterpret_cast<const char*>(bundleName.data()), size);
703 
704     const std::string abilityName = g_mainThread->focusAppAbilityName_;
705     size = abilityName.size();
706     stream.write(reinterpret_cast<const char*>(&size), sizeof(size));
707     stream.write(reinterpret_cast<const char*>(abilityName.data()), size);
708 
709     return stream.str();
710 }
711 
FirstFrameUnmarshalling(const std::string & data,uint32_t fileVersion)712 void RSProfiler::FirstFrameUnmarshalling(const std::string& data, uint32_t fileVersion)
713 {
714     std::stringstream stream;
715     stream.str(data);
716 
717     SetMode(Mode::READ_EMUL);
718 
719     DisableSharedMemory();
720     UnmarshalNodes(*g_context, stream, fileVersion);
721     EnableSharedMemory();
722 
723     SetMode(Mode::NONE);
724 
725     int32_t focusPid = 0;
726     stream.read(reinterpret_cast<char*>(&focusPid), sizeof(focusPid));
727 
728     int32_t focusUid = 0;
729     stream.read(reinterpret_cast<char*>(&focusUid), sizeof(focusUid));
730 
731     uint64_t focusNodeId = 0;
732     stream.read(reinterpret_cast<char*>(&focusNodeId), sizeof(focusNodeId));
733 
734     size_t size = 0;
735     stream.read(reinterpret_cast<char*>(&size), sizeof(size));
736     std::string bundleName;
737     bundleName.resize(size, ' ');
738     stream.read(reinterpret_cast<char*>(bundleName.data()), size);
739 
740     stream.read(reinterpret_cast<char*>(&size), sizeof(size));
741     std::string abilityName;
742     abilityName.resize(size, ' ');
743     stream.read(reinterpret_cast<char*>(abilityName.data()), size);
744 
745     focusPid = Utils::GetMockPid(focusPid);
746     focusNodeId = Utils::PatchNodeId(focusNodeId);
747 
748     CreateMockConnection(focusPid);
749     g_mainThread->SetFocusAppInfo(focusPid, focusUid, bundleName, abilityName, focusNodeId);
750 }
751 
SaveRdc(const ArgList & args)752 void RSProfiler::SaveRdc(const ArgList& args)
753 {
754     g_rdcSent = false;
755     RSSystemProperties::SetSaveRDC(true);
756     RSSystemProperties::SetInstantRecording(true);
757 
758     AwakeRenderServiceThread();
759     Respond("Recording current frame cmds (for .rdc) into : /data/default.drawing");
760 }
761 
SaveSkp(const ArgList & args)762 void RSProfiler::SaveSkp(const ArgList& args)
763 {
764     RSSystemProperties::SetInstantRecording(true);
765     AwakeRenderServiceThread();
766     Respond("Recording current frame cmds into : /data/default.skp");
767 }
768 
ProcessSendingRdc()769 void RSProfiler::ProcessSendingRdc()
770 {
771     if (!RSSystemProperties::GetSaveRDC() || g_rdcSent) {
772         return;
773     }
774     AwakeRenderServiceThread();
775 
776     if (!RSCaptureRecorder::PullAndSendRdc()) {
777         return;
778     }
779     RSSystemProperties::SetSaveRDC(false);
780     g_rdcSent = true;
781 }
782 
GetImagesAdded()783 static uint32_t GetImagesAdded()
784 {
785     const size_t count = ImageCache::Size();
786     const uint32_t added = count - g_lastCacheImageCount;
787     g_lastCacheImageCount = count;
788     return added;
789 }
790 
RecordUpdate()791 void RSProfiler::RecordUpdate()
792 {
793     if (!IsRecording() || (g_recordStartTime <= 0.0)) {
794         return;
795     }
796 
797     const uint64_t frameLengthNanosecs = RawNowNano() - g_frameBeginTimestamp;
798 
799     const double currentTime = g_frameBeginTimestamp * 1e-9; // Now();
800     const double timeSinceRecordStart = currentTime - g_recordStartTime;
801 
802     if (timeSinceRecordStart > 0.0) {
803         RSCaptureData captureData;
804         captureData.SetTime(timeSinceRecordStart);
805         captureData.SetProperty(RSCaptureData::KEY_RS_FRAME_NUMBER, g_frameNumber);
806         captureData.SetProperty(RSCaptureData::KEY_RS_FRAME_LEN, frameLengthNanosecs);
807         captureData.SetProperty(RSCaptureData::KEY_RS_CMD_COUNT, GetCommandCount());
808         captureData.SetProperty(RSCaptureData::KEY_RS_CMD_EXECUTE_COUNT, GetCommandExecuteCount());
809         captureData.SetProperty(RSCaptureData::KEY_RS_CMD_PARCEL_LIST, GetCommandParcelList(g_recordStartTime));
810         captureData.SetProperty(RSCaptureData::KEY_RS_PIXEL_IMAGE_ADDED, GetImagesAdded());
811         captureData.SetProperty(RSCaptureData::KEY_RS_DIRTY_REGION, floor(g_dirtyRegionPercentage));
812         captureData.SetProperty(RSCaptureData::KEY_RS_CPU_ID, g_renderServiceCpuId.load());
813 
814         std::vector<char> out;
815         DataWriter archive(out);
816         char headerType = static_cast<char>(PackageID::RS_PROFILER_RS_METRICS);
817         archive.Serialize(headerType);
818         captureData.Serialize(archive);
819 
820         Network::SendBinary(out.data(), out.size());
821         g_recordFile.WriteRSMetrics(0, timeSinceRecordStart, out.data(), out.size());
822     }
823 
824     WriteBetaRecordMetrics(g_recordFile, timeSinceRecordStart);
825 }
826 
Respond(const std::string & message)827 void RSProfiler::Respond(const std::string& message)
828 {
829     Network::SendMessage(message);
830 }
831 
SetSystemParameter(const ArgList & args)832 void RSProfiler::SetSystemParameter(const ArgList& args)
833 {
834     if (!SystemParameter::Set(args.String(0), args.String(1))) {
835         Respond("There is no such a system parameter");
836     }
837 }
838 
GetSystemParameter(const ArgList & args)839 void RSProfiler::GetSystemParameter(const ArgList& args)
840 {
841     const auto parameter = SystemParameter::Find(args.String());
842     Respond(parameter ? parameter->ToString() : "There is no such a system parameter");
843 }
844 
DumpSystemParameters(const ArgList & args)845 void RSProfiler::DumpSystemParameters(const ArgList& args)
846 {
847     Respond(SystemParameter::Dump());
848 }
849 
DumpConnections(const ArgList & args)850 void RSProfiler::DumpConnections(const ArgList& args)
851 {
852     if (!g_renderService) {
853         return;
854     }
855 
856     std::string out;
857     for (const auto& pid : GetConnectionsPids()) {
858         out += "pid=" + std::to_string(pid);
859 
860         const std::string path = "/proc/" + std::to_string(pid) + "/cmdline";
861         FILE* file = Utils::FileOpen(path, "r");
862         if (const size_t size = Utils::FileSize(file)) {
863             std::string content;
864             content.resize(size);
865             Utils::FileRead(file, content.data(), content.size());
866             Utils::FileClose(file);
867             out += " ";
868             out += content;
869         }
870         if (Utils::IsFileValid(file)) {
871             Utils::FileClose(file);
872         }
873         out += "\n";
874     }
875     Respond(out);
876 }
877 
DumpNodeModifiers(const ArgList & args)878 void RSProfiler::DumpNodeModifiers(const ArgList& args)
879 {
880     if (const auto node = GetRenderNode(args.Node())) {
881         Respond("Modifiers=" + DumpModifiers(*node));
882     }
883 }
884 
DumpNodeProperties(const ArgList & args)885 void RSProfiler::DumpNodeProperties(const ArgList& args)
886 {
887     if (const auto node = GetRenderNode(args.Node())) {
888         Respond("RenderProperties=" + DumpRenderProperties(*node));
889     }
890 }
891 
DumpTree(const ArgList & args)892 void RSProfiler::DumpTree(const ArgList& args)
893 {
894     if (!g_context) {
895         return;
896     }
897 
898     std::map<std::string, std::tuple<NodeId, std::string>> list;
899     GetSurfacesTrees(*g_context, list);
900 
901     std::string out = "Tree: count=" + std::to_string(static_cast<int>(GetRenderNodeCount(*g_context))) +
902                       " time=" + std::to_string(Now()) + "\n";
903 
904     const std::string& node = args.String();
905     for (const auto& item : list) {
906         if (std::strstr(item.first.data(), node.data())) {
907             out += "*** " + item.first + " pid=" + std::to_string(ExtractPid(std::get<0>(item.second))) +
908                    " lowId=" + std::to_string(Utils::ExtractNodeId(std::get<0>(item.second))) + "\n" +
909                    std::get<1>(item.second) + "\n";
910         }
911     }
912 
913     Respond(out);
914 }
915 
DumpTreeToJson(const ArgList & args)916 void RSProfiler::DumpTreeToJson(const ArgList& args)
917 {
918     if (!g_context) {
919         return;
920     }
921 
922     JsonWriter json;
923     json.PushObject();
924     RenderServiceTreeDump(json);
925 
926     auto& display = json["Display"];
927     auto displayNode = GetDisplayNode(*g_context);
928     auto dirtyManager = displayNode ? displayNode->GetDirtyManager() : nullptr;
929     if (dirtyManager) {
930         const auto displayRect = dirtyManager->GetSurfaceRect();
931         display = { displayRect.GetLeft(), displayRect.GetTop(), displayRect.GetRight(), displayRect.GetBottom() };
932     } else {
933         display = { 0.0f, 0.0f, 0.0f, 0.0f };
934     }
935 
936     json.PopObject();
937     Network::SendRSTreeDumpJSON(json.GetDumpString());
938 }
939 
DumpSurfaces(const ArgList & args)940 void RSProfiler::DumpSurfaces(const ArgList& args)
941 {
942     if (!g_context) {
943         return;
944     }
945 
946     std::map<NodeId, std::string> surfaces;
947     GetSurfacesTrees(*g_context, args.Pid(), surfaces);
948 
949     std::string out;
950     for (const auto& item : surfaces) {
951         out += "*** " + std::to_string(item.first) + " pid=" + std::to_string(ExtractPid(item.first)) +
952                " lowId=" + std::to_string(Utils::ExtractNodeId(item.first)) + "\n" + item.second + "\n";
953     }
954 
955     out += "TREE: count=" + std::to_string(static_cast<int32_t>(GetRenderNodeCount(*g_context))) +
956            " time=" + std::to_string(Now()) + "\n";
957 
958     Respond(out);
959 }
960 
DumpNodeSurface(const ArgList & args)961 void RSProfiler::DumpNodeSurface(const ArgList& args)
962 {
963     if (g_renderService) {
964         std::string out;
965         g_renderService->DumpSurfaceNode(out, Utils::GetRootNodeId(args.Node()));
966         Respond(out);
967     }
968 }
969 
PatchNode(const ArgList & args)970 void RSProfiler::PatchNode(const ArgList& args)
971 {
972     const auto node = GetRenderNode(args.Node());
973     if (!node) {
974         return;
975     }
976 
977     const Vector4f screenRect = GetScreenRect(*g_context);
978 
979     auto surfaceNode = static_cast<RSSurfaceRenderNode*>(node.get());
980     {
981         auto& region = const_cast<Occlusion::Region&>(surfaceNode->GetVisibleRegion());
982         region = Occlusion::Region({ screenRect[0], screenRect[1], screenRect[2], screenRect[3] }); // NOLINT
983     }
984 
985     RSProperties& properties = node->GetMutableRenderProperties();
986     properties.SetBounds(screenRect);
987     properties.SetFrame(screenRect);
988     properties.SetDrawRegion(std::make_shared<RectF>(screenRect));
989 
990     AwakeRenderServiceThread();
991 }
992 
KillNode(const ArgList & args)993 void RSProfiler::KillNode(const ArgList& args)
994 {
995     if (const auto node = GetRenderNode(args.Node())) {
996         node->RemoveFromTree(false);
997         AwakeRenderServiceThread();
998         Respond("OK");
999     }
1000 }
1001 
AttachChild(const ArgList & args)1002 void RSProfiler::AttachChild(const ArgList& args)
1003 {
1004     constexpr size_t parentIndex = 0;
1005     constexpr size_t childIndex = parentIndex + 2;
1006 
1007     auto parent = GetRenderNode(Utils::ComposeNodeId(args.Pid(parentIndex), args.Node(parentIndex + 1)));
1008     auto child = GetRenderNode(Utils::ComposeNodeId(args.Pid(childIndex), args.Node(childIndex + 1)));
1009     if (parent && child) {
1010         parent->AddChild(child);
1011         AwakeRenderServiceThread();
1012         Respond("OK");
1013     }
1014 }
1015 
KillPid(const ArgList & args)1016 void RSProfiler::KillPid(const ArgList& args)
1017 {
1018     const pid_t pid = args.Pid();
1019     if (const auto node = GetRenderNode(Utils::GetRootNodeId(static_cast<uint64_t>(pid)))) {
1020         const auto parent = node->GetParent().lock();
1021         const std::string out =
1022             "parentPid=" + std::to_string(GetPid(parent)) + " parentNode=" + std::to_string(GetNodeId(parent));
1023 
1024         g_context->GetMutableNodeMap().FilterNodeByPid(pid);
1025         AwakeRenderServiceThread();
1026         Respond(out);
1027     }
1028 }
1029 
GetRoot(const ArgList & args)1030 void RSProfiler::GetRoot(const ArgList& args)
1031 {
1032     if (!g_context) {
1033         return;
1034     }
1035 
1036     std::string out;
1037 
1038     const RSRenderNodeMap& map = g_context->GetMutableNodeMap();
1039     std::shared_ptr<RSRenderNode> node = map.GetRenderNode<RSRenderNode>(GetRandomSurfaceNode(*g_context));
1040     while (node && (node->GetId() != 0)) {
1041         std::string type;
1042         const RSRenderNodeType nodeType = node->GetType();
1043         if (nodeType == RSRenderNodeType::UNKNOW) {
1044             type = "UNKNOWN";
1045         } else if (nodeType == RSRenderNodeType::RS_NODE) {
1046             type = "NONE";
1047         } else if (nodeType == RSRenderNodeType::DISPLAY_NODE) {
1048             type = "DISPLAY_NODE";
1049         } else if (nodeType == RSRenderNodeType::EFFECT_NODE) {
1050             type = "EFFECT_NODE";
1051         } else if (nodeType == RSRenderNodeType::ROOT_NODE) {
1052             type = "ROOT_NODE";
1053         } else if (nodeType == RSRenderNodeType::CANVAS_DRAWING_NODE) {
1054             type = "CANVAS_DRAWING_NODE";
1055         }
1056 
1057         if (!type.empty()) {
1058             out += "pid=" + std::to_string(GetPid(node)) + " node_id=" + std::to_string(GetNodeId(node)) + "|" + type +
1059                    ";\n";
1060         }
1061 
1062         node = node->GetParent().lock();
1063     };
1064 
1065     if (node) {
1066         out += "ROOT_ID=" + std::to_string(node->GetId()); // DISPLAY_NODE;ohos.sceneboard
1067     }
1068 
1069     Respond(out);
1070 }
1071 
GetDeviceInfo(const ArgList & args)1072 void RSProfiler::GetDeviceInfo(const ArgList& args)
1073 {
1074     Respond(RSTelemetry::GetDeviceInfoString());
1075 }
1076 
GetDeviceFrequency(const ArgList & args)1077 void RSProfiler::GetDeviceFrequency(const ArgList& args)
1078 {
1079     Respond(RSTelemetry::GetDeviceFrequencyString());
1080     Respond(RSTelemetry::GetCpuAffinityString());
1081 }
1082 
FixDeviceEnv(const ArgList & args)1083 void RSProfiler::FixDeviceEnv(const ArgList& args)
1084 {
1085     constexpr int32_t cpu = 8;
1086     Utils::SetCpuAffinity(cpu);
1087     Respond("OK");
1088 }
1089 
GetPerfTree(const ArgList & args)1090 void RSProfiler::GetPerfTree(const ArgList& args)
1091 {
1092     if (!g_context) {
1093         return;
1094     }
1095 
1096     g_nodeSetPerf.clear();
1097     g_mapNode2Count.clear();
1098 
1099     auto& rootNode = g_context->GetGlobalRootRenderNode();
1100     auto rootNodeChildren = rootNode ? rootNode->GetSortedChildren() : nullptr;
1101     if (!rootNodeChildren) {
1102         Respond("ERROR");
1103         return;
1104     }
1105 
1106     for (const auto& child : *rootNodeChildren) {
1107         auto displayNode = RSBaseRenderNode::ReinterpretCast<RSDisplayRenderNode>(child);
1108         if (!displayNode) {
1109             continue;
1110         }
1111         std::vector<RSBaseRenderNode::SharedPtr> curAllSurfaces;
1112         displayNode->CollectSurface(displayNode, curAllSurfaces, true, false);
1113         for (auto& node : curAllSurfaces) {
1114             if (node) {
1115                 PerfTreeFlatten(*node, g_nodeSetPerf, g_mapNode2Count);
1116             }
1117         }
1118     }
1119 
1120     std::string outString;
1121     auto& nodeMap = g_context->GetMutableNodeMap();
1122     for (auto it = g_nodeSetPerf.begin(); it != g_nodeSetPerf.end(); it++) {
1123         auto node = nodeMap.GetRenderNode(*it);
1124         if (!node) {
1125             continue;
1126         }
1127         std::string sNodeType;
1128         RSRenderNode::DumpNodeType(node->GetType(), sNodeType);
1129         outString += (it != g_nodeSetPerf.begin() ? ", " : "") + std::to_string(*it) + ":" +
1130                      std::to_string(g_mapNode2Count[*it]) + " [" + sNodeType + "]";
1131     }
1132 
1133     Network::SendRSTreePerfNodeList(g_nodeSetPerf);
1134     Respond("OK: Count=" + std::to_string(g_nodeSetPerf.size()) + " LIST=[" + outString + "]");
1135 }
1136 
CalcPerfNode(const ArgList & args)1137 void RSProfiler::CalcPerfNode(const ArgList& args)
1138 {
1139     g_calcPerfNode = args.Uint64();
1140     auto node = GetRenderNode(g_calcPerfNode);
1141     const auto parent = node ? node->GetParent().lock() : nullptr;
1142     auto parentChildren = parent ? parent->GetChildren() : nullptr;
1143     if (!parentChildren) {
1144         return;
1145     }
1146 
1147     int index = 0;
1148     g_calcPerfNodeParent = parent->GetId();
1149     for (const auto& child : *parentChildren) {
1150         if (child && child->GetId() == node->GetId()) {
1151             g_calcPerfNodeIndex = index;
1152         }
1153     }
1154 
1155     parent->RemoveChild(node);
1156     Respond("CalcPerfNode: NodeRemoved index=" + std::to_string(index));
1157     AwakeRenderServiceThread();
1158 }
1159 
SocketShutdown(const ArgList & args)1160 void RSProfiler::SocketShutdown(const ArgList& args)
1161 {
1162     Network::ForceShutdown();
1163 }
1164 
Version(const ArgList & args)1165 void RSProfiler::Version(const ArgList& args)
1166 {
1167     Respond("Version: " + std::to_string(RSFILE_VERSION_LATEST));
1168 }
1169 
FileVersion(const ArgList & args)1170 void RSProfiler::FileVersion(const ArgList& args)
1171 {
1172     Respond("File version: " + std::to_string(RSFILE_VERSION_LATEST));
1173 }
1174 
CalcPerfNodeAll(const ArgList & args)1175 void RSProfiler::CalcPerfNodeAll(const ArgList& args)
1176 {
1177     if (g_nodeSetPerf.empty()) {
1178         Respond("ERROR");
1179         return;
1180     }
1181 
1182     g_nodeSetPerfCalcIndex = 0;
1183     CalcPerfNodeAllStep();
1184 
1185     AwakeRenderServiceThread();
1186 }
1187 
CalcPerfNodeAllStep()1188 void RSProfiler::CalcPerfNodeAllStep()
1189 {
1190     if (g_nodeSetPerfCalcIndex < 0) {
1191         return;
1192     }
1193 
1194     if (g_nodeSetPerfCalcIndex == 0) {
1195         g_calcPerfNode = 1;
1196         AwakeRenderServiceThread();
1197         return;
1198     }
1199 
1200     if (g_nodeSetPerfCalcIndex - 1 < static_cast<int32_t>(g_nodeSetPerf.size())) {
1201         auto it = g_nodeSetPerf.begin();
1202         std::advance(it, g_nodeSetPerfCalcIndex - 1);
1203         g_calcPerfNode = *it;
1204     } else {
1205         g_nodeSetPerfCalcIndex = -1;
1206         return;
1207     }
1208 
1209     auto node = GetRenderNode(g_calcPerfNode);
1210     const auto parent = node ? node->GetParent().lock() : nullptr;
1211     auto parentChildren = parent ? parent->GetChildren() : nullptr;
1212     if (!parentChildren) {
1213         g_nodeSetPerfCalcIndex = -1;
1214         return;
1215     }
1216 
1217     int index = 0;
1218     g_calcPerfNodeParent = parent->GetId();
1219     for (const auto& child : *parentChildren) {
1220         if (child && child->GetId() == node->GetId()) {
1221             g_calcPerfNodeIndex = index;
1222         }
1223     }
1224 
1225     parent->RemoveChild(node);
1226     AwakeRenderServiceThread();
1227 }
1228 
TestSaveFrame(const ArgList & args)1229 void RSProfiler::TestSaveFrame(const ArgList& args)
1230 {
1231     g_testDataFrame = FirstFrameMarshalling();
1232     Respond("Save Frame Size: " + std::to_string(g_testDataFrame.size()));
1233 }
1234 
TestLoadFrame(const ArgList & args)1235 void RSProfiler::TestLoadFrame(const ArgList& args)
1236 {
1237     FirstFrameUnmarshalling(g_testDataFrame, RSFILE_VERSION_LATEST);
1238     Respond("Load Frame Size: " + std::to_string(g_testDataFrame.size()));
1239 }
1240 
TestSwitch(const ArgList & args)1241 void RSProfiler::TestSwitch(const ArgList& args)
1242 {
1243     if (g_childOfDisplayNodes.empty()) {
1244         HiddenSpaceTurnOn();
1245         Respond("OK: HiddenSpaceTurnOn");
1246     } else {
1247         HiddenSpaceTurnOff();
1248         Respond("OK: HiddenSpaceTurnOff");
1249     }
1250 }
1251 
RecordStart(const ArgList & args)1252 void RSProfiler::RecordStart(const ArgList& args)
1253 {
1254     g_recordStartTime = 0.0;
1255 
1256     ImageCache::Reset();
1257     g_lastCacheImageCount = 0;
1258 
1259     if (!OpenBetaRecordFile(g_recordFile)) {
1260         g_recordFile.Create(RSFile::GetDefaultPath());
1261     }
1262 
1263     g_recordFile.AddLayer(); // add 0 layer
1264 
1265     FilterMockNode(*g_context);
1266 
1267     g_recordFile.AddHeaderFirstFrame(FirstFrameMarshalling());
1268 
1269     const std::vector<pid_t> pids = GetConnectionsPids();
1270     for (pid_t pid : pids) {
1271         g_recordFile.AddHeaderPid(pid);
1272     }
1273 
1274     SetMode(Mode::WRITE);
1275 
1276     g_recordStartTime = Now();
1277     g_frameNumber = 0;
1278 
1279     if (IsBetaRecordStarted()) {
1280         return;
1281     }
1282 
1283     std::thread thread([]() {
1284         while (IsRecording()) {
1285             if (g_recordStartTime >= 0) {
1286                 SendTelemetry(Now() - g_recordStartTime);
1287             }
1288             static constexpr int32_t GFX_METRICS_SEND_INTERVAL = 8;
1289             std::this_thread::sleep_for(std::chrono::milliseconds(GFX_METRICS_SEND_INTERVAL));
1290         }
1291     });
1292     thread.detach();
1293 
1294     Respond("Network: Record start");
1295 }
1296 
RecordStop(const ArgList & args)1297 void RSProfiler::RecordStop(const ArgList& args)
1298 {
1299     if (!IsRecording()) {
1300         return;
1301     }
1302 
1303     g_recordFile.SetWriteTime(g_recordStartTime);
1304 
1305     std::stringstream stream(std::ios::in | std::ios::out | std::ios::binary);
1306 
1307     if (!IsBetaRecordStarted()) {
1308         // DOUBLE WORK - send header of file
1309         const char headerType = 0;
1310         stream.write(reinterpret_cast<const char*>(&headerType), sizeof(headerType));
1311         stream.write(reinterpret_cast<const char*>(&g_recordStartTime), sizeof(g_recordStartTime));
1312 
1313         const uint32_t pidCount = g_recordFile.GetHeaderPids().size();
1314         stream.write(reinterpret_cast<const char*>(&pidCount), sizeof(pidCount));
1315         for (auto item : g_recordFile.GetHeaderPids()) {
1316             stream.write(reinterpret_cast<const char*>(&item), sizeof(item));
1317         }
1318 
1319         uint32_t sizeFirstFrame = static_cast<uint32_t>(g_recordFile.GetHeaderFirstFrame().size());
1320         stream.write(reinterpret_cast<const char*>(&sizeFirstFrame), sizeof(sizeFirstFrame));
1321         stream.write(reinterpret_cast<const char*>(&g_recordFile.GetHeaderFirstFrame()[0]), sizeFirstFrame);
1322 
1323         ImageCache::Serialize(stream);
1324         Network::SendBinary(stream.str().data(), stream.str().size());
1325     }
1326     SaveBetaRecordFile(g_recordFile);
1327     g_recordFile.Close();
1328     g_recordStartTime = 0.0;
1329 
1330     ImageCache::Reset();
1331     g_lastCacheImageCount = 0;
1332 
1333     Respond("Network: Record stop (" + std::to_string(stream.str().size()) + ")");
1334 }
1335 
PlaybackPrepareFirstFrame(const ArgList & args)1336 void RSProfiler::PlaybackPrepareFirstFrame(const ArgList& args)
1337 {
1338     g_playbackPid = args.Pid();
1339     g_playbackStartTime = 0.0;
1340     g_playbackPauseTime = args.Fp64(1);
1341     std::string path = args.String(2);
1342     if (!Utils::FileExists(path)) {
1343         Respond("Can't playback non existing file '" + path + "'");
1344         path = RSFile::GetDefaultPath();
1345     }
1346 
1347     ImageCache::Reset();
1348 
1349     Respond("Opening file " + path);
1350     g_playbackFile.Open(path);
1351     if (!g_playbackFile.IsOpen()) {
1352         Respond("Can't open file.");
1353         return;
1354     }
1355     std::string dataFirstFrame = g_playbackFile.GetHeaderFirstFrame();
1356 
1357     // get first frame data
1358     FirstFrameUnmarshalling(dataFirstFrame, g_playbackFile.GetVersion());
1359     // The number of frames loaded before command processing
1360     constexpr int defaultWaitFrames = 5;
1361     g_playbackWaitFrames = defaultWaitFrames;
1362     Respond("awake_frame " + std::to_string(g_playbackWaitFrames));
1363     AwakeRenderServiceThread();
1364 }
1365 
PlaybackStart(const ArgList & args)1366 void RSProfiler::PlaybackStart(const ArgList& args)
1367 {
1368     HiddenSpaceTurnOn();
1369 
1370     for (size_t pid : g_playbackFile.GetHeaderPids()) {
1371         CreateMockConnection(Utils::GetMockPid(pid));
1372     }
1373 
1374     g_playbackStartTime = Now();
1375 
1376     const double pauseTime = g_playbackPauseTime;
1377     if (pauseTime > 0.0) {
1378         const uint64_t currentTime = RawNowNano();
1379         const uint64_t pauseTimeStart = currentTime + Utils::ToNanoseconds(pauseTime);
1380         TimePauseAt(currentTime, pauseTimeStart);
1381     }
1382 
1383     AwakeRenderServiceThread();
1384 
1385     g_playbackShouldBeTerminated = false;
1386 
1387     const auto timeoutLimit = args.Int64();
1388     std::thread thread([timeoutLimit]() {
1389         while (IsPlaying()) {
1390             const int64_t timestamp = static_cast<int64_t>(RawNowNano());
1391 
1392             PlaybackUpdate();
1393             if (g_playbackStartTime >= 0) {
1394                 SendTelemetry(Now() - g_playbackStartTime);
1395             }
1396 
1397             const int64_t timeout = timeoutLimit - static_cast<int64_t>(RawNowNano()) + timestamp;
1398             if (timeout > 0) {
1399                 std::this_thread::sleep_for(std::chrono::nanoseconds(timeout));
1400             }
1401         }
1402     });
1403     thread.detach();
1404 
1405     Respond("Playback start");
1406 }
1407 
PlaybackStop(const ArgList & args)1408 void RSProfiler::PlaybackStop(const ArgList& args)
1409 {
1410     if (g_childOfDisplayNodes.empty()) {
1411         return;
1412     }
1413     HiddenSpaceTurnOff();
1414     FilterMockNode(*g_context);
1415     g_playbackShouldBeTerminated = true;
1416 
1417     Respond("Playback stop");
1418 }
1419 
PlaybackUpdate()1420 void RSProfiler::PlaybackUpdate()
1421 {
1422     if (!IsPlaying()) {
1423         return;
1424     }
1425 
1426     const double deltaTime = Now() - g_playbackStartTime;
1427 
1428     std::vector<uint8_t> data;
1429     double readTime = 0.0;
1430     if (!g_playbackShouldBeTerminated && g_playbackFile.ReadRSData(deltaTime, data, readTime)) {
1431         std::stringstream stream(std::ios::in | std::ios::out | std::ios::binary);
1432         stream.write(reinterpret_cast<const char*>(data.data()), data.size());
1433         stream.seekg(0);
1434 
1435         pid_t pid = 0;
1436         stream.read(reinterpret_cast<char*>(&pid), sizeof(pid));
1437 
1438         RSRenderServiceConnection* connection = GetConnection(Utils::GetMockPid(pid));
1439         if (!connection) {
1440             const std::vector<pid_t>& pids = g_playbackFile.GetHeaderPids();
1441             if (!pids.empty()) {
1442                 connection = GetConnection(Utils::GetMockPid(pids[0]));
1443             }
1444         }
1445 
1446         if (connection) {
1447             uint32_t code = 0;
1448             stream.read(reinterpret_cast<char*>(&code), sizeof(code));
1449 
1450             size_t dataSize = 0;
1451             stream.read(reinterpret_cast<char*>(&dataSize), sizeof(dataSize));
1452 
1453             auto* data = new uint8_t[dataSize];
1454             stream.read(reinterpret_cast<char*>(data), dataSize);
1455 
1456             int32_t flags = 0;
1457             stream.read(reinterpret_cast<char*>(&flags), sizeof(flags));
1458 
1459             int32_t waitTime = 0;
1460             stream.read(reinterpret_cast<char*>(&waitTime), sizeof(waitTime));
1461 
1462             AlignedMessageParcel parcel;
1463             parcel.parcel.SetMaxCapacity(dataSize + 1);
1464             parcel.parcel.WriteBuffer(data, dataSize);
1465 
1466             delete[] data;
1467 
1468             MessageOption option;
1469             option.SetFlags(flags);
1470             option.SetWaitTime(waitTime);
1471 
1472             MessageParcel reply;
1473             connection->OnRemoteRequest(code, parcel.parcel, reply, option);
1474         }
1475     }
1476 
1477     if (g_playbackShouldBeTerminated || g_playbackFile.RSDataEOF()) {
1478         g_playbackStartTime = 0.0;
1479         g_playbackFile.Close();
1480         g_playbackPid = 0;
1481         TimePauseClear();
1482         g_playbackShouldBeTerminated = false;
1483     }
1484 }
1485 
PlaybackPrepare(const ArgList & args)1486 void RSProfiler::PlaybackPrepare(const ArgList& args)
1487 {
1488     const pid_t pid = args.Pid();
1489     if (!g_context || (pid == 0)) {
1490         return;
1491     }
1492 
1493     FilterForPlayback(*g_context, pid);
1494     AwakeRenderServiceThread();
1495     Respond("OK");
1496 }
1497 
PlaybackPause(const ArgList & args)1498 void RSProfiler::PlaybackPause(const ArgList& args)
1499 {
1500     if (!IsPlaying()) {
1501         return;
1502     }
1503 
1504     const uint64_t currentTime = RawNowNano();
1505     const double recordPlayTime = Now() - g_playbackStartTime;
1506     TimePauseAt(currentTime, currentTime);
1507     Respond("OK: " + std::to_string(recordPlayTime));
1508 }
1509 
PlaybackPauseAt(const ArgList & args)1510 void RSProfiler::PlaybackPauseAt(const ArgList& args)
1511 {
1512     if (!IsPlaying()) {
1513         return;
1514     }
1515 
1516     const double pauseTime = args.Fp64();
1517     const double recordPlayTime = Now() - g_playbackStartTime;
1518     if (recordPlayTime > pauseTime) {
1519         return;
1520     }
1521 
1522     const uint64_t currentTime = RawNowNano();
1523     const uint64_t pauseTimeStart = currentTime + Utils::ToNanoseconds(pauseTime - recordPlayTime);
1524 
1525     TimePauseAt(currentTime, pauseTimeStart);
1526     ResetAnimationStamp();
1527     Respond("OK");
1528 }
1529 
PlaybackPauseClear(const ArgList & args)1530 void RSProfiler::PlaybackPauseClear(const ArgList& args)
1531 {
1532     TimePauseClear();
1533     Respond("OK");
1534 }
1535 
PlaybackResume(const ArgList & args)1536 void RSProfiler::PlaybackResume(const ArgList& args)
1537 {
1538     if (!IsPlaying()) {
1539         return;
1540     }
1541 
1542     TimePauseResume(Utils::Now());
1543     ResetAnimationStamp();
1544     Respond("OK");
1545 }
1546 
GetCommand(const std::string & command)1547 RSProfiler::Command RSProfiler::GetCommand(const std::string& command)
1548 {
1549     static const std::map<std::string, Command> COMMANDS = {
1550         { "rstree_contains", DumpTree },
1551         { "rstree_fix", PatchNode },
1552         { "rstree_kill_node", KillNode },
1553         { "rstree_setparent", AttachChild },
1554         { "rstree_getroot", GetRoot },
1555         { "rstree_node_mod", DumpNodeModifiers },
1556         { "rstree_node_prop", DumpNodeProperties },
1557         { "rstree_pid", DumpSurfaces },
1558         { "rstree_kill_pid", KillPid },
1559         { "rstree_prepare_replay", PlaybackPrepare },
1560         { "rstree_save_frame", TestSaveFrame },
1561         { "rstree_load_frame", TestLoadFrame },
1562         { "rstree_switch", TestSwitch },
1563         { "rstree_dump_json", DumpTreeToJson },
1564         { "rsrecord_start", RecordStart },
1565         { "rsrecord_stop", RecordStop },
1566         { "rsrecord_replay_prepare", PlaybackPrepareFirstFrame },
1567         { "rsrecord_replay", PlaybackStart },
1568         { "rsrecord_replay_stop", PlaybackStop },
1569         { "rsrecord_pause_now", PlaybackPause },
1570         { "rsrecord_pause_at", PlaybackPauseAt },
1571         { "rsrecord_pause_resume", PlaybackResume },
1572         { "rsrecord_pause_clear", PlaybackPauseClear },
1573         { "rssurface_pid", DumpNodeSurface },
1574         { "rscon_print", DumpConnections },
1575         { "save_rdc", SaveRdc },
1576         { "save_skp", SaveSkp },
1577         { "info", GetDeviceInfo },
1578         { "freq", GetDeviceFrequency },
1579         { "fixenv", FixDeviceEnv },
1580         { "set", SetSystemParameter },
1581         { "get", GetSystemParameter },
1582         { "params", DumpSystemParameters },
1583         { "get_perf_tree", GetPerfTree },
1584         { "calc_perf_node", CalcPerfNode },
1585         { "calc_perf_node_all", CalcPerfNodeAll },
1586         { "socket_shutdown", SocketShutdown },
1587         { "version", Version },
1588         { "file_version", FileVersion },
1589     };
1590 
1591     if (command.empty()) {
1592         return nullptr;
1593     }
1594 
1595     const auto delegate = COMMANDS.find(command);
1596     return (delegate != COMMANDS.end()) ? delegate->second : nullptr;
1597 }
1598 
ProcessCommands()1599 void RSProfiler::ProcessCommands()
1600 {
1601     if (g_playbackWaitFrames > 0) {
1602         g_playbackWaitFrames--;
1603         Respond("awake_frame " + std::to_string(g_playbackWaitFrames));
1604         AwakeRenderServiceThread();
1605         return;
1606     }
1607 
1608     std::vector<std::string> commandData;
1609     if (!Network::PopCommand(commandData)) {
1610         return;
1611     }
1612 
1613     const std::string& command = commandData[0];
1614     if (const Command delegate = GetCommand(command)) {
1615         const ArgList args =
1616             (commandData.size() > 1) ? ArgList({ commandData.begin() + 1, commandData.end() }) : ArgList();
1617         delegate(args);
1618     } else if (!command.empty()) {
1619         Respond("Command has not been found: " + command);
1620     }
1621 }
1622 
GetFrameNumber()1623 uint32_t RSProfiler::GetFrameNumber()
1624 {
1625     return g_frameNumber;
1626 }
1627 
1628 } // namespace OHOS::Rosen