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