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