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