• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "vendor.h"
17 
18 #include "faultlogger_client.h"
19 #include "file_util.h"
20 #include "freeze_json_util.h"
21 #include "hiview_logger.h"
22 #include "string_util.h"
23 #include "time_util.h"
24 #include <regex>
25 
26 namespace OHOS {
27 namespace HiviewDFX {
28 namespace {
29     static constexpr const char* const SYSWARNING = "syswarning";
30 }
31 
32 DEFINE_LOG_LABEL(0xD002D01, "FreezeDetector");
ReduceRelevanceEvents(std::list<WatchPoint> & list,const FreezeResult & result) const33 bool Vendor::ReduceRelevanceEvents(std::list<WatchPoint>& list, const FreezeResult& result) const
34 {
35     HIVIEW_LOGI("before size=%{public}zu", list.size());
36     if (freezeCommon_ == nullptr) {
37         return false;
38     }
39     if (!freezeCommon_->IsSystemResult(result) && !freezeCommon_->IsApplicationResult(result) &&
40         !freezeCommon_->IsSysWarningResult(result)) {
41         list.clear();
42         return false;
43     }
44 
45     // erase if not system event
46     if (freezeCommon_->IsSystemResult(result)) {
47         std::list<WatchPoint>::iterator watchPoint;
48         for (watchPoint = list.begin(); watchPoint != list.end();) {
49             if (freezeCommon_->IsSystemEvent(watchPoint->GetDomain(), watchPoint->GetStringId())) {
50                 watchPoint++;
51             } else {
52                 watchPoint = list.erase(watchPoint);
53             }
54         }
55     }
56 
57     // erase if not application event
58     if (freezeCommon_->IsApplicationResult(result)) {
59         std::list<WatchPoint>::iterator watchPoint;
60         for (watchPoint = list.begin(); watchPoint != list.end();) {
61             if (freezeCommon_->IsApplicationEvent(watchPoint->GetDomain(), watchPoint->GetStringId())) {
62                 watchPoint++;
63             } else {
64                 watchPoint = list.erase(watchPoint);
65             }
66         }
67     }
68 
69     // erase if not sysWarning event
70     if (freezeCommon_->IsSysWarningResult(result)) {
71         std::list<WatchPoint>::iterator watchPoint;
72         for (watchPoint = list.begin(); watchPoint != list.end();) {
73             if (freezeCommon_->IsSysWarningEvent(watchPoint->GetDomain(), watchPoint->GetStringId())) {
74                 watchPoint++;
75             } else {
76                 watchPoint = list.erase(watchPoint);
77             }
78         }
79     }
80 
81     list.sort();
82     list.unique();
83     HIVIEW_LOGI("after size=%{public}zu", list.size());
84     return list.size() != 0;
85 }
86 
GetTimeString(unsigned long long timestamp) const87 std::string Vendor::GetTimeString(unsigned long long timestamp) const
88 {
89     struct tm tm;
90     time_t ts = static_cast<long long>(timestamp) / FreezeCommon::MILLISECOND; // ms
91     localtime_r(&ts, &tm);
92     char buf[TIME_STRING_LEN] = {0};
93 
94     strftime(buf, TIME_STRING_LEN - 1, "%Y%m%d%H%M%S", &tm);
95     return std::string(buf, strlen(buf));
96 }
97 
SendFaultLog(const WatchPoint & watchPoint,const std::string & logPath,const std::string & logName) const98 std::string Vendor::SendFaultLog(const WatchPoint &watchPoint, const std::string& logPath,
99     const std::string& logName) const
100 {
101     if (freezeCommon_ == nullptr) {
102         return "";
103     }
104     std::string packageName = StringUtil::TrimStr(watchPoint.GetPackageName());
105     std::string processName = StringUtil::TrimStr(watchPoint.GetProcessName());
106     std::string stringId = watchPoint.GetStringId();
107 
108     std::string type = freezeCommon_->IsApplicationEvent(watchPoint.GetDomain(), watchPoint.GetStringId()) ?
109         APPFREEZE : (freezeCommon_->IsSystemEvent(watchPoint.GetDomain(), watchPoint.GetStringId()) ? SYSFREEZE :
110         SYSWARNING);
111     processName = processName.empty() ? (packageName.empty() ? stringId : packageName) : processName;
112     if (stringId == "SCREEN_ON") {
113         processName = stringId;
114     } else {
115         FormatProcessName(processName);
116     }
117 
118     FaultLogInfoInner info;
119     info.time = watchPoint.GetTimestamp();
120     info.id = watchPoint.GetUid();
121     info.pid = watchPoint.GetPid();
122     info.faultLogType = (type == APPFREEZE) ? FaultLogType::APP_FREEZE : ((type == SYSFREEZE) ?
123         FaultLogType::SYS_FREEZE : FaultLogType::SYS_WARNING);
124     info.module = processName;
125     info.reason = stringId;
126     std::string disPlayPowerInfo = GetDisPlayPowerInfo();
127     info.summary = type + ": " + processName + " " + stringId +
128         " at " + GetTimeString(watchPoint.GetTimestamp()) + "\n";
129     info.summary += FreezeCommon::DISPLAY_POWER_INFO + disPlayPowerInfo;
130     info.logPath = logPath;
131     info.sectionMaps[FreezeCommon::HIREACE_TIME] = watchPoint.GetHitraceTime();
132     info.sectionMaps[FreezeCommon::SYSRQ_TIME] = watchPoint.GetSysrqTime();
133     info.sectionMaps[FreezeCommon::FORE_GROUND] = watchPoint.GetForeGround();
134     AddFaultLog(info);
135     return logPath;
136 }
137 
DumpEventInfo(std::ostringstream & oss,const std::string & header,const WatchPoint & watchPoint) const138 void Vendor::DumpEventInfo(std::ostringstream& oss, const std::string& header, const WatchPoint& watchPoint) const
139 {
140     uint64_t timestamp = watchPoint.GetTimestamp() / TimeUtil::SEC_TO_MILLISEC;
141     oss << header << std::endl;
142     oss << FreezeCommon::EVENT_DOMAIN << FreezeCommon::COLON << watchPoint.GetDomain() << std::endl;
143     oss << FreezeCommon::EVENT_STRINGID << FreezeCommon::COLON << watchPoint.GetStringId() << std::endl;
144     oss << FreezeCommon::EVENT_TIMESTAMP << FreezeCommon::COLON <<
145         TimeUtil::TimestampFormatToDate(timestamp, "%Y/%m/%d-%H:%M:%S") <<
146         ":" << watchPoint.GetTimestamp() % TimeUtil::SEC_TO_MILLISEC << std::endl;
147     oss << FreezeCommon::EVENT_PID << FreezeCommon::COLON << watchPoint.GetPid() << std::endl;
148     oss << FreezeCommon::EVENT_UID << FreezeCommon::COLON << watchPoint.GetUid() << std::endl;
149     oss << FreezeCommon::EVENT_PACKAGE_NAME << FreezeCommon::COLON << watchPoint.GetPackageName() << std::endl;
150     oss << FreezeCommon::EVENT_PROCESS_NAME << FreezeCommon::COLON << watchPoint.GetProcessName() << std::endl;
151 }
152 
MergeFreezeJsonFile(const WatchPoint & watchPoint,const std::vector<WatchPoint> & list) const153 void Vendor::MergeFreezeJsonFile(const WatchPoint &watchPoint, const std::vector<WatchPoint>& list) const
154 {
155     std::ostringstream oss;
156     for (auto node : list) {
157         std::string filePath = FreezeJsonUtil::GetFilePath(node.GetPid(), node.GetUid(), node.GetTimestamp());
158         if (!FileUtil::FileExists(filePath)) {
159             continue;
160         }
161         std::string realPath;
162         if (!FileUtil::PathToRealPath(filePath, realPath)) {
163             continue;
164         }
165         std::ifstream ifs(realPath, std::ios::in);
166         if (ifs.is_open()) {
167             oss << ifs.rdbuf();
168             ifs.close();
169         }
170         FreezeJsonUtil::DelFile(realPath);
171     }
172 
173     std::string mergeFilePath = FreezeJsonUtil::GetFilePath(watchPoint.GetPid(),
174         watchPoint.GetUid(), watchPoint.GetTimestamp());
175     int jsonFd = FreezeJsonUtil::GetFd(mergeFilePath);
176     if (jsonFd < 0) {
177         HIVIEW_LOGE("fail to open FreezeJsonFile! jsonFd: %{public}d", jsonFd);
178         return;
179     } else {
180         HIVIEW_LOGI("success to open FreezeJsonFile! jsonFd: %{public}d", jsonFd);
181     }
182     HIVIEW_LOGI("MergeFreezeJsonFile oss size: %{public}zu.", oss.str().size());
183     FileUtil::SaveStringToFd(jsonFd, oss.str());
184     FreezeJsonUtil::WriteKeyValue(jsonFd, "domain", watchPoint.GetDomain());
185     FreezeJsonUtil::WriteKeyValue(jsonFd, "stringId", watchPoint.GetStringId());
186     FreezeJsonUtil::WriteKeyValue(jsonFd, "timestamp", watchPoint.GetTimestamp());
187     FreezeJsonUtil::WriteKeyValue(jsonFd, "pid", watchPoint.GetPid());
188     FreezeJsonUtil::WriteKeyValue(jsonFd, "uid", watchPoint.GetUid());
189     FreezeJsonUtil::WriteKeyValue(jsonFd, "package_name", watchPoint.GetPackageName());
190     FreezeJsonUtil::WriteKeyValue(jsonFd, "process_name", watchPoint.GetProcessName());
191     close(jsonFd);
192     HIVIEW_LOGI("success to merge FreezeJsonFiles!");
193 }
194 
FormatProcessName(std::string & processName)195 void Vendor::FormatProcessName(std::string& processName)
196 {
197     std::regex regExpress("[\\/:*?\"<>|]");
198     bool isLegal = !std::regex_search(processName, regExpress);
199     if (isLegal) {
200         return;
201     }
202     processName = std::regex_replace(processName, regExpress, "_");
203     HIVIEW_LOGD("FormatProcessName processName=%{public}s", processName.c_str());
204 }
205 
InitLogInfo(const WatchPoint & watchPoint,std::string & type,std::string & retPath,std::string & logPath,std::string & logName) const206 void Vendor::InitLogInfo(const WatchPoint& watchPoint, std::string& type, std::string& retPath,
207     std::string& logPath, std::string& logName) const
208 {
209     std::string stringId = watchPoint.GetStringId();
210     std::string timestamp = GetTimeString(watchPoint.GetTimestamp());
211     long uid = watchPoint.GetUid();
212     std::string packageName = StringUtil::TrimStr(watchPoint.GetPackageName());
213     std::string processName = StringUtil::TrimStr(watchPoint.GetProcessName());
214     type = freezeCommon_->IsApplicationEvent(watchPoint.GetDomain(), watchPoint.GetStringId()) ? APPFREEZE :
215         (freezeCommon_->IsSystemEvent(watchPoint.GetDomain(), watchPoint.GetStringId()) ? SYSFREEZE : SYSWARNING);
216     processName = processName.empty() ? (packageName.empty() ? stringId : packageName) : processName;
217     if (stringId == "SCREEN_ON") {
218         processName = stringId;
219     } else {
220         FormatProcessName(processName);
221     }
222     if (freezeCommon_->IsApplicationEvent(watchPoint.GetDomain(), watchPoint.GetStringId())) {
223         retPath = FAULT_LOGGER_PATH + APPFREEZE + HYPHEN + processName +
224             HYPHEN + std::to_string(uid) + HYPHEN + timestamp;
225         logPath = FREEZE_DETECTOR_PATH + APPFREEZE + HYPHEN + processName +
226             HYPHEN + std::to_string(uid) + HYPHEN + timestamp + POSTFIX;
227         logName = APPFREEZE + HYPHEN + processName + HYPHEN + std::to_string(uid) + HYPHEN + timestamp + POSTFIX;
228     } else if (freezeCommon_->IsSystemEvent(watchPoint.GetDomain(), watchPoint.GetStringId())) {
229         retPath = FAULT_LOGGER_PATH + SYSFREEZE + HYPHEN + processName +
230             HYPHEN + std::to_string(uid) + HYPHEN + timestamp;
231         logPath = FREEZE_DETECTOR_PATH + SYSFREEZE + HYPHEN + processName +
232             HYPHEN + std::to_string(uid) + HYPHEN + timestamp + POSTFIX;
233         logName = SYSFREEZE + HYPHEN + processName + HYPHEN + std::to_string(uid) + HYPHEN + timestamp + POSTFIX;
234     } else {
235         retPath = FAULT_LOGGER_PATH + SYSWARNING + HYPHEN + processName +
236             HYPHEN + std::to_string(uid) + HYPHEN + timestamp;
237         logPath = FREEZE_DETECTOR_PATH + SYSWARNING + HYPHEN + processName +
238             HYPHEN + std::to_string(uid) + HYPHEN + timestamp + POSTFIX;
239         logName = SYSWARNING + HYPHEN + processName + HYPHEN + std::to_string(uid) + HYPHEN + timestamp + POSTFIX;
240     }
241 }
242 
InitLogBody(const std::vector<WatchPoint> & list,std::ostringstream & body,bool & isFileExists) const243 void Vendor::InitLogBody(const std::vector<WatchPoint>& list, std::ostringstream& body,
244     bool& isFileExists) const
245 {
246     HIVIEW_LOGI("merging list size %{public}zu", list.size());
247     for (auto node : list) {
248         std::string filePath = node.GetLogPath();
249         if (filePath == "nolog" || filePath == "") {
250             HIVIEW_LOGI("only header, no content:[%{public}s, %{public}s]",
251                 node.GetDomain().c_str(), node.GetStringId().c_str());
252             DumpEventInfo(body, HEADER, node);
253             continue;
254         }
255 
256         if (FileUtil::FileExists(filePath) == false) {
257             isFileExists = false;
258             HIVIEW_LOGE("[%{public}s, %{public}s] File:%{public}s does not exist",
259                 node.GetDomain().c_str(), node.GetStringId().c_str(), filePath.c_str());
260             return;
261         }
262 
263         HIVIEW_LOGI("merging file:%{public}s.", filePath.c_str());
264         std::string realPath;
265         if (!FileUtil::PathToRealPath(filePath, realPath)) {
266             HIVIEW_LOGE("PathToRealPath Failed:%{public}s.", filePath.c_str());
267             continue;
268         }
269         std::ifstream ifs(realPath, std::ios::in);
270         if (!ifs.is_open()) {
271             HIVIEW_LOGE("cannot open log file for reading:%{public}s.", realPath.c_str());
272             DumpEventInfo(body, HEADER, node);
273             continue;
274         }
275 
276         body << HEADER << std::endl;
277         body << ifs.rdbuf();
278         ifs.close();
279     }
280 }
281 
InitLogFfrt(const WatchPoint & watchPoint,std::ostringstream & ffrt)282 void Vendor::InitLogFfrt(const WatchPoint &watchPoint, std::ostringstream& ffrt)
283 {
284     std::string ffrtPath = "/data/log/eventlog/ffrt_" + std::to_string(watchPoint.GetPid()) + "_" +
285         TimeUtil::TimestampFormatToDate(watchPoint.GetTimestamp() / TimeUtil::SEC_TO_MILLISEC, "%Y%m%d%H%M%S");
286     std::string realPath;
287     if (!FileUtil::PathToRealPath(ffrtPath, realPath)) {
288         HIVIEW_LOGE("PathToRealPath Failed:%{public}s.", ffrtPath.c_str());
289         return;
290     }
291     std::ifstream ifs(realPath, std::ios::in);
292     if (!ifs.is_open()) {
293         HIVIEW_LOGE("cannot open ffrt file for reading:%{public}s", realPath.c_str());
294         return;
295     }
296     ffrt << ifs.rdbuf();
297     ifs.close();
298     FreezeJsonUtil::DelFile(realPath);
299 }
300 
MergeEventLog(const WatchPoint & watchPoint,const std::vector<WatchPoint> & list,const std::vector<FreezeResult> & result) const301 std::string Vendor::MergeEventLog(
302     const WatchPoint &watchPoint, const std::vector<WatchPoint>& list,
303     const std::vector<FreezeResult>& result) const
304 {
305     if (freezeCommon_ == nullptr) {
306         return "";
307     }
308 
309     std::string type;
310     std::string retPath;
311     std::string logPath;
312     std::string logName;
313     InitLogInfo(watchPoint, type, retPath, logPath, logName);
314 
315     if (FileUtil::FileExists(retPath)) {
316         HIVIEW_LOGW("filename: %{public}s is existed, direct use.", retPath.c_str());
317         return retPath;
318     }
319 
320     std::ostringstream header;
321     DumpEventInfo(header, TRIGGER_HEADER, watchPoint);
322 
323     std::ostringstream body;
324     bool isFileExists = true;
325     InitLogBody(list, body, isFileExists);
326     HIVIEW_LOGI("After Init --body size: %{public}zu.", body.str().size());
327 
328     std::ostringstream ffrt;
329     if (std::any_of(result.begin(), result.end(), [](auto& res) {
330         return res.GetFfrt() == "true";
331     })) {
332         InitLogFfrt(watchPoint, ffrt);
333     }
334 
335     if (!isFileExists) {
336         HIVIEW_LOGE("Failed to open the body file.");
337         return "";
338     }
339 
340     if (type == APPFREEZE) {
341         MergeFreezeJsonFile(watchPoint, list);
342     }
343 
344     int fd = logStore_->CreateLogFile(logName);
345     if (fd < 0) {
346         HIVIEW_LOGE("failed to create log file %{public}s.", logPath.c_str());
347         return "";
348     }
349 
350     FileUtil::SaveStringToFd(fd, header.str());
351     FileUtil::SaveStringToFd(fd, body.str());
352     FileUtil::SaveStringToFd(fd, ffrt.str());
353     close(fd);
354     return SendFaultLog(watchPoint, logPath, logName);
355 }
356 
Init()357 bool Vendor::Init()
358 {
359     if (freezeCommon_ == nullptr) {
360         return false;
361     }
362     logStore_ = std::make_unique<LogStoreEx>(FREEZE_DETECTOR_PATH, true);
363     logStore_->SetMaxSize(MAX_FOLDER_SIZE);
364     logStore_->SetMinKeepingFileNumber(MAX_FILE_NUM);
365     logStore_->Init();
366     return true;
367 }
368 
GetDisPlayPowerInfo()369 std::string Vendor::GetDisPlayPowerInfo()
370 {
371     std::string disPlayPowerInfo;
372     OHOS::PowerMgr::PowerState powerState = OHOS::PowerMgr::PowerMgrClient::GetInstance().GetState();
373     disPlayPowerInfo = "powerState:" + GetPowerStateString(powerState) + "\n";
374     return disPlayPowerInfo;
375 }
376 
GetPowerStateString(OHOS::PowerMgr::PowerState state)377 std::string Vendor::GetPowerStateString(OHOS::PowerMgr::PowerState state)
378 {
379     switch (state) {
380         case OHOS::PowerMgr::PowerState::AWAKE:
381             return std::string("AWAKE");
382         case OHOS::PowerMgr::PowerState::FREEZE:
383             return std::string("FREEZE");
384         case OHOS::PowerMgr::PowerState::INACTIVE:
385             return std::string("INACTIVE");
386         case OHOS::PowerMgr::PowerState::STAND_BY:
387             return std::string("STAND_BY");
388         case OHOS::PowerMgr::PowerState::DOZE:
389             return std::string("DOZE");
390         case OHOS::PowerMgr::PowerState::SLEEP:
391             return std::string("SLEEP");
392         case OHOS::PowerMgr::PowerState::HIBERNATE:
393             return std::string("HIBERNATE");
394         case OHOS::PowerMgr::PowerState::SHUTDOWN:
395             return std::string("SHUTDOWN");
396         case OHOS::PowerMgr::PowerState::UNKNOWN:
397             return std::string("UNKNOWN");
398         default:
399             break;
400     }
401     return std::string("UNKNOWN");
402 }
403 } // namespace HiviewDFX
404 } // namespace OHOS
405