• 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 "display_power_mgr_client.h"
19 #include "faultlogger_client.h"
20 #include "file_util.h"
21 #include "freeze_json_util.h"
22 #include "logger.h"
23 #include "string_util.h"
24 #include "time_util.h"
25 
26 
27 namespace OHOS {
28 namespace HiviewDFX {
29 DEFINE_LOG_TAG("FreezeDetector");
ReduceRelevanceEvents(std::list<WatchPoint> & list,const FreezeResult & result) const30 bool Vendor::ReduceRelevanceEvents(std::list<WatchPoint>& list, const FreezeResult& result) const
31 {
32     HIVIEW_LOGI("before size=%{public}zu", list.size());
33     if (freezeCommon_ == nullptr) {
34         return false;
35     }
36     if (freezeCommon_->IsSystemResult(result) == false && freezeCommon_->IsApplicationResult(result) == false) {
37         list.clear();
38         return false;
39     }
40 
41     // erase if not system event
42     if (freezeCommon_->IsSystemResult(result)) {
43         std::list<WatchPoint>::iterator watchPoint;
44         for (watchPoint = list.begin(); watchPoint != list.end();) {
45             if (freezeCommon_->IsSystemEvent(watchPoint->GetDomain(), watchPoint->GetStringId())) {
46                 watchPoint++;
47             } else {
48                 watchPoint = list.erase(watchPoint);
49             }
50         }
51     }
52 
53     // erase if not application event
54     if (freezeCommon_->IsApplicationResult(result)) {
55         std::list<WatchPoint>::iterator watchPoint;
56         for (watchPoint = list.begin(); watchPoint != list.end();) {
57             if (freezeCommon_->IsApplicationEvent(watchPoint->GetDomain(), watchPoint->GetStringId())) {
58                 watchPoint++;
59             } else {
60                 watchPoint = list.erase(watchPoint);
61             }
62         }
63     }
64 
65     list.sort();
66     list.unique();
67     HIVIEW_LOGI("after size=%{public}zu", list.size());
68     return list.size() != 0;
69 }
70 
GetTimeString(unsigned long long timestamp) const71 std::string Vendor::GetTimeString(unsigned long long timestamp) const
72 {
73     struct tm tm;
74     time_t ts = static_cast<long long>(timestamp) / FreezeCommon::MILLISECOND; // ms
75     localtime_r(&ts, &tm);
76     char buf[TIME_STRING_LEN] = {0};
77 
78     strftime(buf, TIME_STRING_LEN - 1, "%Y%m%d%H%M%S", &tm);
79     return std::string(buf, strlen(buf));
80 }
81 
SendFaultLog(const WatchPoint & watchPoint,const std::string & logPath,const std::string & logName) const82 std::string Vendor::SendFaultLog(const WatchPoint &watchPoint, const std::string& logPath,
83     const std::string& logName) const
84 {
85     if (freezeCommon_ == nullptr) {
86         return "";
87     }
88     std::string packageName = StringUtil::TrimStr(watchPoint.GetPackageName());
89     std::string processName = StringUtil::TrimStr(watchPoint.GetProcessName());
90     std::string stringId = watchPoint.GetStringId();
91 
92     std::string type = freezeCommon_->IsApplicationEvent(watchPoint.GetDomain(), watchPoint.GetStringId()) ?
93         APPFREEZE : SYSFREEZE;
94     if (type == SYSFREEZE) {
95         processName = stringId;
96     } else if (processName == "" && packageName != "") {
97         processName = packageName;
98     }
99     if (processName == "" && packageName == "") {
100         processName = stringId;
101     }
102 
103     FaultLogInfoInner info;
104     info.time = watchPoint.GetTimestamp();
105     info.id = watchPoint.GetUid();
106     info.pid = watchPoint.GetPid();
107     info.faultLogType = freezeCommon_->IsApplicationEvent(watchPoint.GetDomain(), watchPoint.GetStringId()) ?
108         FaultLogType::APP_FREEZE : FaultLogType::SYS_FREEZE;
109     info.module = processName;
110     info.reason = stringId;
111     std::string disPlayPowerInfo = GetDisPlayPowerInfo();
112     info.summary = type + ": " + processName + " " + stringId +
113         " at " + GetTimeString(watchPoint.GetTimestamp()) + "\n";
114     info.summary += FreezeCommon::DISPLAY_POWER_INFO + disPlayPowerInfo;
115     info.logPath = logPath;
116     info.sectionMaps[FreezeCommon::HIREACE_TIME] = watchPoint.GetHitraceTime();
117     info.sectionMaps[FreezeCommon::SYSRQ_TIME] = watchPoint.GetSysrqTime();
118     AddFaultLog(info);
119     return logPath;
120 }
121 
DumpEventInfo(std::ostringstream & oss,const std::string & header,const WatchPoint & watchPoint) const122 void Vendor::DumpEventInfo(std::ostringstream& oss, const std::string& header, const WatchPoint& watchPoint) const
123 {
124     uint64_t timestamp = watchPoint.GetTimestamp() / TimeUtil::SEC_TO_MILLISEC;
125     oss << header << std::endl;
126     oss << FreezeCommon::EVENT_DOMAIN << FreezeCommon::COLON << watchPoint.GetDomain() << std::endl;
127     oss << FreezeCommon::EVENT_STRINGID << FreezeCommon::COLON << watchPoint.GetStringId() << std::endl;
128     oss << FreezeCommon::EVENT_TIMESTAMP << FreezeCommon::COLON <<
129         TimeUtil::TimestampFormatToDate(timestamp, "%Y/%m/%d-%H:%M:%S") <<
130         ":" << watchPoint.GetTimestamp() % TimeUtil::SEC_TO_MILLISEC << std::endl;
131     oss << FreezeCommon::EVENT_PID << FreezeCommon::COLON << watchPoint.GetPid() << std::endl;
132     oss << FreezeCommon::EVENT_UID << FreezeCommon::COLON << watchPoint.GetUid() << std::endl;
133     oss << FreezeCommon::EVENT_PACKAGE_NAME << FreezeCommon::COLON << watchPoint.GetPackageName() << std::endl;
134     oss << FreezeCommon::EVENT_PROCESS_NAME << FreezeCommon::COLON << watchPoint.GetProcessName() << std::endl;
135 }
136 
MergeFreezeJsonFile(const WatchPoint & watchPoint,const std::vector<WatchPoint> & list) const137 void Vendor::MergeFreezeJsonFile(const WatchPoint &watchPoint, const std::vector<WatchPoint>& list) const
138 {
139     std::ostringstream oss;
140     for (auto node : list) {
141         std::string filePath = FreezeJsonUtil::GetFilePath(node.GetPid(), node.GetUid(), node.GetTimestamp());
142         if (!FileUtil::FileExists(filePath)) {
143             continue;
144         }
145         std::ifstream ifs(filePath, std::ios::in);
146         if (ifs.is_open()) {
147             oss << ifs.rdbuf();
148             ifs.close();
149         }
150         FreezeJsonUtil::DelFile(filePath);
151     }
152 
153     std::string mergeFilePath = FreezeJsonUtil::GetFilePath(watchPoint.GetPid(),
154         watchPoint.GetUid(), watchPoint.GetTimestamp());
155     int jsonFd = FreezeJsonUtil::GetFd(mergeFilePath);
156     if (jsonFd < 0) {
157         HIVIEW_LOGE("fail to open FreezeJsonFile! jsonFd: %{public}d", jsonFd);
158         return;
159     } else {
160         HIVIEW_LOGI("success to open FreezeJsonFile! jsonFd: %{public}d", jsonFd);
161     }
162     HIVIEW_LOGI("MergeFreezeJsonFile oss size: %{public}zu.", oss.str().size());
163     FileUtil::SaveStringToFd(jsonFd, oss.str());
164     FreezeJsonUtil::WriteKeyValue(jsonFd, "domain", watchPoint.GetDomain());
165     FreezeJsonUtil::WriteKeyValue(jsonFd, "stringId", watchPoint.GetStringId());
166     FreezeJsonUtil::WriteKeyValue(jsonFd, "timestamp", watchPoint.GetTimestamp());
167     FreezeJsonUtil::WriteKeyValue(jsonFd, "pid", watchPoint.GetPid());
168     FreezeJsonUtil::WriteKeyValue(jsonFd, "uid", watchPoint.GetUid());
169     FreezeJsonUtil::WriteKeyValue(jsonFd, "package_name", watchPoint.GetPackageName());
170     FreezeJsonUtil::WriteKeyValue(jsonFd, "process_name", watchPoint.GetProcessName());
171     close(jsonFd);
172     HIVIEW_LOGI("success to merge FreezeJsonFiles!");
173 }
174 
InitLogInfo(const WatchPoint & watchPoint,std::string & type,std::string & retPath,std::string & logPath,std::string & logName) const175 void Vendor::InitLogInfo(const WatchPoint& watchPoint, std::string& type, std::string& retPath,
176     std::string& logPath, std::string& logName) const
177 {
178     std::string stringId = watchPoint.GetStringId();
179     std::string timestamp = GetTimeString(watchPoint.GetTimestamp());
180     long uid = watchPoint.GetUid();
181     std::string packageName = StringUtil::TrimStr(watchPoint.GetPackageName());
182     std::string processName = StringUtil::TrimStr(watchPoint.GetProcessName());
183 
184     type = freezeCommon_->IsApplicationEvent(watchPoint.GetDomain(), watchPoint.GetStringId()) ?
185         APPFREEZE : SYSFREEZE;
186     if (type == SYSFREEZE) {
187         processName = stringId;
188     } else if (processName == "" && packageName != "") {
189         processName = packageName;
190     }
191     if (processName == "" && packageName == "") {
192         processName = stringId;
193     }
194 
195     if (freezeCommon_->IsApplicationEvent(watchPoint.GetDomain(), watchPoint.GetStringId())) {
196         retPath = FAULT_LOGGER_PATH + APPFREEZE + HYPHEN + processName +
197             HYPHEN + std::to_string(uid) + HYPHEN + timestamp;
198         logPath = FREEZE_DETECTOR_PATH + APPFREEZE + HYPHEN + processName +
199             HYPHEN + std::to_string(uid) + HYPHEN + timestamp + POSTFIX;
200         logName = APPFREEZE + HYPHEN + processName + HYPHEN + std::to_string(uid) + HYPHEN + timestamp + POSTFIX;
201     } else {
202         retPath = FAULT_LOGGER_PATH + SYSFREEZE + HYPHEN + processName +
203             HYPHEN + std::to_string(uid) + HYPHEN + timestamp;
204         logPath = FREEZE_DETECTOR_PATH + SYSFREEZE + HYPHEN + processName +
205             HYPHEN + std::to_string(uid) + HYPHEN + timestamp + POSTFIX;
206         logName = SYSFREEZE + HYPHEN + processName + HYPHEN + std::to_string(uid) + HYPHEN + timestamp + POSTFIX;
207     }
208 }
209 
InitLogBody(const std::vector<WatchPoint> & list,std::ostringstream & body,bool & isFileExists) const210 void Vendor::InitLogBody(const std::vector<WatchPoint>& list, std::ostringstream& body,
211     bool& isFileExists) const
212 {
213     HIVIEW_LOGI("merging list size %{public}zu", list.size());
214     for (auto node : list) {
215         std::string filePath = node.GetLogPath();
216         if (filePath == "nolog" || filePath == "") {
217             HIVIEW_LOGI("only header, no content:[%{public}s, %{public}s]",
218                 node.GetDomain().c_str(), node.GetStringId().c_str());
219             DumpEventInfo(body, HEADER, node);
220             continue;
221         }
222 
223         if (FileUtil::FileExists(filePath) == false) {
224             isFileExists = false;
225             HIVIEW_LOGE("[%{public}s, %{public}s] File:%{public}s does not exist",
226                 node.GetDomain().c_str(), node.GetStringId().c_str(), filePath.c_str());
227             return;
228         }
229 
230         HIVIEW_LOGI("merging file:%{public}s.", filePath.c_str());
231 
232         std::ifstream ifs(filePath, std::ios::in);
233         if (!ifs.is_open()) {
234             HIVIEW_LOGE("cannot open log file for reading:%{public}s.", filePath.c_str());
235             DumpEventInfo(body, HEADER, node);
236             continue;
237         }
238 
239         body << HEADER << std::endl;
240         body << ifs.rdbuf();
241         ifs.close();
242     }
243 }
244 
MergeEventLog(const WatchPoint & watchPoint,const std::vector<WatchPoint> & list,const std::vector<FreezeResult> & result) const245 std::string Vendor::MergeEventLog(
246     const WatchPoint &watchPoint, const std::vector<WatchPoint>& list,
247     const std::vector<FreezeResult>& result) const
248 {
249     if (freezeCommon_ == nullptr) {
250         return "";
251     }
252 
253     std::string type;
254     std::string retPath;
255     std::string logPath;
256     std::string logName;
257     InitLogInfo(watchPoint, type, retPath, logPath, logName);
258 
259     if (FileUtil::FileExists(retPath)) {
260         HIVIEW_LOGW("filename: %{public}s is existed, direct use.", retPath.c_str());
261         return retPath;
262     }
263 
264     std::ostringstream header;
265     DumpEventInfo(header, TRIGGER_HEADER, watchPoint);
266 
267     std::ostringstream body;
268     bool isFileExists = true;
269     InitLogBody(list, body, isFileExists);
270     HIVIEW_LOGI("After Init --body size: %{public}zu.", body.str().size());
271     if (!isFileExists) {
272         HIVIEW_LOGE("Failed to open the file.");
273         return "";
274     }
275 
276     if (type == APPFREEZE) {
277         MergeFreezeJsonFile(watchPoint, list);
278     }
279 
280     int fd = logStore_->CreateLogFile(logName);
281     if (fd < 0) {
282         HIVIEW_LOGE("failed to create log file %{public}s.", logPath.c_str());
283         return "";
284     }
285 
286     FileUtil::SaveStringToFd(fd, header.str());
287     FileUtil::SaveStringToFd(fd, body.str());
288     close(fd);
289     return SendFaultLog(watchPoint, logPath, logName);
290 }
291 
Init()292 bool Vendor::Init()
293 {
294     if (freezeCommon_ == nullptr) {
295         return false;
296     }
297     logStore_ = std::make_unique<LogStoreEx>(FREEZE_DETECTOR_PATH, true);
298     logStore_->SetMaxSize(MAX_FOLDER_SIZE);
299     logStore_->SetMinKeepingFileNumber(MAX_FILE_NUM);
300     logStore_->Init();
301     return true;
302 }
303 
GetDisPlayPowerInfo() const304 std::string Vendor::GetDisPlayPowerInfo() const
305 {
306     std::string disPlayPowerInfo;
307     uint32_t brightness = OHOS::DisplayPowerMgr::DisplayPowerMgrClient::GetInstance().GetDeviceBrightness();
308     disPlayPowerInfo =  "brightness:" + StringUtil::ToString(brightness);
309 
310     OHOS::PowerMgr::PowerState powerState = OHOS::PowerMgr::PowerMgrClient::GetInstance().GetState();
311     disPlayPowerInfo += ", powerState:" + GetPowerStateString(powerState) + "\n";
312     return disPlayPowerInfo;
313 }
314 
GetPowerStateString(OHOS::PowerMgr::PowerState state)315 std::string Vendor::GetPowerStateString(OHOS::PowerMgr::PowerState state)
316 {
317     switch (state) {
318         case OHOS::PowerMgr::PowerState::AWAKE:
319             return std::string("AWAKE");
320         case OHOS::PowerMgr::PowerState::FREEZE:
321             return std::string("FREEZE");
322         case OHOS::PowerMgr::PowerState::INACTIVE:
323             return std::string("INACTIVE");
324         case OHOS::PowerMgr::PowerState::STAND_BY:
325             return std::string("STAND_BY");
326         case OHOS::PowerMgr::PowerState::DOZE:
327             return std::string("DOZE");
328         case OHOS::PowerMgr::PowerState::SLEEP:
329             return std::string("SLEEP");
330         case OHOS::PowerMgr::PowerState::HIBERNATE:
331             return std::string("HIBERNATE");
332         case OHOS::PowerMgr::PowerState::SHUTDOWN:
333             return std::string("SHUTDOWN");
334         case OHOS::PowerMgr::PowerState::UNKNOWN:
335             return std::string("UNKNOWN");
336         default:
337             break;
338     }
339     return std::string("UNKNOWN");
340 }
341 } // namespace HiviewDFX
342 } // namespace OHOS
343