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