1 /*
2  * Copyright (c) 2021-2022 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 "rs_render_service.h"
17 
18 #include <iservice_registry.h>
19 #include <malloc.h>
20 #include <parameters.h>
21 #include <platform/common/rs_log.h>
22 #include "platform/common/rs_system_properties.h"
23 #include <string>
24 #include <system_ability_definition.h>
25 #include <unistd.h>
26 
27 #include "hgm_core.h"
28 #include "parameter.h"
29 #include "rs_main_thread.h"
30 #include "rs_profiler.h"
31 #include "rs_render_service_connection.h"
32 #include "vsync_generator.h"
33 
34 #include "common/rs_singleton.h"
35 #include "pipeline/parallel_render/rs_sub_thread_manager.h"
36 #include "pipeline/round_corner_display/rs_message_bus.h"
37 #include "pipeline/round_corner_display/rs_rcd_render_manager.h"
38 #include "pipeline/round_corner_display/rs_round_corner_display_manager.h"
39 #include "pipeline/rs_hardware_thread.h"
40 #include "pipeline/rs_surface_render_node.h"
41 #include "pipeline/rs_uni_render_judgement.h"
42 #include "system/rs_system_parameters.h"
43 
44 #include "text/font_mgr.h"
45 
46 #ifdef TP_FEATURE_ENABLE
47 #include "touch_screen/touch_screen.h"
48 #endif
49 
50 namespace OHOS {
51 namespace Rosen {
52 namespace {
53 constexpr int64_t UNI_RENDER_VSYNC_OFFSET = 5000000; // ns
54 constexpr int64_t UNI_RENDER_VSYNC_OFFSET_DELAY_MODE = -3300000; // ns
55 const std::string BOOTEVENT_RENDER_SERVICE_READY = "bootevent.renderservice.ready";
56 constexpr size_t CLIENT_DUMP_TREE_TIMEOUT = 2000; // 2000ms
57 static const int INT_INIT_VAL = 0;
58 static const int RGB_SIZE = 8;
59 static const int CREAT_NUM_ONE = 1;
60 static const int INIT_WIDTH = 480;
61 static const int INIT_HEIGHT = 800;
62 static const int INIT_EGL_VERSION = 3;
63 static EGLDisplay g_tmpDisplay = EGL_NO_DISPLAY;
64 static EGLContext g_tmpContext = EGL_NO_CONTEXT;
65 static EGLSurface g_tmpSurface = EGL_NO_SURFACE;
66 
GenerateTaskId()67 uint32_t GenerateTaskId()
68 {
69     static std::atomic<uint32_t> id;
70     return id.fetch_add(1, std::memory_order::memory_order_relaxed);
71 }
72 }
RSRenderService()73 RSRenderService::RSRenderService() {}
74 
~RSRenderService()75 RSRenderService::~RSRenderService() noexcept {}
76 
Init()77 bool RSRenderService::Init()
78 {
79     system::SetParameter(BOOTEVENT_RENDER_SERVICE_READY.c_str(), "false");
80     std::thread preLoadSysTTFThread([]() {
81         Drawing::FontMgr::CreateDefaultFontMgr();
82     });
83     preLoadSysTTFThread.detach();
84 
85     if (RSSystemParameters::GetTcacheEnabled()) {
86         // enable cache
87         mallopt(M_OHOS_CONFIG, M_TCACHE_NORMAL_MODE);
88         mallopt(M_OHOS_CONFIG, M_ENABLE_OPT_TCACHE);
89         mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_ENABLE);
90         mallopt(M_DELAYED_FREE, M_DELAYED_FREE_ENABLE);
91     }
92 
93     RSMainThread::Instance();
94     RSUniRenderJudgement::InitUniRenderConfig();
95 #ifdef TP_FEATURE_ENABLE
96     TOUCH_SCREEN->InitTouchScreen();
97 #endif
98     screenManager_ = CreateOrGetScreenManager();
99     if (RSUniRenderJudgement::GetUniRenderEnabledType() != UniRenderEnabledType::UNI_RENDER_ENABLED_FOR_ALL) {
100         // screenManager initializtion executes in RSHHardwareThread under UNI_RENDER mode
101         if (screenManager_ == nullptr || !screenManager_->Init()) {
102             RS_LOGE("RSRenderService CreateOrGetScreenManager fail.");
103             return false;
104         }
105     } else {
106         RSUniRenderThread::Instance().Start();
107         RSHardwareThread::Instance().Start();
108         RegisterRcdMsg();
109     }
110 
111     auto generator = CreateVSyncGenerator();
112 
113     // The offset needs to be set
114     int64_t offset = 0;
115     if (!HgmCore::Instance().GetLtpoEnabled()) {
116         if (RSUniRenderJudgement::GetUniRenderEnabledType() == UniRenderEnabledType::UNI_RENDER_ENABLED_FOR_ALL) {
117             offset = HgmCore::Instance().IsDelayMode() ? UNI_RENDER_VSYNC_OFFSET_DELAY_MODE : UNI_RENDER_VSYNC_OFFSET;
118         }
119         rsVSyncController_ = new VSyncController(generator, offset);
120         appVSyncController_ = new VSyncController(generator, offset);
121     } else {
122         rsVSyncController_ = new VSyncController(generator, 0);
123         appVSyncController_ = new VSyncController(generator, 0);
124         generator->SetVSyncMode(VSYNC_MODE_LTPO);
125     }
126     rsVSyncDistributor_ = new VSyncDistributor(rsVSyncController_, "rs");
127     appVSyncDistributor_ = new VSyncDistributor(appVSyncController_, "app");
128 
129     generator->SetRSDistributor(rsVSyncDistributor_);
130     generator->SetAppDistributor(appVSyncDistributor_);
131 
132     mainThread_ = RSMainThread::Instance();
133     if (mainThread_ == nullptr) {
134         return false;
135     }
136     mainThread_->rsVSyncDistributor_ = rsVSyncDistributor_;
137     mainThread_->rsVSyncController_ = rsVSyncController_;
138     mainThread_->appVSyncController_ = appVSyncController_;
139     mainThread_->vsyncGenerator_ = generator;
140     mainThread_->Init();
141     mainThread_->SetAppVSyncDistributor(appVSyncDistributor_);
142     mainThread_->PostTask([]() {
143         system::SetParameter(BOOTEVENT_RENDER_SERVICE_READY.c_str(), "true");
144         RS_LOGI("Set boot render service started true");
145         }, "BOOTEVENT_RENDER_SERVICE_READY", 0, AppExecFwk::EventQueue::Priority::VIP);
146 
147     // Wait samgr ready for up to 5 second to ensure adding service to samgr.
148     int status = WaitParameter("bootevent.samgr.ready", "true", 5);
149     if (status != 0) {
150         RS_LOGE("RSRenderService wait SAMGR error, return value [%d].", status);
151     }
152 
153     auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
154     if (samgr == nullptr) {
155         RS_LOGE("RSRenderService GetSystemAbilityManager fail.");
156         return false;
157     }
158     samgr->AddSystemAbility(RENDER_SERVICE, this);
159 
160     RS_PROFILER_INIT(this);
161 
162     return true;
163 }
164 
Run()165 void RSRenderService::Run()
166 {
167     if (!mainThread_) {
168         RS_LOGE("RSRenderService::Run failed, mainThread is nullptr");
169         return;
170     }
171     RS_LOGE("RSRenderService::Run");
172     mainThread_->Start();
173 }
174 
RegisterRcdMsg()175 void RSRenderService::RegisterRcdMsg()
176 {
177     if (RSSingleton<RoundCornerDisplayManager>::GetInstance().GetRcdEnable()) {
178         RS_LOGD("RSSubThreadManager::RegisterRcdMsg");
179         if (!isRcdServiceRegister_) {
180             auto& rcdInstance = RSSingleton<RoundCornerDisplayManager>::GetInstance();
181             auto& msgBus = RSSingleton<RsMessageBus>::GetInstance();
182             msgBus.RegisterTopic<NodeId, uint32_t, uint32_t>(
183                 TOPIC_RCD_DISPLAY_SIZE, &rcdInstance,
184                 &RoundCornerDisplayManager::UpdateDisplayParameter);
185             msgBus.RegisterTopic<NodeId, ScreenRotation>(
186                 TOPIC_RCD_DISPLAY_ROTATION, &rcdInstance,
187                 &RoundCornerDisplayManager::UpdateOrientationStatus);
188             msgBus.RegisterTopic<NodeId, int>(
189                 TOPIC_RCD_DISPLAY_NOTCH, &rcdInstance,
190                 &RoundCornerDisplayManager::UpdateNotchStatus);
191             msgBus.RegisterTopic<NodeId, bool>(
192                 TOPIC_RCD_DISPLAY_HWRESOURCE, &rcdInstance,
193                 &RoundCornerDisplayManager::UpdateHardwareResourcePrepared);
194             isRcdServiceRegister_ = true;
195             RS_LOGD("RSSubThreadManager::RegisterRcdMsg Registed rcd renderservice end");
196             return;
197         }
198         RS_LOGD("RSSubThreadManager::RegisterRcdMsg Registed rcd renderservice already.");
199     }
200 }
201 
CreateConnection(const sptr<RSIConnectionToken> & token)202 sptr<RSIRenderServiceConnection> RSRenderService::CreateConnection(const sptr<RSIConnectionToken>& token)
203 {
204     if (!mainThread_ || !token) {
205         RS_LOGE("RSRenderService::CreateConnection failed, mainThread or token is nullptr");
206         return nullptr;
207     }
208     pid_t remotePid = GetCallingPid();
209     RS_PROFILER_ON_CREATE_CONNECTION(remotePid);
210 
211     auto tokenObj = token->AsObject();
212     sptr<RSIRenderServiceConnection> newConn(
213         new RSRenderServiceConnection(remotePid, this, mainThread_, screenManager_, tokenObj, appVSyncDistributor_));
214 
215     sptr<RSIRenderServiceConnection> tmp;
216     std::unique_lock<std::mutex> lock(mutex_);
217     // if connections_ has the same token one, replace it.
218     auto it = connections_.find(tokenObj);
219     if (it != connections_.end()) {
220         tmp = it->second;
221     }
222     connections_[tokenObj] = newConn;
223     lock.unlock();
224     mainThread_->AddTransactionDataPidInfo(remotePid);
225     return newConn;
226 }
227 
RemoveConnection(sptr<IRemoteObject> token)228 void RSRenderService::RemoveConnection(sptr<IRemoteObject> token)
229 {
230     std::unique_lock<std::mutex> lock(mutex_);
231     if (connections_.count(token) == 0) {
232         return;
233     }
234 
235     auto tmp = connections_.at(token);
236     connections_.erase(token);
237     lock.unlock();
238 }
239 
Dump(int fd,const std::vector<std::u16string> & args)240 int RSRenderService::Dump(int fd, const std::vector<std::u16string>& args)
241 {
242     std::unordered_set<std::u16string> argSets;
243     for (decltype(args.size()) index = 0; index < args.size(); ++index) {
244         argSets.insert(args[index]);
245     }
246     if (screenManager_ == nullptr) {
247         return OHOS::INVALID_OPERATION;
248     }
249     std::string dumpString;
250     DoDump(argSets, dumpString);
251     if (dumpString.size() == 0) {
252         return OHOS::INVALID_OPERATION;
253     }
254     if (write(fd, dumpString.c_str(), dumpString.size()) < 0) {
255         RS_LOGE("RSRenderService::DumpNodesNotOnTheTree write failed");
256         return UNKNOWN_ERROR;
257     }
258     return OHOS::NO_ERROR;
259 }
260 
DumpNodesNotOnTheTree(std::string & dumpString) const261 void RSRenderService::DumpNodesNotOnTheTree(std::string& dumpString) const
262 {
263     dumpString.append("\n");
264     dumpString.append("-- Node Not On Tree\n");
265 
266     const auto& nodeMap = mainThread_->GetContext().GetNodeMap();
267     nodeMap.TraversalNodes([&dumpString](const std::shared_ptr<RSBaseRenderNode>& node) {
268         if (node == nullptr) {
269             return;
270         }
271 
272         if (node->IsInstanceOf<RSSurfaceRenderNode>() && !node->IsOnTheTree()) {
273             const auto& surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node);
274             dumpString += "\n node Id[" + std::to_string(node->GetId()) + "]:\n";
275             const auto& surfaceConsumer = surfaceNode->GetRSSurfaceHandler()->GetConsumer();
276             if (surfaceConsumer == nullptr) {
277                 return;
278             }
279             surfaceConsumer->Dump(dumpString);
280         }
281     });
282 }
283 
DumpAllNodesMemSize(std::string & dumpString) const284 void RSRenderService::DumpAllNodesMemSize(std::string& dumpString) const
285 {
286     dumpString.append("\n");
287     dumpString.append("-- All Surfaces Memory Size\n");
288     dumpString.append("the memory size of all surfaces buffer is : dumpend");
289 
290     const auto& nodeMap = mainThread_->GetContext().GetNodeMap();
291     nodeMap.TraversalNodes([&dumpString](const std::shared_ptr<RSBaseRenderNode>& node) {
292         if (node == nullptr || !node->IsInstanceOf<RSSurfaceRenderNode>()) {
293             return;
294         }
295 
296         const auto& surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node);
297         const auto& surfaceConsumer = surfaceNode->GetRSSurfaceHandler()->GetConsumer();
298         if (surfaceConsumer == nullptr) {
299             return;
300         }
301 
302         surfaceConsumer->Dump(dumpString);
303     });
304 }
305 
DumpHelpInfo(std::string & dumpString) const306 void RSRenderService::DumpHelpInfo(std::string& dumpString) const
307 {
308     dumpString.append("------Graphic2D--RenderSerice ------\n")
309         .append("Usage:\n")
310         .append(" h                             ")
311         .append("|help text for the tool\n")
312         .append("screen                         ")
313         .append("|dump all screen infomation in the system\n")
314         .append("surface                        ")
315         .append("|dump all surface information\n")
316         .append("composer fps                   ")
317         .append("|dump the fps info of composer\n")
318         .append("[surface name] fps             ")
319         .append("|dump the fps info of surface\n")
320         .append("composer fpsClear              ")
321         .append("|clear the fps info of composer\n")
322         .append("[windowname] fps               ")
323         .append("|dump the fps info of window\n")
324         .append("[windowname] hitchs            ")
325         .append("|dump the hitchs info of window\n")
326         .append("[surface name] fpsClear        ")
327         .append("|clear the fps info of surface\n")
328         .append("nodeNotOnTree                  ")
329         .append("|dump nodeNotOnTree info\n")
330         .append("allSurfacesMem                 ")
331         .append("|dump surface mem info\n")
332         .append("RSTree                         ")
333         .append("|dump RSTree info\n")
334         .append("EventParamList                 ")
335         .append("|dump EventParamList info\n")
336         .append("allInfo                        ")
337         .append("|dump all info\n")
338         .append("client                         ")
339         .append("|dump client ui node trees\n")
340         .append("dumpMem                        ")
341         .append("|dump Cache\n")
342         .append("trimMem cpu/gpu/shader         ")
343         .append("|release Cache\n")
344         .append("surfacenode [id]               ")
345         .append("|dump node info\n")
346         .append("fpsCount                       ")
347         .append("|dump the refresh rate counts info\n")
348         .append("clearFpsCount                  ")
349         .append("|clear the refresh rate counts info\n")
350 #ifdef RS_ENABLE_VK
351         .append("vktextureLimit                 ")
352         .append("|dump vk texture limit info\n")
353 #endif
354         .append("flushJankStatsRs")
355         .append("|flush rs jank stats hisysevent\n")
356         .append("gles                           ")
357         .append("|inquire gpu info\n");
358 }
359 
FPSDUMPProcess(std::unordered_set<std::u16string> & argSets,std::string & dumpString,const std::u16string & arg) const360 void RSRenderService::FPSDUMPProcess(std::unordered_set<std::u16string>& argSets,
361     std::string& dumpString, const std::u16string& arg) const
362 {
363     auto iter = argSets.find(arg);
364     if (iter != argSets.end()) {
365         std::string layerArg;
366         argSets.erase(iter);
367         if (!argSets.empty()) {
368             layerArg = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> {}.to_bytes(*argSets.begin());
369         }
370         auto renderType = RSUniRenderJudgement::GetUniRenderEnabledType();
371         if (renderType == UniRenderEnabledType::UNI_RENDER_ENABLED_FOR_ALL) {
372             RSHardwareThread::Instance().ScheduleTask(
373                 [this, &dumpString, &layerArg]() { return screenManager_->FpsDump(dumpString, layerArg); }).wait();
374         } else {
375             mainThread_->ScheduleTask(
376                 [this, &dumpString, &layerArg]() { return screenManager_->FpsDump(dumpString, layerArg); }).wait();
377         }
378     }
379 }
380 
FPSDUMPClearProcess(std::unordered_set<std::u16string> & argSets,std::string & dumpString,const std::u16string & arg) const381 void RSRenderService::FPSDUMPClearProcess(std::unordered_set<std::u16string>& argSets,
382     std::string& dumpString, const std::u16string& arg) const
383 {
384     auto iter = argSets.find(arg);
385     if (iter != argSets.end()) {
386         std::string layerArg;
387         argSets.erase(iter);
388         if (!argSets.empty()) {
389             layerArg = std::wstring_convert<
390             std::codecvt_utf8_utf16<char16_t>, char16_t> {}.to_bytes(*argSets.begin());
391         }
392         auto renderType = RSUniRenderJudgement::GetUniRenderEnabledType();
393         if (renderType == UniRenderEnabledType::UNI_RENDER_ENABLED_FOR_ALL) {
394             RSHardwareThread::Instance().ScheduleTask(
395                 [this, &dumpString, &layerArg]() {
396                     return screenManager_->ClearFpsDump(dumpString, layerArg);
397                 }).wait();
398         } else {
399             mainThread_->ScheduleTask(
400                 [this, &dumpString, &layerArg]() {
401                     return screenManager_->ClearFpsDump(dumpString, layerArg);
402                 }).wait();
403         }
404     }
405 }
406 
DumpRSEvenParam(std::string & dumpString) const407 void RSRenderService::DumpRSEvenParam(std::string& dumpString) const
408 {
409     dumpString.append("\n");
410     dumpString.append("-- EventParamListDump: \n");
411     mainThread_->RsEventParamDump(dumpString);
412 }
413 
DumpRenderServiceTree(std::string & dumpString,bool forceDumpSingleFrame) const414 void RSRenderService::DumpRenderServiceTree(std::string& dumpString, bool forceDumpSingleFrame) const
415 {
416     dumpString.append("\n");
417     dumpString.append("-- RenderServiceTreeDump: \n");
418     mainThread_->RenderServiceTreeDump(dumpString, forceDumpSingleFrame);
419 }
420 
DumpRefreshRateCounts(std::string & dumpString) const421 void RSRenderService::DumpRefreshRateCounts(std::string& dumpString) const
422 {
423     dumpString.append("\n");
424     dumpString.append("-- RefreshRateCounts: \n");
425     RSHardwareThread::Instance().RefreshRateCounts(dumpString);
426 }
427 
DumpClearRefreshRateCounts(std::string & dumpString) const428 void RSRenderService::DumpClearRefreshRateCounts(std::string& dumpString) const
429 {
430     dumpString.append("\n");
431     dumpString.append("-- ClearRefreshRateCounts: \n");
432     RSHardwareThread::Instance().ClearRefreshRateCounts(dumpString);
433 }
434 
WindowHitchsDump(std::unordered_set<std::u16string> & argSets,std::string & dumpString,const std::u16string & arg) const435 void RSRenderService::WindowHitchsDump(
436     std::unordered_set<std::u16string>& argSets, std::string& dumpString, const std::u16string& arg) const
437 {
438     auto iter = argSets.find(arg);
439     if (iter != argSets.end()) {
440         std::string layerArg;
441         argSets.erase(iter);
442         if (!argSets.empty()) {
443             layerArg = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> {}.to_bytes(*argSets.begin());
444         }
445         auto renderType = RSUniRenderJudgement::GetUniRenderEnabledType();
446         if (renderType == UniRenderEnabledType::UNI_RENDER_ENABLED_FOR_ALL) {
447             RSHardwareThread::Instance().ScheduleTask(
448                 [this, &dumpString, &layerArg]() { return screenManager_->HitchsDump(dumpString, layerArg); }).wait();
449         } else {
450             mainThread_->ScheduleTask(
451                 [this, &dumpString, &layerArg]() { return screenManager_->HitchsDump(dumpString, layerArg); }).wait();
452         }
453     }
454 }
455 
DumpSurfaceNode(std::string & dumpString,NodeId id) const456 void RSRenderService::DumpSurfaceNode(std::string& dumpString, NodeId id) const
457 {
458     dumpString.append("\n");
459     dumpString.append("-- SurfaceNode\n");
460 
461     const auto& nodeMap = mainThread_->GetContext().GetNodeMap();
462     auto node = nodeMap.GetRenderNode<RSSurfaceRenderNode>(id);
463     if (node == nullptr) {
464         dumpString +=  std::to_string(id) + " is invalid ID\n";
465         return;
466     }
467     dumpString += "ID: " + std::to_string(node->GetId()) + "\n";
468     dumpString += "Name: " + node->GetName() + "\n";
469     dumpString += "SrcRect: [" + std::to_string(node->GetSrcRect().left_) + "," +
470         std::to_string(node->GetSrcRect().top_) + "," +
471         std::to_string(node->GetSrcRect().width_) + "," +
472         std::to_string(node->GetSrcRect().height_) + "]\n";
473     dumpString += "DstRect: [" + std::to_string(node->GetDstRect().left_) + "," +
474         std::to_string(node->GetDstRect().top_) + "," +
475         std::to_string(node->GetDstRect().width_) + "," +
476         std::to_string(node->GetDstRect().height_) + "]\n";
477     dumpString += "CornerRadius: [" + std::to_string(node->GetRenderProperties().GetCornerRadius().x_) + "," +
478         std::to_string(node->GetRenderProperties().GetCornerRadius().y_) + "," +
479         std::to_string(node->GetRenderProperties().GetCornerRadius().z_) + "," +
480         std::to_string(node->GetRenderProperties().GetCornerRadius().w_) + "]\n";
481     dumpString += "Bounds: [" + std::to_string(node->GetRenderProperties().GetBoundsWidth()) + "," +
482         std::to_string(node->GetRenderProperties().GetBoundsHeight()) + "]\n";
483     if (auto& contextClipRegion = node->contextClipRect_) {
484         dumpString += "ContextClipRegion: [" + std::to_string(contextClipRegion->GetWidth()) + "," +
485                       std::to_string(contextClipRegion->GetHeight()) + "]\n";
486     } else {
487         dumpString += "ContextClipRegion: [ empty ]\n";
488     }
489     dumpString += "Zorder: " + std::to_string(node->GetRenderProperties().GetPositionZ()) + "\n";
490     dumpString += "IsOnTheTree: " + std::to_string(node->IsOnTheTree()) + "\n";
491     dumpString += "Visible: " + std::to_string(node->GetRenderProperties().GetVisible()) + "\n";
492     dumpString += "OcclusionBg: " + std::to_string(node->GetAbilityBgAlpha())+ "\n";
493     dumpString += "Alpha: " + std::to_string(node->GetRenderProperties().GetAlpha()) +
494                   "(include ContextAlpha: " + std::to_string(node->contextAlpha_) + ")\n";
495     dumpString += "GlobalAlpha: " + std::to_string(node->GetGlobalAlpha()) + "\n";
496     dumpString += node->GetVisibleRegion().GetRegionInfo() + "\n";
497     const auto consumer = node->GetRSSurfaceHandler()->GetConsumer();
498     if (consumer == nullptr) {
499         return;
500     }
501     dumpString += "Consumer Info: \n";
502     consumer->Dump(dumpString);
503 }
504 
IsNumber(const std::string & type)505 static bool IsNumber(const std::string& type)
506 {
507     auto number = static_cast<uint32_t>(std::count_if(type.begin(), type.end(), [](unsigned char c) {
508         return std::isdigit(c);
509     }));
510     return number == type.length();
511 }
512 
DumpMem(std::unordered_set<std::u16string> & argSets,std::string & dumpString) const513 void RSRenderService::DumpMem(std::unordered_set<std::u16string>& argSets, std::string& dumpString) const
514 {
515     if (!RSUniRenderJudgement::IsUniRender()) {
516         dumpString.append("\n---------------\nNot in UniRender and no information");
517     } else {
518         std::string type;
519         if (argSets.size() > 1) {
520             argSets.erase(u"dumpMem");
521             if (!argSets.empty()) {
522                 type = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> {}.to_bytes(*argSets.begin());
523             }
524         }
525         int pid = 0;
526         if (!type.empty() && IsNumber(type)) {
527             pid = std::atoi(type.c_str());
528         }
529         mainThread_->ScheduleTask(
530             [this, &argSets, &dumpString, &type, &pid]() {
531                 return mainThread_->DumpMem(argSets, dumpString, type, pid);
532             }).wait();
533         return;
534     }
535 }
536 
DumpJankStatsRs(std::string & dumpString) const537 void RSRenderService::DumpJankStatsRs(std::string& dumpString) const
538 {
539     dumpString.append("\n");
540     RSJankStats::GetInstance().ReportJankStats();
541     dumpString.append("flush done\n");
542 }
543 
InitGLES()544 static void InitGLES()
545 {
546     g_tmpDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
547     EGLint major, minor;
548     eglInitialize(g_tmpDisplay, &major, &minor);
549     EGLint numConfigs = INT_INIT_VAL;
550     const EGLint configAttribs[] = {
551         EGL_RED_SIZE, RGB_SIZE,
552         EGL_GREEN_SIZE, RGB_SIZE,
553         EGL_BLUE_SIZE, RGB_SIZE,
554         EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
555         EGL_NONE
556     };
557     EGLConfig config;
558     eglChooseConfig(g_tmpDisplay, configAttribs, &config, CREAT_NUM_ONE, &numConfigs);
559     const EGLint surfaceAttribs[] = { EGL_WIDTH, INIT_WIDTH, EGL_HEIGHT, INIT_HEIGHT, EGL_NONE };
560     g_tmpSurface = eglCreatePbufferSurface(g_tmpDisplay, config, surfaceAttribs);
561     const EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, INIT_EGL_VERSION, EGL_NONE };
562     g_tmpContext = eglCreateContext(g_tmpDisplay, config, EGL_NO_CONTEXT, contextAttribs);
563     eglMakeCurrent(g_tmpDisplay, g_tmpSurface, g_tmpSurface, g_tmpContext);
564 }
565 
DestroyGLES()566 static void DestroyGLES()
567 {
568     eglDestroySurface(g_tmpDisplay, g_tmpSurface);
569     g_tmpSurface = EGL_NO_SURFACE;
570     eglDestroyContext(g_tmpDisplay, g_tmpContext);
571     g_tmpContext = EGL_NO_CONTEXT;
572     eglTerminate(g_tmpDisplay);
573     g_tmpDisplay = EGL_NO_DISPLAY;
574 }
575 
DumpGpuInfo(std::string & dumpString) const576 void RSRenderService::DumpGpuInfo(std::string& dumpString) const
577 {
578     InitGLES(); // This is necessary because you cannot query GPU information without initialization.
579     dumpString.append("\n");
580     dumpString.append("-- DumpGpuInfo: \n");
581     auto glVendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
582     auto glRenderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
583     auto glesVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));
584     auto glShadingLanguageVersion = reinterpret_cast<const char*>(glGetString(GL_SHADING_LANGUAGE_VERSION));
585     dumpString.append("GL_VENDOR: ");
586     dumpString.append(glVendor ? glVendor : "Unknown");
587     dumpString.append("\n");
588     dumpString.append("GL_RENDERER: ");
589     dumpString.append(glRenderer ? glRenderer : "Unknown");
590     dumpString.append("\n");
591     dumpString.append("GL_VERSION: ");
592     dumpString.append(glesVersion ? glesVersion : "Unknown");
593     dumpString.append("\n");
594     dumpString.append("GL_SHADING_LANGUAGE_VERSION: ");
595     dumpString.append(glShadingLanguageVersion ? glShadingLanguageVersion : "Unknown");
596     dumpString.append("\n");
597     DestroyGLES();
598 }
599 
600 #ifdef RS_ENABLE_VK
DumpVkTextureLimit(std::string & dumpString) const601 void RSRenderService::DumpVkTextureLimit(std::string& dumpString) const
602 {
603     dumpString.append("\n");
604     dumpString.append("-- vktextureLimit:\n");
605     auto& vkContext = OHOS::Rosen::RsVulkanContext::GetSingleton().GetRsVulkanInterface();
606     VkPhysicalDevice physicalDevice = vkContext.GetPhysicalDevice();
607     VkPhysicalDeviceProperties deviceProperties;
608     vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties);
609 
610     uint32_t maxTextureWidth = deviceProperties.limits.maxImageDimension2D;
611     uint32_t maxTextureHeight = deviceProperties.limits.maxImageDimension2D;
612     dumpString.append(
613         "width: " + std::to_string(maxTextureWidth) + " height: " + std::to_string(maxTextureHeight) + "\n");
614 }
615 #endif
616 
DoDump(std::unordered_set<std::u16string> & argSets,std::string & dumpString) const617 void RSRenderService::DoDump(std::unordered_set<std::u16string>& argSets, std::string& dumpString) const
618 {
619     if (!mainThread_ || !screenManager_) {
620         RS_LOGE("RSRenderService::DoDump failed, mainThread or screenManager is nullptr");
621         return;
622     }
623     std::u16string arg1(u"screen");
624     std::u16string arg2(u"surface");
625     std::u16string arg3(u"fps");
626     std::u16string arg4(u"nodeNotOnTree");
627     std::u16string arg5(u"allSurfacesMem");
628     std::u16string arg6(u"RSTree");
629     std::u16string arg6_1(u"MultiRSTrees");
630     std::u16string arg7(u"EventParamList");
631     std::u16string arg8(u"h");
632     std::u16string arg9(u"allInfo");
633     std::u16string arg10(u"trimMem");
634     std::u16string arg11(u"dumpMem");
635     std::u16string arg12(u"surfacenode");
636     std::u16string arg13(u"fpsClear");
637     std::u16string arg15(u"fpsCount");
638     std::u16string arg16(u"clearFpsCount");
639     std::u16string arg17(u"hitchs");
640     std::u16string arg18(u"rsLogFlag");
641     std::u16string arg19(u"flushJankStatsRs");
642     std::u16string arg20(u"client");
643 #ifdef RS_ENABLE_VK
644     std::u16string arg22(u"vktextureLimit");
645 #endif
646     std::u16string arg23(u"gles");
647     if (argSets.count(arg9) || argSets.count(arg1) != 0) {
648         auto renderType = RSUniRenderJudgement::GetUniRenderEnabledType();
649         if (renderType == UniRenderEnabledType::UNI_RENDER_ENABLED_FOR_ALL) {
650             RSHardwareThread::Instance().ScheduleTask(
651                 [this, &dumpString]() { screenManager_->DisplayDump(dumpString); }).wait();
652         } else {
653             mainThread_->ScheduleTask(
654                 [this, &dumpString]() { screenManager_->DisplayDump(dumpString); }).wait();
655         }
656     }
657     if (argSets.count(arg9) || argSets.count(arg2) != 0) {
658         mainThread_->ScheduleTask(
659             [this, &dumpString]() { return screenManager_->SurfaceDump(dumpString); }).wait();
660     }
661     if (argSets.count(arg9) || argSets.count(arg4) != 0) {
662         mainThread_->ScheduleTask(
663             [this, &dumpString]() { DumpNodesNotOnTheTree(dumpString); }).wait();
664     }
665     if (argSets.count(arg9) || argSets.count(arg5) != 0) {
666         mainThread_->ScheduleTask(
667             [this, &dumpString]() { DumpAllNodesMemSize(dumpString); }).wait();
668     }
669     if (argSets.count(arg9) || argSets.count(arg6) != 0) {
670         mainThread_->ScheduleTask(
671             [this, &dumpString]() { DumpRenderServiceTree(dumpString); }).wait();
672     }
673     if (argSets.count(arg9) || argSets.count(arg6_1) != 0) {
674         mainThread_->ScheduleTask(
675             [this, &dumpString]() {DumpRenderServiceTree(dumpString, false); }).wait();
676     }
677     if (argSets.count(arg9) ||argSets.count(arg7) != 0) {
678         mainThread_->ScheduleTask(
679             [this, &dumpString]() { DumpRSEvenParam(dumpString); }).wait();
680     }
681     if (argSets.count(arg10)) {
682         mainThread_->ScheduleTask(
683             [this, &argSets, &dumpString]() { return mainThread_->TrimMem(argSets, dumpString); }).wait();
684     }
685     if (argSets.count(arg11)) {
686         DumpMem(argSets, dumpString);
687     }
688     if (auto iter = argSets.find(arg12) != argSets.end()) {
689         argSets.erase(arg12);
690         if (!argSets.empty()) {
691             NodeId id = static_cast<NodeId>(std::atoll(std::wstring_convert<
692                 std::codecvt_utf8_utf16<char16_t>, char16_t>{}.to_bytes(*argSets.begin()).c_str()));
693             mainThread_->ScheduleTask(
694                 [this, &dumpString, &id]() { return DumpSurfaceNode(dumpString, id); }).wait();
695         }
696     }
697     FPSDUMPProcess(argSets, dumpString, arg3);
698     FPSDUMPClearProcess(argSets, dumpString, arg13);
699     WindowHitchsDump(argSets, dumpString, arg17);
700     if (auto iter = argSets.find(arg18) != argSets.end()) {
701         argSets.erase(arg18);
702         if (!argSets.empty()) {
703             std::string logFlag = std::wstring_convert<
704                 std::codecvt_utf8_utf16<char16_t>, char16_t>{}.to_bytes(*argSets.begin());
705             if (RSLogManager::GetInstance().SetRSLogFlag(logFlag)) {
706                 dumpString.append("Successed to set flag: " + logFlag + "\n");
707             } else {
708                 dumpString.append("Failed to set flag: " + logFlag + "\n");
709             }
710         }
711     }
712     if (argSets.size() == 0 || argSets.count(arg8) != 0 || dumpString.empty()) {
713         mainThread_->ScheduleTask(
714             [this, &dumpString]() { DumpHelpInfo(dumpString); }).wait();
715     }
716     if (argSets.count(arg9) || argSets.count(arg15) != 0) {
717         mainThread_->ScheduleTask(
718             [this, &dumpString]() { DumpRefreshRateCounts(dumpString); }).wait();
719     }
720     if (argSets.count(arg16) != 0) {
721         mainThread_->ScheduleTask(
722             [this, &dumpString]() { DumpClearRefreshRateCounts(dumpString); }).wait();
723     }
724     if (argSets.count(arg19) != 0) {
725         mainThread_->ScheduleTask(
726             [this, &dumpString]() { DumpJankStatsRs(dumpString); }).wait();
727     }
728     if (argSets.count(arg9) || argSets.count(arg20)) {
729         auto taskId = GenerateTaskId();
730         mainThread_->ScheduleTask(
731             [this, taskId]() {
732                 mainThread_->SendClientDumpNodeTreeCommands(taskId);
733             }).wait();
734         mainThread_->CollectClientNodeTreeResult(taskId, dumpString, CLIENT_DUMP_TREE_TIMEOUT);
735     }
736     if (argSets.count(arg23) != 0) {
737         mainThread_->ScheduleTask([this, &dumpString]() { DumpGpuInfo(dumpString); }).wait();
738     }
739 #ifdef RS_ENABLE_VK
740     if (argSets.count(arg22) != 0) {
741         mainThread_->ScheduleTask(
742             [this, &dumpString]() { DumpVkTextureLimit(dumpString); }).wait();
743     }
744 #endif
745 }
746 } // namespace Rosen
747 } // namespace OHOS
748