• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "hiview_service.h"
17 
18 #include <cinttypes>
19 #include <cstdio>
20 #include <fcntl.h>
21 #include <sys/sendfile.h>
22 #include <sys/stat.h>
23 
24 #include "bundle_mgr_client.h"
25 #include "collect_event.h"
26 #include "file_util.h"
27 #include "hiview_logger.h"
28 #include "hiview_platform.h"
29 #include "hiview_service_adapter.h"
30 #include "sys_event.h"
31 #include "string_util.h"
32 #include "time_util.h"
33 #ifdef UNIFIED_COLLECTOR_TRACE_ENABLE
34 #include "trace_state_machine.h"
35 #include "trace_strategy.h"
36 #endif
37 namespace OHOS {
38 namespace HiviewDFX {
39 using namespace UCollect;
40 DEFINE_LOG_TAG("HiView-Service");
41 namespace {
42 constexpr int MIN_SUPPORT_CMD_SIZE = 1;
43 constexpr int32_t ERR_DEFAULT = -1;
44 }
45 
HiviewService()46 HiviewService::HiviewService()
47 {
48     cpuCollector_ = UCollectUtil::CpuCollector::Create();
49     graphicMemoryCollector_ = UCollectUtil::GraphicMemoryCollector::Create();
50 }
51 
StartService()52 void HiviewService::StartService()
53 {
54     std::unique_ptr<HiviewServiceAdapter> adapter = std::make_unique<HiviewServiceAdapter>();
55     adapter->StartService(this);
56 }
57 
DumpRequestDispatcher(int fd,const std::vector<std::string> & cmds)58 void HiviewService::DumpRequestDispatcher(int fd, const std::vector<std::string> &cmds)
59 {
60     if (fd < 0) {
61         HIVIEW_LOGW("invalid fd.");
62         return;
63     }
64 
65     if (cmds.size() == 0) {
66         DumpLoadedPluginInfo(fd);
67         return;
68     }
69 
70     // hidumper hiviewdfx -d
71     if ((cmds.size() == MIN_SUPPORT_CMD_SIZE) && (cmds[0] == "-d")) {
72         DumpDetailedInfo(fd);
73         return;
74     }
75 
76     // hidumper hiviewdfx -p
77     if ((cmds.size() >= MIN_SUPPORT_CMD_SIZE) && (cmds[0] == "-p")) {
78         DumpPluginInfo(fd, cmds);
79         return;
80     }
81 
82     PrintUsage(fd);
83     return;
84 }
85 
DumpPluginInfo(int fd,const std::vector<std::string> & cmds) const86 void HiviewService::DumpPluginInfo(int fd, const std::vector<std::string> &cmds) const
87 {
88     std::string pluginName = "";
89     const int pluginNameSize = 2;
90     const int pluginNamePos = 1;
91     std::vector<std::string> newCmd;
92     if (cmds.size() >= pluginNameSize) {
93         pluginName = cmds[pluginNamePos];
94         newCmd.insert(newCmd.begin(), cmds.begin() + pluginNamePos, cmds.end());
95     }
96 
97     auto &platform = HiviewPlatform::GetInstance();
98     auto const &curPluginMap = platform.GetPluginMap();
99     for (auto const &entry : curPluginMap) {
100         auto const &pluginPtr = entry.second;
101         if (pluginPtr == nullptr) {
102             continue;
103         }
104 
105         if (pluginName.empty()) {
106             pluginPtr->Dump(fd, newCmd);
107             continue;
108         }
109 
110         if (pluginPtr->GetName() == pluginName) {
111             pluginPtr->Dump(fd, newCmd);
112             break;
113         }
114     }
115 }
116 
DumpDetailedInfo(int fd)117 void HiviewService::DumpDetailedInfo(int fd)
118 {
119     if (parser_ != nullptr) {
120         parser_.reset();
121     }
122     DumpLoadedPluginInfo(fd);
123     parser_ = std::make_unique<AuditLogParser>();
124     parser_->StartParse();
125     std::string timeScope = parser_->GetAuditLogTimeScope();
126     dprintf(fd, "%s\n", timeScope.c_str());
127     DumpPluginUsageInfo(fd);
128     DumpThreadUsageInfo(fd);
129     DumpPipelineUsageInfo(fd);
130     parser_.reset();
131 }
132 
DumpLoadedPluginInfo(int fd) const133 void HiviewService::DumpLoadedPluginInfo(int fd) const
134 {
135     auto &platform = HiviewPlatform::GetInstance();
136     auto const &curPluginMap = platform.GetPluginMap();
137     dprintf(fd, "Current Loaded Plugins:\n");
138     for (auto const &entry : curPluginMap) {
139         auto const &pluginName = entry.first;
140         if (entry.second != nullptr) {
141             dprintf(fd, "PluginName:%s ", pluginName.c_str());
142             dprintf(fd, "IsDynamic:%s ",
143                 (entry.second->GetType() == Plugin::PluginType::DYNAMIC) ? "True" : "False");
144             dprintf(fd, "Version:%s ", (entry.second->GetVersion().c_str()));
145             dprintf(fd,
146                 "ThreadName:%s\n",
147                 ((entry.second->GetWorkLoop() == nullptr) ? "Null" : entry.second->GetWorkLoop()->GetName().c_str()));
148         }
149     }
150     dprintf(fd, "Dump Plugin Loaded Info Done.\n\n");
151 }
152 
DumpPluginUsageInfo(int fd)153 void HiviewService::DumpPluginUsageInfo(int fd)
154 {
155     auto &platform = HiviewPlatform::GetInstance();
156     auto const &curPluginMap = platform.GetPluginMap();
157     for (auto const &entry : curPluginMap) {
158         auto pluginName = entry.first;
159         if (entry.second != nullptr) {
160             DumpPluginUsageInfo(fd, pluginName);
161         }
162     }
163 }
164 
DumpPluginUsageInfo(int fd,const std::string & pluginName) const165 void HiviewService::DumpPluginUsageInfo(int fd, const std::string &pluginName) const
166 {
167     if (parser_ == nullptr) {
168         return;
169     }
170     auto logList = parser_->GetPluginSummary(pluginName);
171     dprintf(fd, "Following events processed By Plugin %s:\n", pluginName.c_str());
172     for (auto &log : logList) {
173         dprintf(fd, " %s.\n", log.c_str());
174     }
175     dprintf(fd, "Dump Plugin Usage Done.\n\n");
176 }
177 
DumpThreadUsageInfo(int fd) const178 void HiviewService::DumpThreadUsageInfo(int fd) const
179 {
180     auto &platform = HiviewPlatform::GetInstance();
181     auto const &curThreadMap = platform.GetWorkLoopMap();
182     dprintf(fd, "Start Dump ThreadInfo:\n");
183     for (auto const &entry : curThreadMap) {
184         if (entry.second != nullptr) {
185             std::string name = entry.second->GetName();
186             DumpThreadUsageInfo(fd, name);
187         }
188     }
189     dprintf(fd, "Dump ThreadInfo Done.\n\n");
190 }
191 
DumpThreadUsageInfo(int fd,const std::string & threadName) const192 void HiviewService::DumpThreadUsageInfo(int fd, const std::string &threadName) const
193 {
194     if (parser_ == nullptr) {
195         return;
196     }
197     auto logList = parser_->GetThreadSummary(threadName);
198     dprintf(fd, "Following events processed on Thread %s:\n", threadName.c_str());
199     for (auto &log : logList) {
200         dprintf(fd, " %s.\n", log.c_str());
201     }
202 }
203 
DumpPipelineUsageInfo(int fd) const204 void HiviewService::DumpPipelineUsageInfo(int fd) const
205 {
206     auto &platform = HiviewPlatform::GetInstance();
207     auto const &curPipelineMap = platform.GetPipelineMap();
208     dprintf(fd, "Start Dump Pipeline Info:\n");
209     for (auto const &entry : curPipelineMap) {
210         auto pipeline = entry.first;
211         DumpPipelineUsageInfo(fd, pipeline);
212     }
213 }
214 
DumpPipelineUsageInfo(int fd,const std::string & pipelineName) const215 void HiviewService::DumpPipelineUsageInfo(int fd, const std::string &pipelineName) const
216 {
217     if (parser_ == nullptr) {
218         return;
219     }
220     auto logList = parser_->GetPipelineSummary(pipelineName);
221     dprintf(fd, "Following events processed on Pipeline %s:\n", pipelineName.c_str());
222     for (auto &log : logList) {
223         dprintf(fd, " %s.\n", log.c_str());
224     }
225     dprintf(fd, "Dump Pipeline Usage Info Done.\n\n");
226 }
227 
PrintUsage(int fd) const228 void HiviewService::PrintUsage(int fd) const
229 {
230     dprintf(fd, "Hiview Plugin Platform dump options:\n");
231     dprintf(fd, "hidumper hiviewdfx [-d(etail)]\n");
232     dprintf(fd, "    [-p(lugin) pluginName]\n");
233 }
234 
CopyFile(const std::string & srcFilePath,const std::string & destFilePath)235 int32_t HiviewService::CopyFile(const std::string& srcFilePath, const std::string& destFilePath)
236 {
237     int srcFd = open(srcFilePath.c_str(), O_RDONLY);
238     if (srcFd == -1) {
239         HIVIEW_LOGE("failed to open source file, src=%{public}s", StringUtil::HideSnInfo(srcFilePath).c_str());
240         return ERR_DEFAULT;
241     }
242     struct stat st{};
243     if (fstat(srcFd, &st) == -1) {
244         HIVIEW_LOGE("failed to stat file.");
245         close(srcFd);
246         return ERR_DEFAULT;
247     }
248     int destFd = open(destFilePath.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IROTH);
249     if (destFd == -1) {
250         HIVIEW_LOGE("failed to open destination file, des=%{public}s", StringUtil::HideSnInfo(destFilePath).c_str());
251         close(srcFd);
252         return ERR_DEFAULT;
253     }
254     off_t offset = 0;
255     int cycleNum = 0;
256     while (offset < st.st_size) {
257         size_t count = static_cast<size_t>((st.st_size - offset) > SSIZE_MAX ? SSIZE_MAX : st.st_size - offset);
258         ssize_t ret = sendfile(destFd, srcFd, &offset, count);
259         if (cycleNum > 0) {
260             HIVIEW_LOGI("sendfile cycle num:%{public}d, ret:%{public}zd, offset:%{public}lld, size:%{public}lld",
261                 cycleNum, ret, static_cast<long long>(offset), static_cast<long long>(st.st_size));
262         }
263         cycleNum++;
264         if (ret < 0 || offset > st.st_size) {
265             HIVIEW_LOGE("sendfile fail, ret:%{public}zd, offset:%{public}lld, size:%{public}lld",
266                 ret, static_cast<long long>(offset), static_cast<long long>(st.st_size));
267             close(srcFd);
268             close(destFd);
269             return ERR_DEFAULT;
270         }
271     }
272     close(srcFd);
273     close(destFd);
274     return 0;
275 }
276 
Copy(const std::string & srcFilePath,const std::string & destFilePath)277 int32_t HiviewService::Copy(const std::string& srcFilePath, const std::string& destFilePath)
278 {
279     return CopyFile(srcFilePath, destFilePath);
280 }
281 
Move(const std::string & srcFilePath,const std::string & destFilePath)282 int32_t HiviewService::Move(const std::string& srcFilePath, const std::string& destFilePath)
283 {
284     int copyResult = CopyFile(srcFilePath, destFilePath);
285     if (copyResult != 0) {
286         HIVIEW_LOGW("copy file failed, result: %{public}d", copyResult);
287         return copyResult;
288     }
289     bool result = FileUtil::RemoveFile(srcFilePath);
290     HIVIEW_LOGI("move file, delete src result: %{public}d", result);
291     if (!result) {
292         bool destResult = FileUtil::RemoveFile(destFilePath);
293         HIVIEW_LOGI("move file, delete dest result: %{public}d", destResult);
294         return ERR_DEFAULT;
295     }
296     return 0;
297 }
298 
Remove(const std::string & filePath)299 int32_t HiviewService::Remove(const std::string& filePath)
300 {
301     bool result = FileUtil::RemoveFile(filePath);
302     HIVIEW_LOGI("remove file, result:%{public}d", result);
303     return 0;
304 }
305 
OpenSnapshotTrace(const std::vector<std::string> & tagGroups)306 CollectResult<int32_t> HiviewService::OpenSnapshotTrace(const std::vector<std::string>& tagGroups)
307 {
308 #ifndef UNIFIED_COLLECTOR_TRACE_ENABLE
309     return {UcError::FEATURE_CLOSED};
310 #else
311     TraceRet openRet = TraceStateMachine::GetInstance().OpenTrace(TraceScenario::TRACE_COMMAND, tagGroups);
312     return {GetUcError(openRet)};
313 #endif
314 }
315 
DumpSnapshotTrace(UCollect::TraceClient client)316 CollectResult<std::vector<std::string>> HiviewService::DumpSnapshotTrace(UCollect::TraceClient client)
317 {
318 #ifndef UNIFIED_COLLECTOR_TRACE_ENABLE
319     return {UcError::FEATURE_CLOSED};
320 #else
321     HIVIEW_LOGI("client:[%{public}d] dump trace in snapshot mode.", static_cast<int32_t>(client));
322     CollectResult<std::vector<std::string>> result;
323     auto traceStrategy = TraceFactory::CreateTraceStrategy(client, 0, static_cast<uint64_t>(0));
324     if (traceStrategy == nullptr) {
325         HIVIEW_LOGE("Create traceStrategy error client:%{public}d", static_cast<int32_t>(client));
326         return {UcError::UNSUPPORT};
327     }
328     TraceRet dumpRet = traceStrategy->DoDump(result.data);
329     result.retCode = GetUcError(dumpRet);
330     return result;
331 #endif
332 }
333 
OpenRecordingTrace(const std::string & tags)334 CollectResult<int32_t> HiviewService::OpenRecordingTrace(const std::string& tags)
335 {
336 #ifndef UNIFIED_COLLECTOR_TRACE_ENABLE
337     return {UcError::FEATURE_CLOSED};
338 #else
339     TraceRet openRet = TraceStateMachine::GetInstance().OpenTrace(TraceScenario::TRACE_COMMAND, tags);
340     return {GetUcError(openRet)};
341 #endif
342 }
343 
RecordingTraceOn()344 CollectResult<int32_t> HiviewService::RecordingTraceOn()
345 {
346 #ifndef UNIFIED_COLLECTOR_TRACE_ENABLE
347     return {UcError::FEATURE_CLOSED};
348 #else
349     TraceRet ret = TraceStateMachine::GetInstance().TraceDropOn(TraceScenario::TRACE_COMMAND);
350     return {GetUcError(ret)};
351 #endif
352 }
353 
RecordingTraceOff()354 CollectResult<std::vector<std::string>> HiviewService::RecordingTraceOff()
355 {
356 #ifndef UNIFIED_COLLECTOR_TRACE_ENABLE
357     return {UcError::FEATURE_CLOSED};
358 #else
359     TraceRetInfo traceRetInfo;
360     TraceRet ret = TraceStateMachine::GetInstance().TraceDropOff(TraceScenario::TRACE_COMMAND, traceRetInfo);
361     CollectResult<std::vector<std::string>> result(GetUcError(ret));
362     result.data = traceRetInfo.outputFiles;
363     return result;
364 #endif
365 }
366 
CloseTrace()367 CollectResult<int32_t> HiviewService::CloseTrace()
368 {
369 #ifndef UNIFIED_COLLECTOR_TRACE_ENABLE
370     return {UcError::FEATURE_CLOSED};
371 #else
372     TraceRet ret = TraceStateMachine::GetInstance().CloseTrace(TraceScenario::TRACE_COMMAND);
373     return {GetUcError(ret)};
374 #endif
375 }
376 
377 #ifdef UNIFIED_COLLECTOR_TRACE_ENABLE
InnerCreateAppCallerEvent(UCollectClient::AppCaller & appCaller,const std::string & eventName)378 static std::shared_ptr<AppCallerEvent> InnerCreateAppCallerEvent(UCollectClient::AppCaller &appCaller,
379     const std::string &eventName)
380 {
381     std::shared_ptr<AppCallerEvent> appCallerEvent = std::make_shared<AppCallerEvent>("HiViewService");
382     appCallerEvent->messageType_ = Event::MessageType::PLUGIN_MAINTENANCE;
383     appCallerEvent->eventName_ = eventName;
384     appCallerEvent->isBusinessJank_ = appCaller.isBusinessJank;
385     appCallerEvent->bundleName_ = appCaller.bundleName;
386     appCallerEvent->bundleVersion_ = appCaller.bundleVersion;
387     appCallerEvent->uid_ = appCaller.uid;
388     appCallerEvent->pid_ = appCaller.pid;
389     appCallerEvent->happenTime_ = static_cast<uint64_t>(appCaller.happenTime);
390     appCallerEvent->beginTime_ = appCaller.beginTime;
391     appCallerEvent->endTime_ = appCaller.endTime;
392     appCallerEvent->taskBeginTime_ = static_cast<int64_t>(TimeUtil::GetMilliseconds());
393     appCallerEvent->taskEndTime_ = appCallerEvent->taskBeginTime_;
394     appCallerEvent->resultCode_ = UCollect::UcError::SUCCESS;
395     appCallerEvent->foreground_ = appCaller.foreground;
396     appCallerEvent->threadName_ = appCaller.threadName;
397     return appCallerEvent;
398 }
399 
InnerHasCallAppTrace(std::shared_ptr<AppCallerEvent> appCallerEvent)400 bool HiviewService::InnerHasCallAppTrace(std::shared_ptr<AppCallerEvent> appCallerEvent)
401 {
402     return TraceFlowController(ClientName::APP).HasCallOnceToday(appCallerEvent->uid_, appCallerEvent->happenTime_);
403 }
404 
InnerResponseStartAppTrace(UCollectClient::AppCaller & appCaller)405 CollectResult<int32_t> HiviewService::InnerResponseStartAppTrace(UCollectClient::AppCaller &appCaller)
406 {
407     auto appCallerEvent = InnerCreateAppCallerEvent(appCaller, UCollectUtil::START_APP_TRACE);
408     if (InnerHasCallAppTrace(appCallerEvent)) {
409         HIVIEW_LOGW("deny: already capture trace uid=%{public}d pid=%{public}d",
410                     appCallerEvent->uid_, appCallerEvent->pid_);
411         return {UCollect::UcError::HAD_CAPTURED_TRACE};
412     }
413     TraceRet ret = TraceStateMachine::GetInstance().OpenDynamicTrace(appCallerEvent->pid_);
414     if (!ret.IsSuccess()) {
415         return {GetUcError(ret)};
416     }
417     if (!HiviewPlatform::GetInstance().PostSyncEventToTarget(nullptr, UCollectUtil::UCOLLECTOR_PLUGIN,
418         appCallerEvent)) {
419         HIVIEW_LOGE("post event failed");
420         return {UCollect::UcError::SYSTEM_ERROR};
421     }
422     return {UCollect::UcError::SUCCESS};
423 }
424 
InnerResponseDumpAppTrace(UCollectClient::AppCaller & appCaller)425 CollectResult<int32_t> HiviewService::InnerResponseDumpAppTrace(UCollectClient::AppCaller &appCaller)
426 {
427     CollectResult<std::vector<std::string>> result;
428     auto strategy = TraceFactory::CreateAppStrategy(InnerCreateAppCallerEvent(appCaller, UCollectUtil::DUMP_APP_TRACE));
429     return {GetUcError(strategy->DoDump(result.data))};
430 }
431 #endif
432 
CaptureDurationTrace(UCollectClient::AppCaller & appCaller)433 CollectResult<int32_t> HiviewService::CaptureDurationTrace(UCollectClient::AppCaller &appCaller)
434 {
435 #ifndef UNIFIED_COLLECTOR_TRACE_ENABLE
436     return {UcError::FEATURE_CLOSED};
437 #else
438     if (appCaller.actionId == UCollectClient::ACTION_ID_START_TRACE) {
439         return InnerResponseStartAppTrace(appCaller);
440     } else if (appCaller.actionId == UCollectClient::ACTION_ID_DUMP_TRACE) {
441         return InnerResponseDumpAppTrace(appCaller);
442     } else {
443         HIVIEW_LOGE("invalid param %{public}d, can not capture trace for uid=%{public}d, pid=%{public}d",
444             appCaller.actionId, appCaller.uid, appCaller.pid);
445         return {UCollect::UcError::INVALID_ACTION_ID};
446     }
447 #endif
448 }
449 
450 
GetSysCpuUsage()451 CollectResult<double> HiviewService::GetSysCpuUsage()
452 {
453     CollectResult<double> cpuUsageRet = cpuCollector_->GetSysCpuUsage();
454     if (cpuUsageRet.retCode != UCollect::UcError::SUCCESS) {
455         HIVIEW_LOGE("failed to collect system cpu usage");
456     }
457     return cpuUsageRet;
458 }
459 
SetAppResourceLimit(UCollectClient::MemoryCaller & memoryCaller)460 CollectResult<int32_t> HiviewService::SetAppResourceLimit(UCollectClient::MemoryCaller& memoryCaller)
461 {
462     std::string eventName = "APP_RESOURCE_LIMIT";
463     SysEventCreator sysEventCreator("HIVIEWDFX", eventName, SysEventCreator::FAULT);
464     sysEventCreator.SetKeyValue("PID", memoryCaller.pid);
465     sysEventCreator.SetKeyValue("RESOURCE_TYPE", memoryCaller.resourceType);
466     sysEventCreator.SetKeyValue("RESOURCE_LIMIT", memoryCaller.limitValue);
467     sysEventCreator.SetKeyValue("RESOURCE_DEBUG_ENABLE", memoryCaller.enabledDebugLog ? "true" : "false");
468     auto sysEvent = std::make_shared<SysEvent>(eventName, nullptr, sysEventCreator);
469     std::shared_ptr<Event> event = std::dynamic_pointer_cast<Event>(sysEvent);
470     if (!HiviewPlatform::GetInstance().PostSyncEventToTarget(nullptr, "XPower", event)) {
471         HIVIEW_LOGE("%{public}s failed for pid=%{public}d error", eventName.c_str(), memoryCaller.pid);
472         return {UCollect::UcError::SYSTEM_ERROR};
473     }
474     return {UCollect::UcError::SUCCESS};
475 }
476 
SetSplitMemoryValue(std::vector<UCollectClient::MemoryCaller> & memList)477 CollectResult<int32_t> HiviewService::SetSplitMemoryValue(std::vector<UCollectClient::MemoryCaller>& memList)
478 {
479     std::vector<int32_t> pidList;
480     std::vector<int32_t> resourceList;
481     for (auto it : memList) {
482         pidList.push_back(it.pid);
483         resourceList.push_back(it.limitValue);
484     }
485     std::string eventName = "AVCODEC_SPLITMEMORY";
486     SysEventCreator sysEventCreator("HIVIEWDFX", eventName, SysEventCreator::FAULT);
487     sysEventCreator.SetKeyValue("PID_LIST", pidList);
488     sysEventCreator.SetKeyValue("RESOURCE_LIST", resourceList);
489 
490     auto sysEvent = std::make_shared<SysEvent>(eventName, nullptr, sysEventCreator);
491     auto event = std::dynamic_pointer_cast<Event>(sysEvent);
492     if (!HiviewPlatform::GetInstance().PostSyncEventToTarget(nullptr, "XPower", event)) {
493         HIVIEW_LOGE("%{public}s failed", eventName.c_str());
494         return {UCollect::UcError::SYSTEM_ERROR};
495     }
496     return {UCollect::UcError::SUCCESS};
497 }
498 
GetGraphicUsage(int32_t pid)499 CollectResult<int32_t> HiviewService::GetGraphicUsage(int32_t pid)
500 {
501     return graphicMemoryCollector_->GetGraphicUsage(pid, GraphicType::TOTAL, true);
502 }
503 }  // namespace HiviewDFX
504 }  // namespace OHOS
505