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 "ffrt.h"
21 #include "hiview_logger.h"
22 #include "plugin_factory.h"
23 #include "process_status.h"
24 #include "string_util.h"
25 #include "sys_event_dao.h"
26
27 #include "decoded/decoded_event.h"
28
29 namespace OHOS {
30 namespace HiviewDFX {
31 namespace {
32 const static uint64_t TO_NANO_SECOND_MULTPLE = 1000000;
33 const static int MIN_APP_UID = 10000;
34 const static long MULTIPLE_DELAY_TIME = 10;
35 const static long SINGLE_DELAY_TIME = 3;
36 }
37 REGISTER_PROXY(FreezeDetectorPlugin);
38 DEFINE_LOG_LABEL(0xD002D01, "FreezeDetector");
FreezeDetectorPlugin()39 FreezeDetectorPlugin::FreezeDetectorPlugin()
40 {
41 }
42
~FreezeDetectorPlugin()43 FreezeDetectorPlugin::~FreezeDetectorPlugin()
44 {
45 }
46
ReadyToLoad()47 bool FreezeDetectorPlugin::ReadyToLoad()
48 {
49 freezeCommon_ = std::make_shared<FreezeCommon>();
50 bool ret1 = freezeCommon_->Init();
51 freezeResolver_ = std::make_unique<FreezeResolver>(freezeCommon_);
52 bool ret2 = freezeResolver_->Init();
53 return ret1 && ret2;
54 }
55
OnLoad()56 void FreezeDetectorPlugin::OnLoad()
57 {
58 HIVIEW_LOGD("OnLoad.");
59 SetName(FREEZE_DETECTOR_PLUGIN_NAME);
60 SetVersion(FREEZE_DETECTOR_PLUGIN_VERSION);
61
62 freezeCommon_ = std::make_shared<FreezeCommon>();
63 bool ret = freezeCommon_->Init();
64 if (!ret) {
65 HIVIEW_LOGW("freezeCommon_->Init false.");
66 freezeCommon_ = nullptr;
67 return;
68 }
69 freezeResolver_ = std::make_unique<FreezeResolver>(freezeCommon_);
70 ret = freezeResolver_->Init();
71 if (!ret) {
72 HIVIEW_LOGW("freezeResolver_->Init false.");
73 freezeCommon_ = nullptr;
74 freezeResolver_ = nullptr;
75 }
76 }
77
OnUnload()78 void FreezeDetectorPlugin::OnUnload()
79 {
80 HIVIEW_LOGD("OnUnload.");
81 }
82
OnEvent(std::shared_ptr<Event> & event)83 bool FreezeDetectorPlugin::OnEvent(std::shared_ptr<Event> &event)
84 {
85 return false;
86 }
87
CanProcessEvent(std::shared_ptr<Event> event)88 bool FreezeDetectorPlugin::CanProcessEvent(std::shared_ptr<Event> event)
89 {
90 return false;
91 }
92
RemoveRedundantNewline(const std::string & content) const93 std::string FreezeDetectorPlugin::RemoveRedundantNewline(const std::string& content) const
94 {
95 std::vector<std::string> lines;
96 StringUtil::SplitStr(content, "\\n", lines, false, false);
97
98 std::string outContent;
99 for (const auto& line : lines) {
100 outContent.append(line).append("\n");
101 }
102 return outContent;
103 }
104
MakeWatchPoint(const Event & event)105 WatchPoint FreezeDetectorPlugin::MakeWatchPoint(const Event& event)
106 {
107 Event& eventRef = const_cast<Event&>(event);
108 SysEvent& sysEvent = static_cast<SysEvent&>(eventRef);
109
110 long seq = sysEvent.GetSeq();
111 long pid = sysEvent.GetEventIntValue(FreezeCommon::EVENT_PID);
112 pid = pid ? pid : sysEvent.GetPid();
113 long tid = sysEvent.GetEventIntValue(FreezeCommon::EVENT_TID);
114 long uid = sysEvent.GetEventIntValue(FreezeCommon::EVENT_UID);
115 uid = uid ? uid : sysEvent.GetUid();
116 std::string packageName = sysEvent.GetEventValue(FreezeCommon::EVENT_PACKAGE_NAME);
117 std::string processName = sysEvent.GetEventValue(FreezeCommon::EVENT_PROCESS_NAME);
118 std::string hitraceTime = sysEvent.GetEventValue(FreezeCommon::HITRACE_TIME);
119 std::string sysrqTime = sysEvent.GetEventValue(FreezeCommon::SYSRQ_TIME);
120 std::string terminalThreadStack = sysEvent.GetEventValue(FreezeCommon::TERMINAL_THREAD_STACK);
121 std::string telemetryId = sysEvent.GetEventValue(FreezeCommon::TELEMETRY_ID);
122 std::string traceName = sysEvent.GetEventValue(FreezeCommon::TRACE_NAME);
123 std::string info = sysEvent.GetEventValue(EventStore::EventCol::INFO);
124 std::string hitraceIdInfo = sysEvent.GetEventValue(FreezeCommon::EVENT_TRACE_ID);
125 std::string procStatm = sysEvent.GetEventValue(FreezeCommon::PROC_STATM);
126 std::string hostResourceWarning = sysEvent.GetEventValue(FreezeCommon::HOST_RESOURCE_WARNING);
127 std::regex reg("logPath:([^,]+)");
128 std::smatch result;
129 std::string logPath = std::regex_search(info, result, reg) ? result[1].str() : info;
130 std::string foreGround;
131 CheckForeGround(uid, pid, event.happenTime_, foreGround);
132 WatchPoint watchPoint = OHOS::HiviewDFX::WatchPoint::Builder().InitSeq(seq).InitDomain(event.domain_)
133 .InitStringId(event.eventName_).InitTimestamp(event.happenTime_).InitPid(pid).InitTid(tid).InitUid(uid)
134 .InitTerminalThreadStack(terminalThreadStack).InitTelemetryId(telemetryId).InitTraceName(traceName)
135 .InitPackageName(packageName).InitProcessName(processName).InitForeGround(foreGround).InitMsg("")
136 .InitLogPath(logPath).InitHitraceTime(hitraceTime).InitSysrqTime(sysrqTime).InitHitraceIdInfo(hitraceIdInfo)
137 .InitProcStatm(procStatm).InitHostResourceWarning(hostResourceWarning).Build();
138 HIVIEW_LOGI("watchpoint domain=%{public}s, stringid=%{public}s, pid=%{public}ld, uid=%{public}ld, seq=%{public}ld,"
139 " packageName=%{public}s, processName=%{public}s, logPath=%{public}s, hitraceIdInfo=%{public}s,"
140 "procStatm=%{public}s, hostResourceWarning=%{public}s", event.domain_.c_str(), event.eventName_.c_str(), pid,
141 uid, seq, packageName.c_str(), processName.c_str(), logPath.c_str(), hitraceIdInfo.c_str(), procStatm.c_str(),
142 hostResourceWarning.c_str());
143 return watchPoint;
144 }
145
CheckForeGround(long uid,long pid,unsigned long long eventTime,std::string & foreGround)146 void FreezeDetectorPlugin::CheckForeGround(long uid, long pid, unsigned long long eventTime, std::string& foreGround)
147 {
148 if (uid < MIN_APP_UID) {
149 return;
150 }
151
152 UCollectUtil::ProcessState state = UCollectUtil::ProcessStatus::GetInstance().GetProcessState(pid);
153 if (state == UCollectUtil::FOREGROUND) {
154 foreGround = "Yes";
155 }
156 if (state == UCollectUtil::BACKGROUND) {
157 uint64_t lastFgTime = static_cast<uint64_t>(UCollectUtil::ProcessStatus::GetInstance()
158 .GetProcessLastForegroundTime(pid));
159 foreGround = (lastFgTime > eventTime) ? "Yes" : "No";
160 }
161 }
162
OnEventListeningCallback(const Event & event)163 void FreezeDetectorPlugin::OnEventListeningCallback(const Event& event)
164 {
165 if (event.rawData_ == nullptr) {
166 HIVIEW_LOGE("raw data of event is null.");
167 return;
168 }
169 EventRaw::DecodedEvent decodedEvent(event.rawData_->GetData(), event.rawData_->GetDataLength());
170 if (!decodedEvent.IsValid()) {
171 HIVIEW_LOGE("failed to decode the raw data of event.");
172 return;
173 }
174 HIVIEW_LOGD("received event id=%{public}u, domain=%{public}s, stringid=%{public}s, extraInfo=%{public}s.",
175 event.eventId_, event.domain_.c_str(), event.eventName_.c_str(), decodedEvent.AsJsonStr().c_str());
176 if (freezeCommon_ == nullptr) {
177 return;
178 }
179
180 if (!freezeCommon_->IsFreezeEvent(event.domain_, event.eventName_)) {
181 HIVIEW_LOGE("not freeze event.");
182 return;
183 }
184
185 HIVIEW_LOGD("received event domain=%{public}s, stringid=%{public}s",
186 event.domain_.c_str(), event.eventName_.c_str());
187 this->AddUseCount();
188 // dispatcher context, send task to our thread
189 WatchPoint watchPoint = MakeWatchPoint(event);
190 if (watchPoint.GetLogPath().empty()) {
191 HIVIEW_LOGW("log path is empty.");
192 return;
193 }
194
195 std::shared_ptr<FreezeRuleCluster> freezeRuleCluster = freezeCommon_->GetFreezeRuleCluster();
196 std::vector<FreezeResult> freezeResultList;
197 bool ruleRet = freezeRuleCluster->GetResult(watchPoint, freezeResultList);
198 if (!ruleRet) {
199 HIVIEW_LOGW("get rule failed.");
200 return;
201 }
202 long delayTime = freezeResultList.size() > 1 ? MULTIPLE_DELAY_TIME : SINGLE_DELAY_TIME;
203 for (auto& i : freezeResultList) {
204 long window = i.GetWindow();
205 delayTime = std::max(delayTime, window);
206 }
207 ffrt::submit([this, watchPoint] { this->ProcessEvent(watchPoint); }, {}, {},
208 ffrt::task_attr().name("dfr_fre_detec").qos(ffrt::qos_default)
209 .delay(static_cast<unsigned long long>(delayTime) * TO_NANO_SECOND_MULTPLE));
210 }
211
ProcessEvent(WatchPoint watchPoint)212 void FreezeDetectorPlugin::ProcessEvent(WatchPoint watchPoint)
213 {
214 HIVIEW_LOGD("received event domain=%{public}s, stringid=%{public}s",
215 watchPoint.GetDomain().c_str(), watchPoint.GetStringId().c_str());
216 if (freezeResolver_ == nullptr) {
217 this->SubUseCount();
218 return;
219 }
220
221 auto ret = freezeResolver_->ProcessEvent(watchPoint);
222 if (ret < 0) {
223 HIVIEW_LOGE("FreezeResolver ProcessEvent filled.");
224 }
225 this->SubUseCount();
226 }
227 } // namespace HiviewDFX
228 } // namespace OHOS
229