• 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_inner.h"
16 
17 #include <sys/time.h>
18 
19 #include "ability_manager_client.h"
20 #include "ability_state.h"
21 #include "appfreeze_manager.h"
22 #include "app_recovery.h"
23 #include "backtrace_local.h"
24 #include "exit_reason.h"
25 #include "ffrt.h"
26 #include "freeze_util.h"
27 #include "hilog_tag_wrapper.h"
28 #include "hitrace_meter.h"
29 #include "hisysevent.h"
30 #include "parameter.h"
31 #include "xcollie/watchdog.h"
32 #include "time_util.h"
33 #include "parameters.h"
34 
35 namespace OHOS {
36 using AbilityRuntime::FreezeUtil;
37 namespace AppExecFwk {
38 namespace {
39 constexpr char EVENT_UID[] = "UID";
40 constexpr char EVENT_PID[] = "PID";
41 constexpr char EVENT_MESSAGE[] = "MSG";
42 constexpr char EVENT_PACKAGE_NAME[] = "PACKAGE_NAME";
43 constexpr char EVENT_PROCESS_NAME[] = "PROCESS_NAME";
44 constexpr char EVENT_STACK[] = "STACK";
45 constexpr int32_t HALF_DURATION = 3000;
46 constexpr int32_t HALF_INTERVAL = 300;
47 const bool BETA_VERSION = OHOS::system::GetParameter("const.logsystem.versiontype", "unknown") == "beta";
48 }
49 std::weak_ptr<EventHandler> AppfreezeInner::appMainHandler_;
50 std::shared_ptr<AppfreezeInner> AppfreezeInner::instance_ = nullptr;
51 std::mutex AppfreezeInner::singletonMutex_;
52 
AppfreezeInner()53 AppfreezeInner::AppfreezeInner()
54 {}
55 
~AppfreezeInner()56 AppfreezeInner::~AppfreezeInner()
57 {}
58 
SetMainHandler(const std::shared_ptr<EventHandler> & eventHandler)59 void AppfreezeInner::SetMainHandler(const std::shared_ptr<EventHandler>& eventHandler)
60 {
61     appMainHandler_ = eventHandler;
62 }
63 
SetApplicationInfo(const std::shared_ptr<ApplicationInfo> & applicationInfo)64 void AppfreezeInner::SetApplicationInfo(const std::shared_ptr<ApplicationInfo>& applicationInfo)
65 {
66     applicationInfo_ = applicationInfo;
67 }
68 
GetInstance()69 std::shared_ptr<AppfreezeInner> AppfreezeInner::GetInstance()
70 {
71     if (instance_ == nullptr) {
72         std::lock_guard<std::mutex> lock(singletonMutex_);
73         if (instance_ == nullptr) {
74             instance_ = std::make_shared<AppfreezeInner>();
75         }
76     }
77     return instance_;
78 }
79 
DestroyInstance()80 void AppfreezeInner::DestroyInstance()
81 {
82     std::lock_guard<std::mutex> lock(singletonMutex_);
83     if (instance_ != nullptr) {
84         instance_.reset();
85         instance_ = nullptr;
86     }
87 }
88 
IsHandleAppfreeze()89 bool AppfreezeInner::IsHandleAppfreeze()
90 {
91     return !isAppDebug_;
92 }
93 
GetProcStatm(int32_t pid)94 std::string AppfreezeInner::GetProcStatm(int32_t pid)
95 {
96     std::string procStatm;
97     std::ifstream statmStream("/proc/" + std::to_string(pid) + "/statm");
98     if (statmStream) {
99         std::getline(statmStream, procStatm);
100         statmStream.close();
101     }
102     return procStatm;
103 }
104 
GetMainHandlerDump(std::string & msgContent)105 void AppfreezeInner::GetMainHandlerDump(std::string& msgContent)
106 {
107     msgContent = "\nMain handler dump start time: " + AbilityRuntime::TimeUtil::DefaultCurrentTimeStr() + "\n";
108     auto mainHandler = appMainHandler_.lock();
109     if (mainHandler == nullptr) {
110         msgContent += "mainHandler is destructed!\n";
111     } else {
112         MainHandlerDumper handlerDumper;
113         msgContent += "mainHandler dump is:\n";
114         mainHandler->Dump(handlerDumper);
115         msgContent += handlerDumper.GetDumpInfo();
116     }
117     msgContent += "Main handler dump end time: " + AbilityRuntime::TimeUtil::DefaultCurrentTimeStr() + "\n";
118 }
119 
ChangeFaultDateInfo(FaultData & faultData,const std::string & msgContent)120 void AppfreezeInner::ChangeFaultDateInfo(FaultData& faultData, const std::string& msgContent)
121 {
122     faultData.errorObject.message += msgContent;
123     faultData.faultType = FaultDataType::APP_FREEZE;
124     faultData.notifyApp = false;
125     faultData.waitSaveState = false;
126     faultData.forceExit = false;
127     int32_t pid = IPCSkeleton::GetCallingPid();
128     faultData.errorObject.stack = "\nDump tid stack start time: " +
129         AbilityRuntime::TimeUtil::DefaultCurrentTimeStr() + "\n";
130     std::string stack = "";
131     if (!HiviewDFX::GetBacktraceStringByTidWithMix(stack, pid, 0, true)) {
132         stack = "Failed to dump stacktrace for " + std::to_string(pid) + "\n" + stack;
133     }
134     faultData.errorObject.stack += stack + "\nDump tid stack end time: " +
135         AbilityRuntime::TimeUtil::DefaultCurrentTimeStr() + "\n";
136     bool isExit = IsExitApp(faultData.errorObject.name) && faultData.needKillProcess;
137     if (isExit) {
138         faultData.forceExit = true;
139         faultData.waitSaveState = AppRecovery::GetInstance().IsEnabled();
140         AAFwk::ExitReason exitReason = {REASON_APP_FREEZE, "Kill Reason:" + faultData.errorObject.name};
141         AbilityManagerClient::GetInstance()->RecordAppExitReason(exitReason);
142     }
143     NotifyANR(faultData);
144     if (isExit) {
145         AppFreezeRecovery();
146     }
147 }
148 
AppfreezeHandleOverReportCount(bool isSixSecondEvent)149 void AppfreezeInner::AppfreezeHandleOverReportCount(bool isSixSecondEvent)
150 {
151     FaultData faultData;
152     faultData.errorObject.message =
153         "\nFault time:" + AbilityRuntime::TimeUtil::FormatTime("%Y/%m/%d-%H:%M:%S") + "\n";
154     faultData.errorObject.message += "App main thread is not response!";
155     faultData.faultType = FaultDataType::APP_FREEZE;
156     int32_t pid = static_cast<int32_t>(getpid());
157     if (isSixSecondEvent) {
158         faultData.errorObject.name = AppFreezeType::THREAD_BLOCK_6S;
159         faultData.procStatm = GetProcStatm(pid);
160     } else {
161         if (!BETA_VERSION) {
162             int32_t ret = HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::AAFWK, "HIVIEW_HALF_FREEZE_LOG",
163                 HiviewDFX::HiSysEvent::EventType::FAULT, "PID", pid, "PACKAGE_NAME", "");
164             TAG_LOGW(AAFwkTag::APPDFR, "hisysevent write HIVIEW_HALF_FREEZE_LOG, pid:%{public}d, packageName:,"
165                 " ret:%{public}d", pid, ret);
166         }
167         faultData.errorObject.name = AppFreezeType::THREAD_BLOCK_3S;
168     }
169     if (!IsHandleAppfreeze()) {
170         NotifyANR(faultData);
171         return;
172     }
173     std::string msgContent;
174     GetMainHandlerDump(msgContent);
175     ChangeFaultDateInfo(faultData, msgContent);
176     return;
177 }
178 
AppfreezeHandle(const FaultData & faultData,bool onlyMainThread)179 int AppfreezeInner::AppfreezeHandle(const FaultData& faultData, bool onlyMainThread)
180 {
181     if (!IsHandleAppfreeze()) {
182         NotifyANR(faultData);
183         return -1;
184     }
185     auto reportFreeze = [faultData, onlyMainThread]() {
186         if (faultData.errorObject.name == "") {
187             TAG_LOGE(AAFwkTag::APPDFR, "null name");
188             return;
189         }
190         AppExecFwk::AppfreezeInner::GetInstance()->AcquireStack(faultData, onlyMainThread);
191     };
192 
193     {
194         std::lock_guard<std::mutex> lock(handlingMutex_);
195         handlinglist_.emplace_back(faultData);
196         constexpr int HANDLING_MIN_SIZE = 1;
197         if (handlinglist_.size() <= HANDLING_MIN_SIZE) {
198             TAG_LOGW(AAFwkTag::APPDFR, "submit reportAppFreeze, eventName:%{public}s, startTime:%{public}s\n",
199                 faultData.errorObject.name.c_str(), AbilityRuntime::TimeUtil::DefaultCurrentTimeStr().c_str());
200             ffrt::submit(reportFreeze, {}, {}, ffrt::task_attr().name("reportAppFreeze"));
201         }
202     }
203     return 0;
204 }
205 
IsExitApp(const std::string & name)206 bool AppfreezeInner::IsExitApp(const std::string& name)
207 {
208     if (name == AppFreezeType::THREAD_BLOCK_6S || name == AppFreezeType::APP_INPUT_BLOCK ||
209         name == AppFreezeType::LIFECYCLE_TIMEOUT || name == AppFreezeType::BUSSINESS_THREAD_BLOCK_6S ||
210         name == AppFreezeType::LIFECYCLE_TIMEOUT_WARNING) {
211         return true;
212     }
213     return false;
214 }
215 
AcquireStack(const FaultData & info,bool onlyMainThread)216 int AppfreezeInner::AcquireStack(const FaultData& info, bool onlyMainThread)
217 {
218     HITRACE_METER_FMT(HITRACE_TAG_APP, "AppfreezeInner::AcquireStack name:%s", info.errorObject.name.c_str());
219     std::string msgContent;
220     int64_t startTime = AbilityRuntime::TimeUtil::CurrentTimeMillis();
221     GetMainHandlerDump(msgContent);
222     TAG_LOGW(AAFwkTag::APPDFR, "get mainhandler dump, eventName:%{public}s, endTime:%{public}s, "
223         "interval:%{public}" PRId64 " ms", info.errorObject.name.c_str(),
224         AbilityRuntime::TimeUtil::DefaultCurrentTimeStr().c_str(),
225         AbilityRuntime::TimeUtil::CurrentTimeMillis() - startTime);
226 
227     std::lock_guard<std::mutex> lock(handlingMutex_);
228     for (auto it = handlinglist_.begin(); it != handlinglist_.end(); it = handlinglist_.erase(it)) {
229         HITRACE_METER_FMT(HITRACE_TAG_APP, "send appfreeze name:%s", it->errorObject.name.c_str());
230         FaultData faultData;
231         faultData.errorObject.message = it->errorObject.message + "\n";
232         if (it->state != 0) {
233             faultData.errorObject.message += "client actions for ability:\n" +
234                 FreezeUtil::GetInstance().GetLifecycleEvent(it->token) + "\nclient actions for app:\n" +
235                 FreezeUtil::GetInstance().GetAppLifecycleEvent(0) + "\n";
236             if (it->errorObject.name == AppFreezeType::LIFECYCLE_TIMEOUT ||
237                 it->errorObject.name == AppFreezeType::LIFECYCLE_TIMEOUT_WARNING) {
238                 FreezeUtil::GetInstance().DeleteLifecycleEvent(it->token);
239                 FreezeUtil::GetInstance().DeleteAppLifecycleEvent(0);
240             }
241         }
242         faultData.errorObject.name = it->errorObject.name;
243         faultData.timeoutMarkers = it->timeoutMarkers;
244         faultData.eventId = it->eventId;
245         faultData.needKillProcess = it->needKillProcess;
246         faultData.appfreezeInfo = it->appfreezeInfo;
247         faultData.appRunningUniqueId = it->appRunningUniqueId;
248         faultData.procStatm = it->procStatm;
249         ChangeFaultDateInfo(faultData, msgContent);
250     }
251     return 0;
252 }
253 
ThreadBlock(std::atomic_bool & isSixSecondEvent)254 void AppfreezeInner::ThreadBlock(std::atomic_bool& isSixSecondEvent)
255 {
256     FaultData faultData;
257     faultData.errorObject.message =
258         "\nFault time:" + AbilityRuntime::TimeUtil::FormatTime("%Y/%m/%d-%H:%M:%S") + "\n";
259     faultData.errorObject.message += "App main thread is not response!";
260     faultData.faultType = FaultDataType::APP_FREEZE;
261     bool onlyMainThread = false;
262     int32_t pid = static_cast<int32_t>(getpid());
263 
264     if (isSixSecondEvent) {
265         faultData.errorObject.name = AppFreezeType::THREAD_BLOCK_6S;
266         onlyMainThread = true;
267 #ifdef APP_NO_RESPONSE_DIALOG
268         isSixSecondEvent.store(false);
269 #endif
270         faultData.procStatm = GetProcStatm(pid);
271     } else {
272         if (!BETA_VERSION) {
273             int32_t ret = HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::AAFWK, "HIVIEW_HALF_FREEZE_LOG",
274                 HiviewDFX::HiSysEvent::EventType::FAULT, "PID", pid, "PACKAGE_NAME", "");
275             TAG_LOGW(AAFwkTag::APPDFR, "hisysevent write HIVIEW_HALF_FREEZE_LOG, pid:%{public}d, packageName:,"
276                 " ret:%{public}d", pid, ret);
277         }
278         faultData.errorObject.name = AppFreezeType::THREAD_BLOCK_3S;
279         isSixSecondEvent.store(true);
280         std::string outFile;
281         OHOS::HiviewDFX::Watchdog::GetInstance().StartSample(HALF_DURATION, HALF_INTERVAL, outFile);
282         faultData.appfreezeInfo = outFile;
283     }
284 
285     if (!IsHandleAppfreeze()) {
286         return;
287     }
288 
289     AppfreezeHandle(faultData, onlyMainThread);
290 }
291 
NotifyANR(const FaultData & faultData)292 int AppfreezeInner::NotifyANR(const FaultData& faultData)
293 {
294     HITRACE_METER_FMT(HITRACE_TAG_APP, "AppfreezeInner::NotifyANR name:%s",
295         faultData.errorObject.name.c_str());
296     auto applicationInfo = applicationInfo_.lock();
297     if (applicationInfo == nullptr) {
298         TAG_LOGE(AAFwkTag::APPDFR, "null applicationInfo_");
299         return -1;
300     }
301 
302     int32_t pid = static_cast<int32_t>(getpid());
303     TAG_LOGW(AAFwkTag::APPDFR, "NotifyAppFault:%{public}s, pid:%{public}d, bundleName:%{public}s "
304         "currentTime:%{public}s, processExit:%{public}d\n", faultData.errorObject.name.c_str(), pid,
305         applicationInfo->bundleName.c_str(), AbilityRuntime::TimeUtil::DefaultCurrentTimeStr().c_str(),
306         faultData.needKillProcess);
307 
308     int ret = DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance()->NotifyAppFault(faultData);
309     if (ret != 0) {
310         TAG_LOGW(AAFwkTag::APPDFR, "NotifyAppFault ret:%{public}d", ret);
311     }
312     return ret;
313 }
314 
AppFreezeRecovery()315 void AppfreezeInner::AppFreezeRecovery()
316 {
317     AppRecovery::GetInstance().ScheduleSaveAppState(StateReason::APP_FREEZE);
318     AppRecovery::GetInstance().ScheduleRecoverApp(StateReason::APP_FREEZE);
319 }
320 
SetAppDebug(bool isAppDebug)321 void AppfreezeInner::SetAppDebug(bool isAppDebug)
322 {
323     isAppDebug_ = isAppDebug;
324 }
325 
Dump(const std::string & message)326 void MainHandlerDumper::Dump(const std::string &message)
327 {
328     dumpInfo += message;
329 }
330 
GetTag()331 std::string MainHandlerDumper::GetTag()
332 {
333     return "";
334 }
335 
GetDumpInfo()336 std::string MainHandlerDumper::GetDumpInfo()
337 {
338     return dumpInfo;
339 }
340 }  // namespace AAFwk
341 }  // namespace OHOS