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
16 #include "freeze_detector_plugin.h"
17
18 #include <algorithm>
19
20 #include "logger.h"
21 #include "plugin_factory.h"
22 #include "string_util.h"
23 #include "sys_event_dao.h"
24
25 #include "decoded/decoded_event.h"
26
27 namespace OHOS {
28 namespace HiviewDFX {
29 REGISTER_PROXY(FreezeDetectorPlugin);
30 DEFINE_LOG_TAG("FreezeDetector");
FreezeDetectorPlugin()31 FreezeDetectorPlugin::FreezeDetectorPlugin()
32 {
33 }
34
~FreezeDetectorPlugin()35 FreezeDetectorPlugin::~FreezeDetectorPlugin()
36 {
37 }
38
ReadyToLoad()39 bool FreezeDetectorPlugin::ReadyToLoad()
40 {
41 freezeCommon_ = std::make_shared<FreezeCommon>();
42 bool ret1 = freezeCommon_->Init();
43 freezeResolver_ = std::make_unique<FreezeResolver>(freezeCommon_);
44 bool ret2 = freezeResolver_->Init();
45 return ret1 && ret2;
46 }
47
OnLoad()48 void FreezeDetectorPlugin::OnLoad()
49 {
50 HIVIEW_LOGD("OnLoad.");
51 SetName(FREEZE_DETECTOR_PLUGIN_NAME);
52 SetVersion(FREEZE_DETECTOR_PLUGIN_VERSION);
53
54 threadLoop_ = GetWorkLoop();
55 if (threadLoop_ == nullptr) {
56 HIVIEW_LOGW("thread loop is null.");
57 return;
58 }
59 threadLoop_->StartLoop(false);
60 freezeCommon_ = std::make_shared<FreezeCommon>();
61 bool ret = freezeCommon_->Init();
62 if (!ret) {
63 HIVIEW_LOGW("freezeCommon_->Init false.");
64 freezeCommon_ = nullptr;
65 return;
66 }
67 freezeResolver_ = std::make_unique<FreezeResolver>(freezeCommon_);
68 ret = freezeResolver_->Init();
69 if (!ret) {
70 HIVIEW_LOGW("freezeResolver_->Init false.");
71 freezeCommon_ = nullptr;
72 freezeResolver_ = nullptr;
73 }
74 }
75
OnUnload()76 void FreezeDetectorPlugin::OnUnload()
77 {
78 HIVIEW_LOGD("OnUnload.");
79 }
80
OnEvent(std::shared_ptr<Event> & event)81 bool FreezeDetectorPlugin::OnEvent(std::shared_ptr<Event> &event)
82 {
83 return false;
84 }
85
CanProcessEvent(std::shared_ptr<Event> event)86 bool FreezeDetectorPlugin::CanProcessEvent(std::shared_ptr<Event> event)
87 {
88 return false;
89 }
90
RemoveRedundantNewline(const std::string & content) const91 std::string FreezeDetectorPlugin::RemoveRedundantNewline(const std::string& content) const
92 {
93 std::vector<std::string> lines;
94 StringUtil::SplitStr(content, "\\n", lines, false, false);
95
96 std::string outContent;
97 for (const auto& line : lines) {
98 outContent.append(line).append("\n");
99 }
100 return outContent;
101 }
102
MakeWatchPoint(const Event & event)103 WatchPoint FreezeDetectorPlugin::MakeWatchPoint(const Event& event)
104 {
105 Event& eventRef = const_cast<Event&>(event);
106 SysEvent& sysEvent = static_cast<SysEvent&>(eventRef);
107
108 long seq = sysEvent.GetSeq();
109 long tid = sysEvent.GetTid();
110 long pid = sysEvent.GetEventIntValue(FreezeCommon::EVENT_PID);
111 pid = pid ? pid : sysEvent.GetPid();
112 long uid = sysEvent.GetEventIntValue(FreezeCommon::EVENT_UID);
113 uid = uid ? uid : sysEvent.GetUid();
114 std::string packageName = sysEvent.GetEventValue(FreezeCommon::EVENT_PACKAGE_NAME);
115 std::string processName = sysEvent.GetEventValue(FreezeCommon::EVENT_PROCESS_NAME);
116 std::string msg = RemoveRedundantNewline(sysEvent.GetEventValue(FreezeCommon::EVENT_MSG));
117 std::string hiteaceTime = sysEvent.GetEventValue(FreezeCommon::HIREACE_TIME);
118 std::string sysrqTime = sysEvent.GetEventValue(FreezeCommon::SYSRQ_TIME);
119 std::string info = sysEvent.GetEventValue(EventStore::EventCol::INFO);
120 std::regex reg("logPath:([^,]+)");
121 std::smatch result;
122 std::string logPath = "";
123 if (std::regex_search(info, result, reg)) {
124 logPath = result[1].str();
125 }
126 WatchPoint watchPoint = OHOS::HiviewDFX::WatchPoint::Builder()
127 .InitSeq(seq)
128 .InitDomain(event.domain_)
129 .InitStringId(event.eventName_)
130 .InitTimestamp(event.happenTime_)
131 .InitPid(pid)
132 .InitTid(tid)
133 .InitUid(uid)
134 .InitPackageName(packageName)
135 .InitProcessName(processName)
136 .InitMsg(msg)
137 .InitLogPath(logPath)
138 .InitHitraceTime(hiteaceTime)
139 .InitSysrqTime(sysrqTime)
140 .Build();
141 HIVIEW_LOGI("watchpoint domain=%{public}s, stringid=%{public}s, pid=%{public}ld, uid=%{public}ld, "
142 "seq=%{public}ld, packageName=%{public}s, processName=%{public}s, msg=%{public}s logPath=%{public}s.",
143 event.domain_.c_str(), event.eventName_.c_str(), pid, uid,
144 seq, packageName.c_str(), processName.c_str(), msg.c_str(), logPath.c_str());
145
146 return watchPoint;
147 }
148
OnEventListeningCallback(const Event & event)149 void FreezeDetectorPlugin::OnEventListeningCallback(const Event& event)
150 {
151 if (event.rawData_ == nullptr) {
152 HIVIEW_LOGE("raw data of event is null.");
153 return;
154 }
155 EventRaw::DecodedEvent decodedEvent(event.rawData_->GetData());
156 if (!decodedEvent.IsValid()) {
157 HIVIEW_LOGE("failed to decode the raw data of event.");
158 return;
159 }
160 HIVIEW_LOGD("received event id=%{public}u, domain=%{public}s, stringid=%{public}s, extraInfo=%{public}s.",
161 event.eventId_, event.domain_.c_str(), event.eventName_.c_str(), decodedEvent.AsJsonStr().c_str());
162 if (freezeCommon_ == nullptr) {
163 return;
164 }
165
166 if (freezeCommon_->IsFreezeEvent(event.domain_, event.eventName_) == false) {
167 HIVIEW_LOGE("not freeze event.");
168 return;
169 }
170
171 HIVIEW_LOGD("received event domain=%{public}s, stringid=%{public}s",
172 event.domain_.c_str(), event.eventName_.c_str());
173 HIVIEW_LOGD("threadLoop_->IsRunning() = %{public}d", threadLoop_->IsRunning());
174 this->AddUseCount();
175 // dispatcher context, send task to our thread
176 WatchPoint watchPoint = MakeWatchPoint(event);
177 if (watchPoint.GetLogPath().empty()) {
178 return;
179 }
180
181 std::shared_ptr<FreezeRuleCluster> freezeRuleCluster = freezeCommon_->GetFreezeRuleCluster();
182 std::vector<FreezeResult> freezeResultList;
183 bool ruleRet = freezeRuleCluster->GetResult(watchPoint, freezeResultList);
184 if (!ruleRet) {
185 return;
186 }
187 long delayTime = 0;
188 if (freezeResultList.size() > 1) {
189 for (auto& i : freezeResultList) {
190 long window = i.GetWindow();
191 delayTime = std::max(delayTime, window);
192 }
193 if (delayTime == 0) {
194 delayTime = 10; // delay: 10s
195 }
196 }
197 auto task = std::bind(&FreezeDetectorPlugin::ProcessEvent, this, watchPoint);
198 threadLoop_->AddTimerEvent(nullptr, nullptr, task, delayTime, false);
199 }
200
ProcessEvent(WatchPoint watchPoint)201 void FreezeDetectorPlugin::ProcessEvent(WatchPoint watchPoint)
202 {
203 HIVIEW_LOGD("received event domain=%{public}s, stringid=%{public}s",
204 watchPoint.GetDomain().c_str(), watchPoint.GetStringId().c_str());
205 if (freezeResolver_ == nullptr) {
206 this->SubUseCount();
207 return;
208 }
209
210 auto ret = freezeResolver_->ProcessEvent(watchPoint);
211 if (ret < 0) {
212 HIVIEW_LOGE("FreezeResolver ProcessEvent filled.");
213 }
214 this->SubUseCount();
215 }
216 } // namespace HiviewDFX
217 } // namespace OHOS
218