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