• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2024 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 #include "appfreeze_manager.h"
16 
17 #include <fcntl.h>
18 #include <sys/time.h>
19 #include <sys/wait.h>
20 #include <sys/types.h>
21 #include <sys/syscall.h>
22 #include <sys/stat.h>
23 #include <fstream>
24 
25 #include "backtrace_local.h"
26 #include "faultloggerd_client.h"
27 #include "file_ex.h"
28 #include "ffrt.h"
29 #include "dfx_dump_catcher.h"
30 #include "directory_ex.h"
31 #include "hisysevent.h"
32 #include "hitrace_meter.h"
33 #include "parameter.h"
34 #include "parameters.h"
35 #include "singleton.h"
36 
37 #include "app_mgr_client.h"
38 #include "hilog_tag_wrapper.h"
39 #include "time_util.h"
40 
41 namespace OHOS {
42 namespace AppExecFwk {
43 namespace {
44 constexpr char EVENT_UID[] = "UID";
45 constexpr char EVENT_PID[] = "PID";
46 constexpr char EVENT_TID[] = "TID";
47 constexpr char EVENT_INPUT_ID[] = "INPUT_ID";
48 constexpr char EVENT_MESSAGE[] = "MSG";
49 constexpr char EVENT_PACKAGE_NAME[] = "PACKAGE_NAME";
50 constexpr char EVENT_PROCESS_NAME[] = "PROCESS_NAME";
51 constexpr char EVENT_STACK[] = "STACK";
52 constexpr char BINDER_INFO[] = "BINDER_INFO";
53 constexpr char APP_RUNNING_UNIQUE_ID[] = "APP_RUNNING_UNIQUE_ID";
54 constexpr char FREEZE_MEMORY[] = "FREEZE_MEMORY";
55 constexpr int MAX_LAYER = 8;
56 constexpr int FREEZEMAP_SIZE_MAX = 20;
57 constexpr int FREEZE_TIME_LIMIT = 60000;
58 static constexpr uint8_t ARR_SIZE = 7;
59 static constexpr uint8_t DECIMAL = 10;
60 static constexpr uint8_t FREE_ASYNC_INDEX = 6;
61 static constexpr uint16_t FREE_ASYNC_MAX = 1000;
62 static constexpr int64_t NANOSECONDS = 1000000000;  // NANOSECONDS mean 10^9 nano second
63 static constexpr int64_t MICROSECONDS = 1000000;    // MICROSECONDS mean 10^6 millias second
64 constexpr uint64_t SEC_TO_MILLISEC = 1000;
65 constexpr uint32_t BUFFER_SIZE = 1024;
66 const std::string LOG_FILE_PATH = "data/log/eventlog";
67 static bool g_betaVersion = OHOS::system::GetParameter("const.logsystem.versiontype", "unknown") == "beta";
68 static bool g_developMode = (OHOS::system::GetParameter("persist.hiview.leak_detector", "unknown") == "enable") ||
69                             (OHOS::system::GetParameter("persist.hiview.leak_detector", "unknown") == "true");
70 }
71 std::shared_ptr<AppfreezeManager> AppfreezeManager::instance_ = nullptr;
72 ffrt::mutex AppfreezeManager::singletonMutex_;
73 ffrt::mutex AppfreezeManager::freezeMutex_;
74 ffrt::mutex AppfreezeManager::catchStackMutex_;
75 std::map<int, std::string> AppfreezeManager::catchStackMap_;
76 ffrt::mutex AppfreezeManager::freezeFilterMutex_;
77 
AppfreezeManager()78 AppfreezeManager::AppfreezeManager()
79 {
80     name_ = "AppfreezeManager" + std::to_string(AbilityRuntime::TimeUtil::CurrentTimeMillis());
81 }
82 
~AppfreezeManager()83 AppfreezeManager::~AppfreezeManager()
84 {
85 }
86 
GetInstance()87 std::shared_ptr<AppfreezeManager> AppfreezeManager::GetInstance()
88 {
89     if (instance_ == nullptr) {
90         std::lock_guard<ffrt::mutex> lock(singletonMutex_);
91         if (instance_ == nullptr) {
92             instance_ = std::make_shared<AppfreezeManager>();
93         }
94     }
95     return instance_;
96 }
97 
DestroyInstance()98 void AppfreezeManager::DestroyInstance()
99 {
100     std::lock_guard<ffrt::mutex> lock(singletonMutex_);
101     if (instance_ != nullptr) {
102         instance_.reset();
103         instance_ = nullptr;
104     }
105 }
106 
IsHandleAppfreeze(const std::string & bundleName)107 bool AppfreezeManager::IsHandleAppfreeze(const std::string& bundleName)
108 {
109     if (bundleName.empty()) {
110         return true;
111     }
112     return !DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance()->IsAttachDebug(bundleName);
113 }
114 
AppfreezeHandle(const FaultData & faultData,const AppfreezeManager::AppInfo & appInfo)115 int AppfreezeManager::AppfreezeHandle(const FaultData& faultData, const AppfreezeManager::AppInfo& appInfo)
116 {
117     TAG_LOGD(AAFwkTag::APPDFR, "called %{public}s, bundleName %{public}s, name_ %{public}s",
118         faultData.errorObject.name.c_str(), appInfo.bundleName.c_str(), name_.c_str());
119     if (!IsHandleAppfreeze(appInfo.bundleName)) {
120         return -1;
121     }
122     HITRACE_METER_FMT(HITRACE_TAG_APP, "AppfreezeHandler:%{public}s bundleName:%{public}s",
123         faultData.errorObject.name.c_str(), appInfo.bundleName.c_str());
124     std::string memoryContent = "";
125     CollectFreezeSysMemory(memoryContent);
126     if (faultData.errorObject.name == AppFreezeType::APP_INPUT_BLOCK ||
127         faultData.errorObject.name == AppFreezeType::THREAD_BLOCK_3S ||
128         faultData.errorObject.name == AppFreezeType::LIFECYCLE_HALF_TIMEOUT) {
129         AcquireStack(faultData, appInfo, memoryContent);
130     } else {
131         NotifyANR(faultData, appInfo, "", memoryContent);
132     }
133     return 0;
134 }
135 
CollectFreezeSysMemory(std::string & memoryContent)136 void AppfreezeManager::CollectFreezeSysMemory(std::string& memoryContent)
137 {
138     memoryContent = "\nGet freeze memory start time: " + AbilityRuntime::TimeUtil::DefaultCurrentTimeStr() + "\n";
139     std::string tmp = "";
140     std::string pressMemInfo = "/proc/pressure/memory";
141     OHOS::LoadStringFromFile(pressMemInfo, tmp);
142     memoryContent += tmp + "\n";
143     std::string memInfoPath = "/proc/memview";
144     if (!OHOS::FileExists(memInfoPath)) {
145         memInfoPath = "/proc/meminfo";
146     }
147     OHOS::LoadStringFromFile(memInfoPath, tmp);
148     memoryContent += tmp + "\nGet freeze memory end time: " + AbilityRuntime::TimeUtil::DefaultCurrentTimeStr();
149 }
150 
MergeNotifyInfo(FaultData & faultNotifyData,const AppfreezeManager::AppInfo & appInfo)151 int AppfreezeManager::MergeNotifyInfo(FaultData& faultNotifyData, const AppfreezeManager::AppInfo& appInfo)
152 {
153     std::string memoryContent = "";
154     CollectFreezeSysMemory(memoryContent);
155     std::string fileName = faultNotifyData.errorObject.name + "_" +
156         AbilityRuntime::TimeUtil::FormatTime("%Y%m%d%H%M%S") + "_" + std::to_string(appInfo.pid) + "_stack";
157     std::string catcherStack = "";
158     faultNotifyData.errorObject.message += "\nCatche stack trace start time: " +
159         AbilityRuntime::TimeUtil::DefaultCurrentTimeStr() + "\n";
160     if (faultNotifyData.errorObject.name == AppFreezeType::LIFECYCLE_HALF_TIMEOUT
161         || faultNotifyData.errorObject.name == AppFreezeType::LIFECYCLE_TIMEOUT) {
162         catcherStack += CatcherStacktrace(appInfo.pid, faultNotifyData.errorObject.stack);
163     } else {
164         catcherStack += CatchJsonStacktrace(appInfo.pid, faultNotifyData.errorObject.name,
165             faultNotifyData.errorObject.stack);
166     }
167     std::string timeStamp = "Catche stack trace end time: " + AbilityRuntime::TimeUtil::DefaultCurrentTimeStr();
168     faultNotifyData.errorObject.stack = WriteToFile(fileName, catcherStack);
169     if (appInfo.isOccurException) {
170         faultNotifyData.errorObject.message += "\nnotifyAppFault exception.\n";
171     }
172     faultNotifyData.errorObject.message += timeStamp;
173     if (faultNotifyData.errorObject.name == AppFreezeType::APP_INPUT_BLOCK ||
174         faultNotifyData.errorObject.name == AppFreezeType::THREAD_BLOCK_3S ||
175         faultNotifyData.errorObject.name == AppFreezeType::LIFECYCLE_HALF_TIMEOUT) {
176         AcquireStack(faultNotifyData, appInfo, memoryContent);
177     } else {
178         NotifyANR(faultNotifyData, appInfo, "", memoryContent);
179     }
180     return 0;
181 }
182 
AppfreezeHandleWithStack(const FaultData & faultData,const AppfreezeManager::AppInfo & appInfo)183 int AppfreezeManager::AppfreezeHandleWithStack(const FaultData& faultData, const AppfreezeManager::AppInfo& appInfo)
184 {
185     TAG_LOGW(AAFwkTag::APPDFR, "NotifyAppFaultTask called, eventName:%{public}s, bundleName:%{public}s, "
186         "name_:%{public}s, currentTime:%{public}s", faultData.errorObject.name.c_str(), appInfo.bundleName.c_str(),
187         name_.c_str(), AbilityRuntime::TimeUtil::DefaultCurrentTimeStr().c_str());
188     if (!IsHandleAppfreeze(appInfo.bundleName)) {
189         return -1;
190     }
191     FaultData faultNotifyData;
192     faultNotifyData.errorObject.name = faultData.errorObject.name;
193     faultNotifyData.errorObject.message = faultData.errorObject.message;
194     faultNotifyData.errorObject.stack = faultData.errorObject.stack;
195     faultNotifyData.faultType = FaultDataType::APP_FREEZE;
196     faultNotifyData.eventId = faultData.eventId;
197     faultNotifyData.tid = faultData.tid;
198 
199     HITRACE_METER_FMT(HITRACE_TAG_APP, "AppfreezeHandleWithStack pid:%d-name:%s",
200         appInfo.pid, faultData.errorObject.name.c_str());
201     return MergeNotifyInfo(faultNotifyData, appInfo);
202 }
203 
WriteToFile(const std::string & fileName,std::string & content)204 std::string AppfreezeManager::WriteToFile(const std::string& fileName, std::string& content)
205 {
206     std::string dir_path = LOG_FILE_PATH + "/freeze";
207     constexpr mode_t defaultLogDirMode = 0770;
208     if (!OHOS::FileExists(dir_path)) {
209         OHOS::ForceCreateDirectory(dir_path);
210         OHOS::ChangeModeDirectory(dir_path, defaultLogDirMode);
211     }
212     std::string realPath;
213     if (!OHOS::PathToRealPath(dir_path, realPath)) {
214         TAG_LOGE(AAFwkTag::APPDFR, "pathToRealPath failed:%{public}s", dir_path.c_str());
215         return "";
216     }
217     std::string stackPath = realPath + "/" + fileName;
218     constexpr mode_t defaultLogFileMode = 0644;
219     FILE* fp = fopen(stackPath.c_str(), "w+");
220     chmod(stackPath.c_str(), defaultLogFileMode);
221     if (fp == nullptr) {
222         TAG_LOGI(AAFwkTag::APPDFR, "stackPath create failed, errno: %{public}d", errno);
223         return "";
224     } else {
225         TAG_LOGI(AAFwkTag::APPDFR, "stackPath: %{public}s", stackPath.c_str());
226     }
227     OHOS::SaveStringToFile(stackPath, content, true);
228     (void)fclose(fp);
229     return stackPath;
230 }
231 
LifecycleTimeoutHandle(const ParamInfo & info,FreezeUtil::LifecycleFlow flow)232 int AppfreezeManager::LifecycleTimeoutHandle(const ParamInfo& info, FreezeUtil::LifecycleFlow flow)
233 {
234     if (info.typeId != AppfreezeManager::TypeAttribute::CRITICAL_TIMEOUT) {
235         return -1;
236     }
237     if (!IsHandleAppfreeze(info.bundleName)) {
238         return -1;
239     }
240     if (info.eventName != AppFreezeType::LIFECYCLE_TIMEOUT &&
241         info.eventName != AppFreezeType::LIFECYCLE_HALF_TIMEOUT) {
242         return -1;
243     }
244     TAG_LOGD(AAFwkTag::APPDFR, "called %{public}s, name_ %{public}s", info.bundleName.c_str(),
245         name_.c_str());
246     HITRACE_METER_FMT(HITRACE_TAG_APP, "LifecycleTimeoutHandle:%{public}s bundleName:%{public}s",
247         info.eventName.c_str(), info.bundleName.c_str());
248     AppFaultDataBySA faultDataSA;
249     faultDataSA.errorObject.name = info.eventName;
250     faultDataSA.errorObject.message = info.msg;
251     faultDataSA.errorObject.stack = "\nDump tid stack start time:" +
252         AbilityRuntime::TimeUtil::DefaultCurrentTimeStr() + "\n";
253     std::string stack = "";
254     if (!HiviewDFX::GetBacktraceStringByTidWithMix(stack, info.pid, 0, true)) {
255         stack = "Failed to dump stacktrace for " + stack;
256     }
257     faultDataSA.errorObject.stack += stack + "\nDump tid stack end time:" +
258         AbilityRuntime::TimeUtil::DefaultCurrentTimeStr() + "\n";
259     faultDataSA.faultType = FaultDataType::APP_FREEZE;
260     faultDataSA.timeoutMarkers = "notifyFault" +
261                                  std::to_string(info.pid) +
262                                  "-" + std::to_string(AbilityRuntime::TimeUtil::CurrentTimeMillis());
263     faultDataSA.pid = info.pid;
264     if (flow.state != AbilityRuntime::FreezeUtil::TimeoutState::UNKNOWN) {
265         faultDataSA.token = flow.token;
266         faultDataSA.state = static_cast<uint32_t>(flow.state);
267     }
268     DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance()->NotifyAppFaultBySA(faultDataSA);
269     return 0;
270 }
271 
AcquireStack(const FaultData & faultData,const AppfreezeManager::AppInfo & appInfo,const std::string & memoryContent)272 int AppfreezeManager::AcquireStack(const FaultData& faultData,
273     const AppfreezeManager::AppInfo& appInfo, const std::string& memoryContent)
274 {
275     int ret = 0;
276     int pid = appInfo.pid;
277     FaultData faultNotifyData;
278     faultNotifyData.errorObject.name = faultData.errorObject.name;
279     faultNotifyData.errorObject.message = faultData.errorObject.message;
280     faultNotifyData.errorObject.stack = faultData.errorObject.stack;
281     faultNotifyData.faultType = FaultDataType::APP_FREEZE;
282     faultNotifyData.eventId = faultData.eventId;
283     std::string binderInfo;
284     std::string binderPidsStr;
285     std::string terminalBinderTid;
286     AppfreezeManager::TerminalBinder terminalBinder = {0, 0, false};
287     std::set<int> asyncPids;
288     std::set<int> syncPids = GetBinderPeerPids(binderInfo, pid, asyncPids, terminalBinder);
289     if (syncPids.empty()) {
290         binderInfo +="PeerBinder pids is empty\n";
291     }
292     for (auto& pidTemp : syncPids) {
293         TAG_LOGI(AAFwkTag::APPDFR, "PeerBinder pidTemp pids:%{public}d", pidTemp);
294         if (pidTemp == pid) {
295             continue;
296         }
297         std::string content = "Binder catcher stacktrace, type is peer, pid : " + std::to_string(pidTemp) + "\n";
298         content += CatcherStacktrace(pidTemp, "");
299         binderPidsStr += " " + std::to_string(pidTemp);
300         if (terminalBinder.pid > 0 && pidTemp == terminalBinder.pid) {
301             terminalBinder.tid  = (terminalBinder.tid > 0) ? terminalBinder.tid : terminalBinder.pid;
302             content = "Binder catcher stacktrace, terminal binder tag\n" + content +
303                 "Binder catcher stacktrace, terminal binder tag\n";
304             terminalBinderTid = std::to_string(terminalBinder.tid);
305         }
306         binderInfo += content;
307     }
308     for (auto& pidTemp : asyncPids) {
309         TAG_LOGI(AAFwkTag::APPDFR, "AsyncBinder pidTemp pids:%{public}d", pidTemp);
310         if (pidTemp != pid && syncPids.find(pidTemp) == syncPids.end()) {
311             std::string content = "Binder catcher stacktrace, type is async, pid : " + std::to_string(pidTemp) + "\n";
312             content += CatcherStacktrace(pidTemp, "");
313             binderInfo += content;
314         }
315     }
316 
317     std::string fileName = faultData.errorObject.name + "_" +
318         AbilityRuntime::TimeUtil::FormatTime("%Y%m%d%H%M%S") + "_" + std::to_string(appInfo.pid) + "_binder";
319     std::string fullStackPath = WriteToFile(fileName, binderInfo);
320     binderInfo = fullStackPath + "," + binderPidsStr + "," + terminalBinderTid;
321 
322     ret = NotifyANR(faultNotifyData, appInfo, binderInfo, memoryContent);
323     return ret;
324 }
325 
NotifyANR(const FaultData & faultData,const AppfreezeManager::AppInfo & appInfo,const std::string & binderInfo,const std::string & memoryContent)326 int AppfreezeManager::NotifyANR(const FaultData& faultData, const AppfreezeManager::AppInfo& appInfo,
327     const std::string& binderInfo, const std::string& memoryContent)
328 {
329     std::string appRunningUniqueId = "";
330     DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance()->GetAppRunningUniqueIdByPid(appInfo.pid,
331         appRunningUniqueId);
332     int ret = 0;
333     int64_t startTime = AbilityRuntime::TimeUtil::CurrentTimeMillis();
334     if (faultData.errorObject.name == AppFreezeType::APP_INPUT_BLOCK) {
335         ret = HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::AAFWK, faultData.errorObject.name,
336             OHOS::HiviewDFX::HiSysEvent::EventType::FAULT, EVENT_UID, appInfo.uid, EVENT_PID, appInfo.pid,
337             EVENT_PACKAGE_NAME, appInfo.bundleName, EVENT_PROCESS_NAME, appInfo.processName, EVENT_MESSAGE,
338             faultData.errorObject.message, EVENT_STACK, faultData.errorObject.stack, BINDER_INFO, binderInfo,
339             APP_RUNNING_UNIQUE_ID, appRunningUniqueId, EVENT_INPUT_ID, faultData.eventId,
340             FREEZE_MEMORY, memoryContent);
341     } else {
342         ret = HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::AAFWK, faultData.errorObject.name,
343             OHOS::HiviewDFX::HiSysEvent::EventType::FAULT, EVENT_UID, appInfo.uid, EVENT_PID, appInfo.pid,
344             EVENT_TID, faultData.tid,
345             EVENT_PACKAGE_NAME, appInfo.bundleName, EVENT_PROCESS_NAME, appInfo.processName, EVENT_MESSAGE,
346             faultData.errorObject.message, EVENT_STACK, faultData.errorObject.stack, BINDER_INFO, binderInfo,
347             APP_RUNNING_UNIQUE_ID, appRunningUniqueId, FREEZE_MEMORY, memoryContent);
348     }
349     TAG_LOGW(AAFwkTag::APPDFR,
350         "reportEvent:%{public}s, pid:%{public}d, tid:%{public}d, bundleName:%{public}s, appRunningUniqueId:%{public}s"
351         ", endTime:%{public}s, interval:%{public}" PRId64 " ms, eventId:%{public}d hisysevent write ret: %{public}d",
352         faultData.errorObject.name.c_str(), appInfo.pid, faultData.tid, appInfo.bundleName.c_str(),
353         appRunningUniqueId.c_str(), AbilityRuntime::TimeUtil::DefaultCurrentTimeStr().c_str(),
354         AbilityRuntime::TimeUtil::CurrentTimeMillis() - startTime, faultData.eventId, ret);
355     return 0;
356 }
357 
BinderParser(std::ifstream & fin,std::string & stack,std::set<int> & asyncPids) const358 std::map<int, std::list<AppfreezeManager::PeerBinderInfo>> AppfreezeManager::BinderParser(std::ifstream& fin,
359     std::string& stack, std::set<int>& asyncPids) const
360 {
361     std::map<uint32_t, uint32_t> asyncBinderMap;
362     std::vector<std::pair<uint32_t, uint64_t>> freeAsyncSpacePairs;
363     std::map<int, std::list<AppfreezeManager::PeerBinderInfo>> binderInfos = BinderLineParser(fin, stack,
364         asyncBinderMap, freeAsyncSpacePairs);
365 
366     std::sort(freeAsyncSpacePairs.begin(), freeAsyncSpacePairs.end(),
367         [] (const auto& pairOne, const auto& pairTwo) { return pairOne.second < pairTwo.second; });
368     std::vector<std::pair<uint32_t, uint32_t>> asyncBinderPairs(asyncBinderMap.begin(), asyncBinderMap.end());
369     std::sort(asyncBinderPairs.begin(), asyncBinderPairs.end(),
370         [] (const auto& pairOne, const auto& pairTwo) { return pairOne.second > pairTwo.second; });
371 
372     size_t freeAsyncSpaceSize = freeAsyncSpacePairs.size();
373     size_t asyncBinderSize = asyncBinderPairs.size();
374     size_t individualMaxSize = 2;
375     for (size_t i = 0; i < individualMaxSize; i++) {
376         if (i < freeAsyncSpaceSize) {
377             asyncPids.insert(freeAsyncSpacePairs[i].first);
378         }
379         if (i < asyncBinderSize) {
380             asyncPids.insert(asyncBinderPairs[i].first);
381         }
382     }
383 
384     return binderInfos;
385 }
386 
BinderLineParser(std::ifstream & fin,std::string & stack,std::map<uint32_t,uint32_t> & asyncBinderMap,std::vector<std::pair<uint32_t,uint64_t>> & freeAsyncSpacePairs) const387 std::map<int, std::list<AppfreezeManager::PeerBinderInfo>> AppfreezeManager::BinderLineParser(std::ifstream& fin,
388     std::string& stack, std::map<uint32_t, uint32_t>& asyncBinderMap,
389     std::vector<std::pair<uint32_t, uint64_t>>& freeAsyncSpacePairs) const
390 {
391     std::map<int, std::list<AppfreezeManager::PeerBinderInfo>> binderInfos;
392     std::string line;
393     bool isBinderMatchup = false;
394     TAG_LOGI(AAFwkTag::APPDFR, "start");
395     stack += "BinderCatcher --\n\n";
396     while (getline(fin, line)) {
397         stack += line + "\n";
398         isBinderMatchup = (!isBinderMatchup && line.find("free_async_space") != line.npos) ? true : isBinderMatchup;
399         std::vector<std::string> strList = GetFileToList(line);
400 
401         auto strSplit = [](const std::string& str, uint16_t index) -> std::string {
402             std::vector<std::string> strings;
403             SplitStr(str, ":", strings);
404             return index < strings.size() ? strings[index] : "";
405         };
406 
407         if (isBinderMatchup) {
408             if (line.find("free_async_space") == line.npos && strList.size() == ARR_SIZE &&
409                 std::atoll(strList[FREE_ASYNC_INDEX].c_str()) < FREE_ASYNC_MAX) {
410                 freeAsyncSpacePairs.emplace_back(
411                     std::atoi(strList[0].c_str()),
412                     std::atoll(strList[FREE_ASYNC_INDEX].c_str()));
413             }
414         } else if (line.find("async\t") != std::string::npos && strList.size() > ARR_SIZE) {
415             std::string serverPid = strSplit(strList[3], 0);
416             std::string serverTid = strSplit(strList[3], 1);
417             if (serverPid != "" && serverTid != "" && std::atoi(serverTid.c_str()) == 0) {
418                 asyncBinderMap[std::atoi(serverPid.c_str())]++;
419             }
420         } else if (strList.size() >= ARR_SIZE) { // 7: valid array size
421             AppfreezeManager::PeerBinderInfo info = {0};
422             // 0: local id,
423             std::string clientPid = strSplit(strList[0], 0);
424             std::string clientTid = strSplit(strList[0], 1);
425             // 2: peer id,
426             std::string serverPid = strSplit(strList[2], 0);
427             std::string serverTid = strSplit(strList[2], 1);
428              // 5: wait time, s
429             std::string wait = strSplit(strList[5], 1);
430             if (clientPid == "" || clientTid == "" || serverPid == "" || serverTid == "" || wait == "") {
431                 continue;
432             }
433             info = {std::strtol(clientPid.c_str(), nullptr, DECIMAL), std::strtol(clientTid.c_str(), nullptr, DECIMAL),
434                     std::strtol(serverPid.c_str(), nullptr, DECIMAL), strtol(serverTid.c_str(), nullptr, DECIMAL)};
435             int waitTime = std::strtol(wait.c_str(), nullptr, DECIMAL);
436             TAG_LOGI(AAFwkTag::APPDFR, "server:%{public}d, client:%{public}d, wait:%{public}d", info.serverPid,
437                 info.clientPid, waitTime);
438             binderInfos[info.clientPid].push_back(info);
439         }
440     }
441     TAG_LOGI(AAFwkTag::APPDFR, "binderInfos size: %{public}zu", binderInfos.size());
442     return binderInfos;
443 }
444 
GetFileToList(std::string line) const445 std::vector<std::string> AppfreezeManager::GetFileToList(std::string line) const
446 {
447     std::vector<std::string> strList;
448     std::istringstream lineStream(line);
449     std::string tmpstr;
450     while (lineStream >> tmpstr) {
451         strList.push_back(tmpstr);
452     }
453     TAG_LOGD(AAFwkTag::APPDFR, "strList size: %{public}zu", strList.size());
454     return strList;
455 }
456 
GetBinderPeerPids(std::string & stack,int pid,std::set<int> & asyncPids,AppfreezeManager::TerminalBinder & terminalBinder) const457 std::set<int> AppfreezeManager::GetBinderPeerPids(std::string& stack, int pid, std::set<int>& asyncPids,
458     AppfreezeManager::TerminalBinder& terminalBinder) const
459 {
460     std::set<int> pids;
461     std::ifstream fin;
462     std::string path = LOGGER_DEBUG_PROC_PATH;
463     char resolvePath[PATH_MAX] = {0};
464     if (realpath(path.c_str(), resolvePath) == nullptr) {
465         TAG_LOGE(AAFwkTag::APPDFR, "invalid realpath");
466         return pids;
467     }
468     fin.open(resolvePath);
469     if (!fin.is_open()) {
470         TAG_LOGE(AAFwkTag::APPDFR, "open failed, %{public}s", resolvePath);
471         stack += "open file failed :" + path + "\r\n";
472         return pids;
473     }
474 
475     stack += "\n\nPeerBinderCatcher -- pid==" + std::to_string(pid) + "\n\n";
476     std::map<int, std::list<AppfreezeManager::PeerBinderInfo>> binderInfos = BinderParser(fin, stack, asyncPids);
477     fin.close();
478 
479     if (binderInfos.size() == 0 || binderInfos.find(pid) == binderInfos.end()) {
480         return pids;
481     }
482 
483     ParseBinderPids(binderInfos, pids, pid, 0, terminalBinder);
484     for (auto& each : pids) {
485         TAG_LOGD(AAFwkTag::APPDFR, "each pids:%{public}d", each);
486     }
487     return pids;
488 }
489 
ParseBinderPids(const std::map<int,std::list<AppfreezeManager::PeerBinderInfo>> & binderInfos,std::set<int> & pids,int pid,int layer,AppfreezeManager::TerminalBinder & terminalBinder) const490 void AppfreezeManager::ParseBinderPids(const std::map<int, std::list<AppfreezeManager::PeerBinderInfo>>& binderInfos,
491     std::set<int>& pids, int pid, int layer, AppfreezeManager::TerminalBinder& terminalBinder) const
492 {
493     auto it = binderInfos.find(pid);
494     layer++;
495     if (layer >= MAX_LAYER || it == binderInfos.end()) {
496         return;
497     }
498 
499     bool isGetLayerBinder = false;
500     for (auto& each : it->second) {
501         if (!terminalBinder.firstLayerInit || (!isGetLayerBinder && each.clientPid == terminalBinder.pid &&
502             each.clientTid == terminalBinder.tid)) {
503             terminalBinder.pid = each.serverPid;
504             terminalBinder.tid = each.serverTid;
505             terminalBinder.firstLayerInit = true;
506             isGetLayerBinder = true;
507         }
508         pids.insert(each.serverPid);
509         ParseBinderPids(binderInfos, pids, each.serverPid, layer, terminalBinder);
510     }
511 }
512 
DeleteStack(int pid)513 void AppfreezeManager::DeleteStack(int pid)
514 {
515     std::lock_guard<ffrt::mutex> lock(catchStackMutex_);
516     auto it = catchStackMap_.find(pid);
517     if (it != catchStackMap_.end()) {
518         catchStackMap_.erase(it);
519     }
520 }
521 
FindStackByPid(std::string & ret,int pid) const522 void AppfreezeManager::FindStackByPid(std::string& ret, int pid) const
523 {
524     std::lock_guard<ffrt::mutex> lock(catchStackMutex_);
525     auto it = catchStackMap_.find(pid);
526     if (it != catchStackMap_.end()) {
527         ret = it->second;
528     }
529 }
530 
CatchJsonStacktrace(int pid,const std::string & faultType,const std::string & stack) const531 std::string AppfreezeManager::CatchJsonStacktrace(int pid, const std::string& faultType,
532     const std::string& stack) const
533 {
534     HITRACE_METER_FMT(HITRACE_TAG_APP, "CatchJsonStacktrace pid:%d", pid);
535     HiviewDFX::DfxDumpCatcher dumplog;
536     std::string msg;
537     size_t defaultMaxFaultNum = 256;
538     if (dumplog.DumpCatchProcess(pid, msg, defaultMaxFaultNum, true) == -1) {
539         TAG_LOGI(AAFwkTag::APPDFR, "appfreeze catch stack failed");
540         msg = "Failed to dump stacktrace for " + std::to_string(pid) + "\n" + msg +
541             "\nMain thread stack:" + stack;
542         if (faultType == AppFreezeType::APP_INPUT_BLOCK) {
543             FindStackByPid(msg, pid);
544         }
545     } else {
546         if (faultType == AppFreezeType::THREAD_BLOCK_3S) {
547             std::lock_guard<ffrt::mutex> lock(catchStackMutex_);
548             catchStackMap_[pid] = msg;
549         }
550     }
551     return msg;
552 }
553 
CatcherStacktrace(int pid,const std::string & stack) const554 std::string AppfreezeManager::CatcherStacktrace(int pid, const std::string& stack) const
555 {
556     HITRACE_METER_FMT(HITRACE_TAG_APP, "CatcherStacktrace pid:%d", pid);
557     HiviewDFX::DfxDumpCatcher dumplog;
558     std::string msg;
559     if (dumplog.DumpCatchProcess(pid, msg) == -1) {
560         msg = "Failed to dump stacktrace for " + std::to_string(pid) + "\n" + msg +
561             "\nMain thread stack:" + stack;
562     }
563     return msg;
564 }
565 
IsProcessDebug(int32_t pid,std::string bundleName)566 bool AppfreezeManager::IsProcessDebug(int32_t pid, std::string bundleName)
567 {
568     std::lock_guard<ffrt::mutex> lock(freezeFilterMutex_);
569     auto it = appfreezeFilterMap_.find(bundleName);
570     if (it != appfreezeFilterMap_.end() && it->second.pid == pid) {
571         if (g_betaVersion || g_developMode) {
572             TAG_LOGI(AAFwkTag::APPDFR, "filtration current device is beta or development do not report appfreeze");
573             return true;
574         }
575         if (it->second.state == AppFreezeState::APPFREEZE_STATE_CANCELED) {
576             TAG_LOGI(AAFwkTag::APPDFR, "filtration only once");
577             return false;
578         } else {
579             TAG_LOGI(AAFwkTag::APPDFR, "filtration %{public}s", bundleName.c_str());
580             return true;
581         }
582     }
583 
584     const int buffSize = 128;
585     char paramBundle[buffSize] = {0};
586     GetParameter("hiviewdfx.appfreeze.filter_bundle_name", "", paramBundle, buffSize - 1);
587     std::string debugBundle(paramBundle);
588 
589     if (bundleName.compare(debugBundle) == 0) {
590         TAG_LOGI(AAFwkTag::APPDFR, "filtration %{public}s_%{public}s not exit",
591             debugBundle.c_str(), bundleName.c_str());
592         return true;
593     }
594     return false;
595 }
596 
GetFreezeCurrentTime()597 int64_t AppfreezeManager::GetFreezeCurrentTime()
598 {
599     struct timespec t;
600     t.tv_sec = 0;
601     t.tv_nsec = 0;
602     clock_gettime(CLOCK_MONOTONIC, &t);
603     return static_cast<int64_t>(((t.tv_sec) * NANOSECONDS + t.tv_nsec) / MICROSECONDS);
604 }
605 
SetFreezeState(int32_t pid,int state,const std::string & errorName)606 void AppfreezeManager::SetFreezeState(int32_t pid, int state, const std::string& errorName)
607 {
608     std::lock_guard<ffrt::mutex> lock(freezeMutex_);
609     if (appfreezeInfo_.find(pid) != appfreezeInfo_.end()) {
610         appfreezeInfo_[pid].state = state;
611         appfreezeInfo_[pid].occurTime = GetFreezeCurrentTime();
612     } else {
613         AppFreezeInfo info;
614         info.pid = pid;
615         info.state = state;
616         info.occurTime = GetFreezeCurrentTime();
617         info.errorName = errorName;
618         appfreezeInfo_.emplace(pid, info);
619     }
620 }
621 
GetFreezeState(int32_t pid)622 int AppfreezeManager::GetFreezeState(int32_t pid)
623 {
624     std::lock_guard<ffrt::mutex> lock(freezeMutex_);
625     auto it = appfreezeInfo_.find(pid);
626     if (it != appfreezeInfo_.end()) {
627         return it->second.state;
628     }
629     return AppFreezeState::APPFREEZE_STATE_IDLE;
630 }
631 
GetFreezeTime(int32_t pid)632 int64_t AppfreezeManager::GetFreezeTime(int32_t pid)
633 {
634     std::lock_guard<ffrt::mutex> lock(freezeMutex_);
635     auto it = appfreezeInfo_.find(pid);
636     if (it != appfreezeInfo_.end()) {
637         return it->second.occurTime;
638     }
639     return 0;
640 }
641 
ClearOldInfo()642 void AppfreezeManager::ClearOldInfo()
643 {
644     std::lock_guard<ffrt::mutex> lock(freezeMutex_);
645     int64_t currentTime = GetFreezeCurrentTime();
646     for (auto it = appfreezeInfo_.begin(); it != appfreezeInfo_.end();) {
647         auto diff = currentTime - it->second.occurTime;
648         if (diff > FREEZE_TIME_LIMIT) {
649             it = appfreezeInfo_.erase(it);
650         } else {
651             ++it;
652         }
653     }
654 }
655 
IsNeedIgnoreFreezeEvent(int32_t pid,const std::string & errorName)656 bool AppfreezeManager::IsNeedIgnoreFreezeEvent(int32_t pid, const std::string& errorName)
657 {
658     if (appfreezeInfo_.size() >= FREEZEMAP_SIZE_MAX) {
659         ClearOldInfo();
660     }
661     int state = GetFreezeState(pid);
662     int64_t currentTime = GetFreezeCurrentTime();
663     int64_t lastTime = GetFreezeTime(pid);
664     auto diff = currentTime - lastTime;
665     if (state == AppFreezeState::APPFREEZE_STATE_FREEZE) {
666         if (diff >= FREEZE_TIME_LIMIT) {
667             TAG_LOGI(AAFwkTag::APPDFR, "durationTime: "
668                 "%{public}" PRId64 "state: %{public}d", diff, state);
669             return false;
670         }
671         return true;
672     } else {
673         if (errorName == "THREAD_BLOCK_3S") {
674             return false;
675         }
676         SetFreezeState(pid, AppFreezeState::APPFREEZE_STATE_FREEZE, errorName);
677         TAG_LOGI(AAFwkTag::APPDFR, "durationTime: %{public}" PRId64 ", SetFreezeState: "
678             "%{public}s", diff, errorName.c_str());
679         return false;
680     }
681 }
682 
CancelAppFreezeDetect(int32_t pid,const std::string & bundleName)683 bool AppfreezeManager::CancelAppFreezeDetect(int32_t pid, const std::string& bundleName)
684 {
685     if (bundleName.empty()) {
686         TAG_LOGE(AAFwkTag::APPDFR, "SetAppFreezeFilter bundleName is empty.");
687         return false;
688     }
689     std::lock_guard<ffrt::mutex> lock(freezeFilterMutex_);
690     AppFreezeInfo info;
691     info.pid = pid;
692     info.state = AppFreezeState::APPFREEZE_STATE_CANCELING;
693     appfreezeFilterMap_.emplace(bundleName, info);
694     return true;
695 }
696 
RemoveDeathProcess(std::string bundleName)697 void AppfreezeManager::RemoveDeathProcess(std::string bundleName)
698 {
699     std::lock_guard<ffrt::mutex> lock(freezeFilterMutex_);
700     auto it = appfreezeFilterMap_.find(bundleName);
701     if (it != appfreezeFilterMap_.end()) {
702         TAG_LOGI(AAFwkTag::APPDFR, "Remove bundleName: %{public}s", bundleName.c_str());
703         appfreezeFilterMap_.erase(it);
704     }
705 }
706 
ResetAppfreezeState(int32_t pid,const std::string & bundleName)707 void AppfreezeManager::ResetAppfreezeState(int32_t pid, const std::string& bundleName)
708 {
709     std::lock_guard<ffrt::mutex> lock(freezeFilterMutex_);
710     if (appfreezeFilterMap_.find(bundleName) != appfreezeFilterMap_.end()) {
711         TAG_LOGD(AAFwkTag::APPDFR, "bundleName: %{public}s",
712             bundleName.c_str());
713         appfreezeFilterMap_[bundleName].state = AppFreezeState::APPFREEZE_STATE_CANCELED;
714     }
715 }
716 
IsValidFreezeFilter(int32_t pid,const std::string & bundleName)717 bool AppfreezeManager::IsValidFreezeFilter(int32_t pid, const std::string& bundleName)
718 {
719     if (g_betaVersion || g_developMode) {
720         TAG_LOGI(AAFwkTag::APPDFR, "current device is beta or development do not report appfreeze");
721         return true;
722     }
723     std::lock_guard<ffrt::mutex> lock(freezeFilterMutex_);
724     if (appfreezeFilterMap_.find(bundleName) != appfreezeFilterMap_.end()) {
725         return false;
726     }
727     return true;
728 }
729 }  // namespace AAFwk
730 }  // namespace OHOS