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