• 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 #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 "hiview_logger.h"
23 #include "memory_catcher.h"
24 #include "open_stacktrace_catcher.h"
25 #include "parameter_ex.h"
26 #include "peer_binder_catcher.h"
27 #include "securec.h"
28 #include "shell_catcher.h"
29 #include "string_util.h"
30 #include "trace_collector.h"
31 
32 namespace OHOS {
33 namespace HiviewDFX {
34 namespace {
35 const std::string SYSTEM_STACK[] = {
36     "foundation",
37     "render_service",
38 };
39 }
40 DEFINE_LOG_LABEL(0xD002D01, "EventLogger-EventLogTask");
EventLogTask(int fd,int jsonFd,std::shared_ptr<SysEvent> event)41 EventLogTask::EventLogTask(int fd, int jsonFd, std::shared_ptr<SysEvent> event)
42     : targetFd_(fd),
43       targetJsonFd_(jsonFd),
44       event_(event),
45       maxLogSize_(DEFAULT_LOG_SIZE),
46       taskLogSize_(0),
47       status_(Status::TASK_RUNNABLE)
48 {
49     int pid = event_->GetEventIntValue("PID");
50     pid_ = pid ? pid : event_->GetPid();
51     captureList_.insert(std::pair<std::string, capture>("s", [this] { this->AppStackCapture(); }));
52     captureList_.insert(std::pair<std::string, capture>("S", [this] { this->SystemStackCapture(); }));
53     captureList_.insert(std::pair<std::string, capture>("b", [this] { this->BinderLogCapture(); }));
54     captureList_.insert(std::pair<std::string, capture>("cmd:m", [this] { this->MemoryUsageCapture(); }));
55     captureList_.insert(std::pair<std::string, capture>("cmd:c", [this] { this->CpuUsageCapture(); }));
56     captureList_.insert(std::pair<std::string, capture>("cmd:w", [this] { this->WMSUsageCapture(); }));
57     captureList_.insert(std::pair<std::string, capture>("cmd:a", [this] { this->AMSUsageCapture(); }));
58     captureList_.insert(std::pair<std::string, capture>("cmd:p", [this] { this->PMSUsageCapture(); }));
59     captureList_.insert(std::pair<std::string, capture>("cmd:d", [this] { this->DPMSUsageCapture(); }));
60     captureList_.insert(std::pair<std::string, capture>("cmd:rs", [this] { this->RSUsageCapture(); }));
61     captureList_.insert(std::pair<std::string, capture>("cmd:mmi", [this] { this->MMIUsageCapture(); }));
62     captureList_.insert(std::pair<std::string, capture>("cmd:dms", [this] { this->DMSUsageCapture(); }));
63     captureList_.insert(std::pair<std::string, capture>("cmd:eec", [this] { this->EECStateCapture(); }));
64     captureList_.insert(std::pair<std::string, capture>("cmd:gec", [this] { this->GECStateCapture(); }));
65     captureList_.insert(std::pair<std::string, capture>("cmd:ui", [this] { this->UIStateCapture(); }));
66     captureList_.insert(std::pair<std::string, capture>("cmd:ss", [this] { this->Screenshot(); }));
67     captureList_.insert(std::pair<std::string, capture>("T", [this] { this->HilogCapture(); }));
68     captureList_.insert(std::pair<std::string, capture>("t", [this] { this->LightHilogCapture(); }));
69     captureList_.insert(std::pair<std::string, capture>("e", [this] { this->DmesgCapture(); }));
70     captureList_.insert(std::pair<std::string, capture>("k:SysRq",
71         [this] { this->SysrqCapture(false); }));
72     captureList_.insert(std::pair<std::string, capture>("k:SysRqFile",
73         [this] { this->SysrqCapture(true); }));
74     captureList_.insert(std::pair<std::string, capture>("tr", [this] { this->HitraceCapture(); }));
75     captureList_.insert(std::pair<std::string, capture>("cmd:scbCS",
76         [this] { this->SCBSessionCapture(); }));
77     captureList_.insert(std::pair<std::string, capture>("cmd:scbVP",
78         [this] { this->SCBViewParamCapture(); }));
79     captureList_.insert(std::pair<std::string, capture>("cmd:scbWMS",
80         [this] { this->SCBWMSCapture(); }));
81     captureList_.insert(std::pair<std::string, capture>("cmd:scbWMSEVT",
82         [this] { this->SCBWMSEVTCapture(); }));
83     captureList_.insert(std::pair<std::string, capture>("cmd:dam",
84         [this] { this->DumpAppMapCapture(); }));
85     captureList_.insert(std::pair<std::string, capture>("t:input",
86         [this] { this->InputHilogCapture(); }));
87 }
88 
AddLog(const std::string & cmd)89 void EventLogTask::AddLog(const std::string &cmd)
90 {
91     if (tasks_.size() == 0) {
92         status_ = Status::TASK_RUNNABLE;
93     }
94 
95     if (captureList_.find(cmd) != captureList_.end()) {
96         captureList_[cmd]();
97         return;
98     }
99     PeerBinderCapture(cmd);
100     catchedPids_.clear();
101 }
102 
StartCompose()103 EventLogTask::Status EventLogTask::StartCompose()
104 {
105     // nothing to do, return success
106     if (status_ != Status::TASK_RUNNABLE) {
107         return status_;
108     }
109     status_ = Status::TASK_RUNNING;
110     // nothing to do, return success
111     if (tasks_.size() == 0) {
112         return Status::TASK_SUCCESS;
113     }
114 
115     auto dupedFd = dup(targetFd_);
116     int dupedJsonFd = -1;
117     if (targetJsonFd_ >= 0) {
118         dupedJsonFd = dup(targetJsonFd_);
119     }
120     uint32_t catcherIndex = 0;
121     for (auto& catcher : tasks_) {
122         catcherIndex++;
123         if (dupedFd < 0) {
124             status_ = Status::TASK_FAIL;
125             AddStopReason(targetFd_, catcher, "Fail to dup file descriptor, exit!");
126             return TASK_FAIL;
127         }
128 
129         AddSeparator(dupedFd, catcher);
130         int curLogSize = catcher->Catch(dupedFd, dupedJsonFd);
131         HIVIEW_LOGI("finish catcher: %{public}s, curLogSize: %{public}d", catcher->GetDescription().c_str(),
132             curLogSize);
133         if (ShouldStopLogTask(dupedFd, catcherIndex, curLogSize, catcher)) {
134             break;
135         }
136     }
137     close(dupedFd);
138     if (dupedJsonFd >= 0) {
139         close(dupedJsonFd);
140     }
141     if (status_ == Status::TASK_RUNNING) {
142         status_ = Status::TASK_SUCCESS;
143     }
144     return status_;
145 }
146 
ShouldStopLogTask(int fd,uint32_t curTaskIndex,int curLogSize,std::shared_ptr<EventLogCatcher> catcher)147 bool EventLogTask::ShouldStopLogTask(int fd, uint32_t curTaskIndex, int curLogSize,
148     std::shared_ptr<EventLogCatcher> catcher)
149 {
150     if (status_ == Status::TASK_TIMEOUT) {
151         HIVIEW_LOGE("Break Log task, parent has timeout.");
152         return true;
153     }
154 
155     bool encounterErr = (curLogSize < 0);
156     bool hasFinished = (curTaskIndex == tasks_.size());
157     if (!encounterErr) {
158         taskLogSize_ += static_cast<uint32_t>(curLogSize);
159     }
160 
161     if (taskLogSize_ > maxLogSize_ && !hasFinished) {
162         AddStopReason(fd, catcher, "Exceed max log size");
163         status_ = Status::TASK_EXCEED_SIZE;
164         return true;
165     }
166 
167     if (encounterErr) {
168         AddStopReason(fd, catcher, "Log catcher not successful");
169         HIVIEW_LOGE("catcher %{public}s, Log catcher not successful", catcher->GetDescription().c_str());
170     }
171     return false;
172 }
173 
AddStopReason(int fd,std::shared_ptr<EventLogCatcher> catcher,const std::string & reason)174 void EventLogTask::AddStopReason(int fd, std::shared_ptr<EventLogCatcher> catcher, const std::string& reason)
175 {
176     char buf[BUF_SIZE_512] = {0};
177     int ret = -1;
178     if (catcher != nullptr) {
179         catcher->Stop();
180         // sleep 1s for syncing log to the fd, then we could append failure reason ?
181         sleep(1);
182         std::string summary = catcher->GetDescription();
183         ret = snprintf_s(buf, BUF_SIZE_512, BUF_SIZE_512 - 1, "\nTask stopped when running catcher:%s, Reason:%s \n",
184                          summary.c_str(), reason.c_str());
185     } else {
186         ret = snprintf_s(buf, BUF_SIZE_512, BUF_SIZE_512 - 1, "\nTask stopped, Reason:%s \n", reason.c_str());
187     }
188 
189     if (ret > 0) {
190         write(fd, buf, strnlen(buf, BUF_SIZE_512));
191         fsync(fd);
192     }
193 }
194 
AddSeparator(int fd,std::shared_ptr<EventLogCatcher> catcher) const195 void EventLogTask::AddSeparator(int fd, std::shared_ptr<EventLogCatcher> catcher) const
196 {
197     char buf[BUF_SIZE_512] = {0};
198     std::string summary = catcher->GetDescription();
199     if (summary.empty()) {
200         HIVIEW_LOGE("summary.empty() catcher is %{public}s", catcher->GetName().c_str());
201         return;
202     }
203 
204     int ret = snprintf_s(buf, BUF_SIZE_512, BUF_SIZE_512 - 1, "\n%s\n", summary.c_str());
205     if (ret > 0) {
206         write(fd, buf, strnlen(buf, BUF_SIZE_512));
207         fsync(fd);
208     }
209 }
210 
RecordCatchedPids(const std::string & packageName)211 void EventLogTask::RecordCatchedPids(const std::string& packageName)
212 {
213     int pid = CommonUtils::GetPidByName(packageName);
214     if (pid > 0) {
215         catchedPids_.insert(pid);
216     }
217 }
218 
GetTaskStatus() const219 EventLogTask::Status EventLogTask::GetTaskStatus() const
220 {
221     return status_;
222 }
223 
GetLogSize() const224 long EventLogTask::GetLogSize() const
225 {
226     return taskLogSize_;
227 }
228 
AppStackCapture()229 void EventLogTask::AppStackCapture()
230 {
231     auto capture = std::make_shared<OpenStacktraceCatcher>();
232     capture->Initialize(event_->GetEventValue("PACKAGE_NAME"), pid_, 0);
233     tasks_.push_back(capture);
234 }
235 
SystemStackCapture()236 void EventLogTask::SystemStackCapture()
237 {
238     for (auto packageName : SYSTEM_STACK) {
239         auto capture = std::make_shared<OpenStacktraceCatcher>();
240         capture->Initialize(packageName, 0, 0);
241         RecordCatchedPids(packageName);
242         tasks_.push_back(capture);
243     }
244 }
245 
BinderLogCapture()246 void EventLogTask::BinderLogCapture()
247 {
248     auto capture = std::make_shared<BinderCatcher>();
249     capture->Initialize("", 0, 0);
250     tasks_.push_back(capture);
251 }
252 
MemoryUsageCapture()253 void EventLogTask::MemoryUsageCapture()
254 {
255     auto capture = std::make_shared<MemoryCatcher>();
256     capture->Initialize("", 0, 0);
257     tasks_.push_back(capture);
258 }
259 
PeerBinderCapture(const std::string & cmd)260 bool EventLogTask::PeerBinderCapture(const std::string &cmd)
261 {
262     auto find = cmd.find("pb");
263     if (find == cmd.npos) {
264         return false;
265     }
266 
267     std::vector<std::string> cmdList;
268     StringUtil::SplitStr(cmd, ":", cmdList, true);
269     if (cmdList.size() != PeerBinderCatcher::BP_CMD_SZ || cmdList.front() != "pb") {
270         return false;
271     }
272 
273     auto capture = std::make_shared<PeerBinderCatcher>();
274     capture->Initialize(cmdList[PeerBinderCatcher::BP_CMD_PERF_TYPE_INDEX],
275         StringUtil::StrToInt(cmdList[PeerBinderCatcher::BP_CMD_LAYER_INDEX]), pid_);
276     capture->Init(event_, "", catchedPids_);
277     tasks_.push_back(capture);
278     return true;
279 }
280 
CpuUsageCapture()281 void EventLogTask::CpuUsageCapture()
282 {
283     auto capture = std::make_shared<ShellCatcher>();
284     capture->Initialize("hidumper --cpuusage", ShellCatcher::CATCHER_CPU, pid_);
285     tasks_.push_back(capture);
286 }
287 
WMSUsageCapture()288 void EventLogTask::WMSUsageCapture()
289 {
290     auto capture = std::make_shared<ShellCatcher>();
291     capture->Initialize("hidumper -s WindowManagerService -a -a", ShellCatcher::CATCHER_WMS, pid_);
292     tasks_.push_back(capture);
293 }
294 
AMSUsageCapture()295 void EventLogTask::AMSUsageCapture()
296 {
297     auto capture = std::make_shared<ShellCatcher>();
298     capture->Initialize("hidumper -s AbilityManagerService -a -a", ShellCatcher::CATCHER_AMS, pid_);
299     tasks_.push_back(capture);
300 }
301 
PMSUsageCapture()302 void EventLogTask::PMSUsageCapture()
303 {
304     auto capture = std::make_shared<ShellCatcher>();
305     capture->Initialize("hidumper -s PowerManagerService -a -s", ShellCatcher::CATCHER_PMS, pid_);
306     tasks_.push_back(capture);
307 }
308 
DPMSUsageCapture()309 void EventLogTask::DPMSUsageCapture()
310 {
311     auto capture = std::make_shared<ShellCatcher>();
312     capture->Initialize("hidumper -s DisplayPowerManagerService", ShellCatcher::CATCHER_DPMS, 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 
MMIUsageCapture()323 void EventLogTask::MMIUsageCapture()
324 {
325     auto capture = std::make_shared<ShellCatcher>();
326     capture->Initialize("hidumper -s MultimodalInput -a -w", ShellCatcher::CATCHER_MMI, pid_);
327     tasks_.push_back(capture);
328 }
329 
DMSUsageCapture()330 void EventLogTask::DMSUsageCapture()
331 {
332     auto capture = std::make_shared<ShellCatcher>();
333     capture->Initialize("hidumper -s DisplayManagerService -a -a", ShellCatcher::CATCHER_DMS, pid_);
334     tasks_.push_back(capture);
335 }
336 
EECStateCapture()337 void EventLogTask::EECStateCapture()
338 {
339     auto capture = std::make_shared<ShellCatcher>();
340     capture->Initialize("hidumper -s 4606 -a '-b EventExclusiveCommander getAllEventExclusiveCaller'",
341         ShellCatcher::CATCHER_EEC, pid_);
342     tasks_.push_back(capture);
343 }
344 
GECStateCapture()345 void EventLogTask::GECStateCapture()
346 {
347     auto capture = std::make_shared<ShellCatcher>();
348     capture->Initialize("hidumper -s 4606 -a '-b SCBGestureManager getAllGestureEnableCaller'",
349         ShellCatcher::CATCHER_GEC, pid_);
350     tasks_.push_back(capture);
351 }
352 
UIStateCapture()353 void EventLogTask::UIStateCapture()
354 {
355     auto capture = std::make_shared<ShellCatcher>();
356     capture->Initialize("hidumper -s 4606 -a '-p 0'", ShellCatcher::CATCHER_UI, pid_);
357     tasks_.push_back(capture);
358 }
359 
Screenshot()360 void EventLogTask::Screenshot()
361 {
362     auto capture = std::make_shared<ShellCatcher>();
363     capture->Initialize("snapshot_display -f x.jpeg", ShellCatcher::CATCHER_SNAPSHOT, pid_);
364     tasks_.push_back(capture);
365 }
366 
HilogCapture()367 void EventLogTask::HilogCapture()
368 {
369     auto capture = std::make_shared<ShellCatcher>();
370     capture->Initialize("hilog -x", ShellCatcher::CATCHER_HILOG, 0);
371     tasks_.push_back(capture);
372 }
373 
LightHilogCapture()374 void EventLogTask::LightHilogCapture()
375 {
376     auto capture = std::make_shared<ShellCatcher>();
377     capture->Initialize("hilog -z 1000 -P", ShellCatcher::CATCHER_LIGHT_HILOG, pid_);
378     tasks_.push_back(capture);
379 }
380 
DmesgCapture()381 void EventLogTask::DmesgCapture()
382 {
383     auto capture = std::make_shared<DmesgCatcher>();
384     capture->Initialize("", 0, 0);
385     capture->Init(event_);
386     tasks_.push_back(capture);
387 }
388 
SysrqCapture(bool isWriteNewFile)389 void EventLogTask::SysrqCapture(bool isWriteNewFile)
390 {
391     auto capture = std::make_shared<DmesgCatcher>();
392     capture->Initialize("", isWriteNewFile, 1);
393     capture->Init(event_);
394     tasks_.push_back(capture);
395 }
396 
HitraceCapture()397 void EventLogTask::HitraceCapture()
398 {
399     std::shared_ptr<UCollectUtil::TraceCollector> collector = UCollectUtil::TraceCollector::Create();
400     UCollect::TraceCaller caller = UCollect::TraceCaller::RELIABILITY;
401     auto result = collector->DumpTraceWithDuration(caller, MAX_DUMP_TRACE_LIMIT);
402     if (result.retCode != 0) {
403         HIVIEW_LOGE("get hitrace fail! error code : %{public}d", result.retCode);
404         return;
405     }
406 }
407 
SCBSessionCapture()408 void EventLogTask::SCBSessionCapture()
409 {
410     auto capture = std::make_shared<ShellCatcher>();
411     capture->Initialize("hidumper -s 4606 -a '-b SCBScenePanel getContainerSession'",
412         ShellCatcher::CATCHER_SCBSESSION, pid_);
413     tasks_.push_back(capture);
414 }
415 
SCBViewParamCapture()416 void EventLogTask::SCBViewParamCapture()
417 {
418     auto capture = std::make_shared<ShellCatcher>();
419     capture->Initialize("hidumper -s 4606 -a '-b SCBScenePanel getViewParam'",
420         ShellCatcher::CATCHER_SCBVIEWPARAM, pid_);
421     tasks_.push_back(capture);
422 }
423 
SCBWMSCapture()424 void EventLogTask::SCBWMSCapture()
425 {
426     auto capture = std::make_shared<ShellCatcher>();
427     capture->SetEvent(event_);
428     std::string focusWindowId = capture->GetFocusWindowId();
429     if (focusWindowId.empty()) {
430         HIVIEW_LOGE("dump simplify get focus window error");
431         return;
432     }
433     std::string cmd = "hidumper -s WindowManagerService -a -w " + focusWindowId + " -simplify";
434     capture->Initialize(cmd, ShellCatcher::CATCHER_SCBWMS, pid_);
435     tasks_.push_back(capture);
436 }
437 
SCBWMSEVTCapture()438 void EventLogTask::SCBWMSEVTCapture()
439 {
440     auto capture = std::make_shared<ShellCatcher>();
441     capture->SetEvent(event_);
442     std::string focusWindowId = capture->GetFocusWindowId();
443     if (focusWindowId.empty()) {
444         HIVIEW_LOGE("dump event get focus window error");
445         return;
446     }
447     std::string cmd = "hidumper -s WindowManagerService -a -w " + focusWindowId + " -event";
448     capture->Initialize(cmd, ShellCatcher::CATCHER_SCBWMSEVT, pid_);
449     tasks_.push_back(capture);
450 }
451 
DumpAppMapCapture()452 void EventLogTask::DumpAppMapCapture()
453 {
454     auto capture = std::make_shared<ShellCatcher>();
455     capture->Initialize("hidumper -s 1910 -a DumpAppMap", ShellCatcher::CATCHER_DAM, pid_);
456     tasks_.push_back(capture);
457 }
458 
InputHilogCapture()459 void EventLogTask::InputHilogCapture()
460 {
461     auto capture = std::make_shared<ShellCatcher>();
462     int32_t eventId = event_->GetEventIntValue("INPUT_ID");
463     if (eventId > 0) {
464         std::string cmd = "hilog -T InputKeyFlow -e " +
465             std::to_string(eventId) + " -x";
466         capture->Initialize(cmd, ShellCatcher::CATCHER_INPUT_EVENT_HILOG, eventId);
467     } else {
468         capture->Initialize("hilog -T InputKeyFlow -x", ShellCatcher::CATCHER_INPUT_HILOG,
469             pid_);
470     }
471     tasks_.push_back(capture);
472 }
473 } // namespace HiviewDFX
474 } // namespace OHOS
475