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