• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 #include "event_log_task.h"
16 
17 #include <unistd.h>
18 
19 #include "binder_catcher.h"
20 #include "common_utils.h"
21 #include "dmesg_catcher.h"
22 #include "logger.h"
23 #include "open_stacktrace_catcher.h"
24 #include "parameter_ex.h"
25 #include "peer_binder_catcher.h"
26 #include "securec.h"
27 #include "shell_catcher.h"
28 #include "string_util.h"
29 #include "trace_collector.h"
30 
31 namespace OHOS {
32 namespace HiviewDFX {
33 namespace {
34 const std::string SYSTEM_STACK[] = {
35     "foundation",
36     "render_service",
37 };
38 }
39 DEFINE_LOG_LABEL(0xD002D01, "EventLogger-EventLogTask");
EventLogTask(int fd,int jsonFd,std::shared_ptr<SysEvent> event)40 EventLogTask::EventLogTask(int fd, int jsonFd, std::shared_ptr<SysEvent> event)
41     : targetFd_(fd),
42       targetJsonFd_(jsonFd),
43       event_(event),
44       maxLogSize_(DEFAULT_LOG_SIZE),
45       taskLogSize_(0),
46       status_(Status::TASK_RUNNABLE)
47 {
48     int pid = event_->GetEventIntValue("PID");
49     pid_ = pid ? pid : event_->GetPid();
50     captureList_.insert(std::pair<std::string, capture>("s", std::bind(&EventLogTask::AppStackCapture, this)));
51     captureList_.insert(std::pair<std::string, capture>("S", std::bind(&EventLogTask::SystemStackCapture, this)));
52     captureList_.insert(std::pair<std::string, capture>("b", std::bind(&EventLogTask::BinderLogCapture, this)));
53     captureList_.insert(std::pair<std::string, capture>("cmd:c", std::bind(&EventLogTask::CpuUsageCapture, this)));
54     captureList_.insert(std::pair<std::string, capture>("cmd:m", std::bind(&EventLogTask::MemoryUsageCapture, this)));
55     captureList_.insert(std::pair<std::string, capture>("cmd:w", std::bind(&EventLogTask::WMSUsageCapture, this)));
56     captureList_.insert(std::pair<std::string, capture>("cmd:a", std::bind(&EventLogTask::AMSUsageCapture, this)));
57     captureList_.insert(std::pair<std::string, capture>("cmd:p", std::bind(&EventLogTask::PMSUsageCapture, this)));
58     captureList_.insert(std::pair<std::string, capture>("cmd:d", std::bind(&EventLogTask::DPMSUsageCapture, this)));
59     captureList_.insert(std::pair<std::string, capture>("cmd:rs", std::bind(&EventLogTask::RSUsageCapture, this)));
60     captureList_.insert(std::pair<std::string, capture>("cmd:ss", std::bind(&EventLogTask::Screenshot, this)));
61     captureList_.insert(std::pair<std::string, capture>("T", std::bind(&EventLogTask::HilogCapture, this)));
62     captureList_.insert(std::pair<std::string, capture>("t", std::bind(&EventLogTask::LightHilogCapture, this)));
63     captureList_.insert(std::pair<std::string, capture>("e", std::bind(&EventLogTask::DmesgCapture, this)));
64     captureList_.insert(std::pair<std::string, capture>("k:SysRq",
65         std::bind(&EventLogTask::SysrqCapture, this, false)));
66     captureList_.insert(std::pair<std::string, capture>("k:SysRqFile",
67         std::bind(&EventLogTask::SysrqCapture, this, true)));
68     captureList_.insert(std::pair<std::string, capture>("tr", std::bind(&EventLogTask::HitraceCapture, this)));
69     captureList_.insert(std::pair<std::string, capture>("cmd:scbCS",
70         std::bind(&EventLogTask::SCBSessionCapture, this)));
71     captureList_.insert(std::pair<std::string, capture>("cmd:scbVP",
72         std::bind(&EventLogTask::SCBViewParamCapture, this)));
73 }
74 
AddLog(const std::string & cmd)75 void EventLogTask::AddLog(const std::string &cmd)
76 {
77     if (tasks_.size() == 0) {
78         status_ = Status::TASK_RUNNABLE;
79     }
80 
81     if (captureList_.find(cmd) != captureList_.end()) {
82         captureList_[cmd]();
83         return;
84     }
85     PeerBinderCapture(cmd);
86     catchedPids_.clear();
87 }
88 
StartCompose()89 EventLogTask::Status EventLogTask::StartCompose()
90 {
91     // nothing to do, return success
92     if (status_ != Status::TASK_RUNNABLE) {
93         return status_;
94     }
95     status_ = Status::TASK_RUNNING;
96     // nothing to do, return success
97     if (tasks_.size() == 0) {
98         return Status::TASK_SUCCESS;
99     }
100 
101     auto dupedFd = dup(targetFd_);
102     int dupedJsonFd = -1;
103     if (targetJsonFd_ >= 0) {
104         dupedJsonFd = dup(targetJsonFd_);
105     }
106     uint32_t catcherIndex = 0;
107     for (auto& catcher : tasks_) {
108         catcherIndex++;
109         if (dupedFd < 0) {
110             status_ = Status::TASK_FAIL;
111             AddStopReason(targetFd_, catcher, "Fail to dup file descriptor, exit!");
112             return TASK_FAIL;
113         }
114 
115         AddSeparator(dupedFd, catcher);
116         int curLogSize = catcher->Catch(dupedFd, dupedJsonFd);
117         HIVIEW_LOGI("finish catcher: %{public}s, curLogSize: %{public}d", catcher->GetDescription().c_str(),
118             curLogSize);
119         if (ShouldStopLogTask(dupedFd, catcherIndex, curLogSize, catcher)) {
120             break;
121         }
122     }
123     close(dupedFd);
124     if (dupedJsonFd >= 0) {
125         close(dupedJsonFd);
126     }
127     if (status_ == Status::TASK_RUNNING) {
128         status_ = Status::TASK_SUCCESS;
129     }
130     return status_;
131 }
132 
ShouldStopLogTask(int fd,uint32_t curTaskIndex,int curLogSize,std::shared_ptr<EventLogCatcher> catcher)133 bool EventLogTask::ShouldStopLogTask(int fd, uint32_t curTaskIndex, int curLogSize,
134     std::shared_ptr<EventLogCatcher> catcher)
135 {
136     if (status_ == Status::TASK_TIMEOUT) {
137         HIVIEW_LOGE("Break Log task, parent has timeout.");
138         return true;
139     }
140 
141     bool encounterErr = (curLogSize < 0);
142     bool hasFinished = (curTaskIndex == tasks_.size());
143     if (!encounterErr) {
144         taskLogSize_ += curLogSize;
145     }
146 
147     if (taskLogSize_ > maxLogSize_ && !hasFinished) {
148         AddStopReason(fd, catcher, "Exceed max log size");
149         status_ = Status::TASK_EXCEED_SIZE;
150         return true;
151     }
152 
153     if (encounterErr) {
154         AddStopReason(fd, catcher, "Log catcher not successful");
155         HIVIEW_LOGE("catcher %{public}s, Log catcher not successful", catcher->GetDescription().c_str());
156     }
157     return false;
158 }
159 
AddStopReason(int fd,std::shared_ptr<EventLogCatcher> catcher,const std::string & reason)160 void EventLogTask::AddStopReason(int fd, std::shared_ptr<EventLogCatcher> catcher, const std::string& reason)
161 {
162     char buf[BUF_SIZE_512] = {0};
163     int ret = -1;
164     if (catcher != nullptr) {
165         catcher->Stop();
166         // sleep 1s for syncing log to the fd, then we could append failure reason ?
167         sleep(1);
168         std::string summary = catcher->GetDescription();
169         ret = snprintf_s(buf, BUF_SIZE_512, BUF_SIZE_512 - 1, "\nTask stopped when running catcher:%s, Reason:%s \n",
170                          summary.c_str(), reason.c_str());
171     } else {
172         ret = snprintf_s(buf, BUF_SIZE_512, BUF_SIZE_512 - 1, "\nTask stopped, Reason:%s \n", reason.c_str());
173     }
174 
175     if (ret > 0) {
176         write(fd, buf, strnlen(buf, BUF_SIZE_512));
177         fsync(fd);
178     }
179 }
180 
AddSeparator(int fd,std::shared_ptr<EventLogCatcher> catcher) const181 void EventLogTask::AddSeparator(int fd, std::shared_ptr<EventLogCatcher> catcher) const
182 {
183     char buf[BUF_SIZE_512] = {0};
184     std::string summary = catcher->GetDescription();
185     if (summary.empty()) {
186         HIVIEW_LOGE("summary.empty() catcher is %{public}s", catcher->GetName().c_str());
187         return;
188     }
189 
190     int ret = snprintf_s(buf, BUF_SIZE_512, BUF_SIZE_512 - 1, "\n%s\n", summary.c_str());
191     if (ret > 0) {
192         write(fd, buf, strnlen(buf, BUF_SIZE_512));
193         fsync(fd);
194     }
195 }
196 
RecordCatchedPids(const std::string & packageName)197 void EventLogTask::RecordCatchedPids(const std::string& packageName)
198 {
199     int pid = CommonUtils::GetPidByName(packageName);
200     if (pid > 0) {
201         catchedPids_.insert(pid);
202     }
203 }
204 
GetTaskStatus() const205 EventLogTask::Status EventLogTask::GetTaskStatus() const
206 {
207     return status_;
208 }
209 
GetLogSize() const210 long EventLogTask::GetLogSize() const
211 {
212     return taskLogSize_;
213 }
214 
AppStackCapture()215 void EventLogTask::AppStackCapture()
216 {
217     auto capture = std::make_shared<OpenStacktraceCatcher>();
218     capture->Initialize(event_->GetEventValue("PACKAGE_NAME"), pid_, 0);
219     tasks_.push_back(capture);
220 }
221 
SystemStackCapture()222 void EventLogTask::SystemStackCapture()
223 {
224     for (auto packageName : SYSTEM_STACK) {
225         auto capture = std::make_shared<OpenStacktraceCatcher>();
226         capture->Initialize(packageName, 0, 0);
227         RecordCatchedPids(packageName);
228         tasks_.push_back(capture);
229     }
230 }
231 
BinderLogCapture()232 void EventLogTask::BinderLogCapture()
233 {
234     auto capture = std::make_shared<BinderCatcher>();
235     capture->Initialize("", 0, 0);
236     tasks_.push_back(capture);
237 }
238 
PeerBinderCapture(const std::string & cmd)239 bool EventLogTask::PeerBinderCapture(const std::string &cmd)
240 {
241     auto find = cmd.find("pb");
242     if (find == cmd.npos) {
243         return false;
244     }
245 
246     std::vector<std::string> cmdList;
247     StringUtil::SplitStr(cmd, ":", cmdList, true);
248     if (cmdList.size() != PeerBinderCatcher::BP_CMD_SZ || cmdList.front() != "pb") {
249         return false;
250     }
251 
252     auto capture = std::make_shared<PeerBinderCatcher>();
253     capture->Initialize(cmdList[PeerBinderCatcher::BP_CMD_PERF_TYPE_INDEX],
254         StringUtil::StrToInt(cmdList[PeerBinderCatcher::BP_CMD_LAYER_INDEX]), pid_);
255     capture->Init(event_, "", catchedPids_);
256     tasks_.push_back(capture);
257     return true;
258 }
259 
WMSUsageCapture()260 void EventLogTask::WMSUsageCapture()
261 {
262     auto capture = std::make_shared<ShellCatcher>();
263     capture->Initialize("hidumper -s WindowManagerService -a -a", ShellCatcher::CATCHER_WMS, pid_);
264     tasks_.push_back(capture);
265 }
266 
AMSUsageCapture()267 void EventLogTask::AMSUsageCapture()
268 {
269     auto capture = std::make_shared<ShellCatcher>();
270     capture->Initialize("hidumper -s AbilityManagerService -a -a", ShellCatcher::CATCHER_AMS, pid_);
271     tasks_.push_back(capture);
272 }
273 
CpuUsageCapture()274 void EventLogTask::CpuUsageCapture()
275 {
276     auto capture = std::make_shared<ShellCatcher>();
277     capture->Initialize("hidumper --cpuusage", ShellCatcher::CATCHER_CPU, pid_);
278     tasks_.push_back(capture);
279 }
280 
MemoryUsageCapture()281 void EventLogTask::MemoryUsageCapture()
282 {
283     auto capture = std::make_shared<ShellCatcher>();
284     capture->Initialize("hidumper --mem", ShellCatcher::CATCHER_MEM, pid_);
285     tasks_.push_back(capture);
286 }
287 
PMSUsageCapture()288 void EventLogTask::PMSUsageCapture()
289 {
290     auto capture = std::make_shared<ShellCatcher>();
291     capture->Initialize("hidumper -s PowerManagerService -a -s", ShellCatcher::CATCHER_PMS, pid_);
292     tasks_.push_back(capture);
293 }
294 
DPMSUsageCapture()295 void EventLogTask::DPMSUsageCapture()
296 {
297     auto capture = std::make_shared<ShellCatcher>();
298     capture->Initialize("hidumper -s DisplayPowerManagerService", ShellCatcher::CATCHER_DPMS, pid_);
299     tasks_.push_back(capture);
300 }
301 
HilogCapture()302 void EventLogTask::HilogCapture()
303 {
304     auto capture = std::make_shared<ShellCatcher>();
305     capture->Initialize("hilog -x", ShellCatcher::CATCHER_HILOG, 0);
306     tasks_.push_back(capture);
307 }
308 
LightHilogCapture()309 void EventLogTask::LightHilogCapture()
310 {
311     auto capture = std::make_shared<ShellCatcher>();
312     capture->Initialize("hilog -z 100 -P", ShellCatcher::CATCHER_LIGHT_HILOG, pid_);
313     tasks_.push_back(capture);
314 }
315 
RSUsageCapture()316 void EventLogTask::RSUsageCapture()
317 {
318     auto capture = std::make_shared<ShellCatcher>();
319     capture->Initialize("hidumper -s RenderService -a allInfo", ShellCatcher::CATCHER_RS, pid_);
320     tasks_.push_back(capture);
321 }
322 
Screenshot()323 void EventLogTask::Screenshot()
324 {
325     auto capture = std::make_shared<ShellCatcher>();
326     capture->Initialize("snapshot_display -f x.jpeg", ShellCatcher::CATCHER_SNAPSHOT, pid_);
327     tasks_.push_back(capture);
328 }
329 
DmesgCapture()330 void EventLogTask::DmesgCapture()
331 {
332     auto capture = std::make_shared<DmesgCatcher>();
333     capture->Initialize("", 0, 0);
334     capture->Init(event_);
335     tasks_.push_back(capture);
336 }
337 
SysrqCapture(bool isWriteNewFile)338 void EventLogTask::SysrqCapture(bool isWriteNewFile)
339 {
340     auto capture = std::make_shared<DmesgCatcher>();
341     capture->Initialize("", isWriteNewFile, 1);
342     capture->Init(event_);
343     tasks_.push_back(capture);
344 }
345 
HitraceCapture()346 void EventLogTask::HitraceCapture()
347 {
348     std::shared_ptr<UCollectUtil::TraceCollector> collector = UCollectUtil::TraceCollector::Create();
349     UCollectUtil::TraceCollector::Caller caller = UCollectUtil::TraceCollector::Caller::RELIABILITY;
350     auto result = collector->DumpTrace(caller);
351     if (result.retCode != 0) {
352         HIVIEW_LOGE("get hitrace fail! error code : %{public}d", result.retCode);
353         return;
354     }
355 }
356 
SCBSessionCapture()357 void EventLogTask::SCBSessionCapture()
358 {
359     auto capture = std::make_shared<ShellCatcher>();
360     capture->Initialize("scb_debug SCBScenePanel getContainerSession", ShellCatcher::CATCHER_SCBSESSION, pid_);
361     tasks_.push_back(capture);
362 }
363 
SCBViewParamCapture()364 void EventLogTask::SCBViewParamCapture()
365 {
366     auto capture = std::make_shared<ShellCatcher>();
367     capture->Initialize("scb_debug SCBScenePanel getViewParam", ShellCatcher::CATCHER_SCBVIEWPARAM, pid_);
368     tasks_.push_back(capture);
369 }
370 } // namespace HiviewDFX
371 } // namespace OHOS
372