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