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