1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.server.am;
18 
19 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
20 import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
21 
22 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
23 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
24 import static com.android.server.am.ActivityManagerService.MY_PID;
25 import static com.android.server.am.ActivityManagerService.SYSTEM_DEBUGGABLE;
26 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
27 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
28 
29 import android.app.ActivityManager;
30 import android.app.ActivityOptions;
31 import android.app.ApplicationErrorReport;
32 import android.app.ApplicationExitInfo;
33 import android.content.ActivityNotFoundException;
34 import android.content.Context;
35 import android.content.Intent;
36 import android.content.pm.ApplicationInfo;
37 import android.content.pm.VersionedPackage;
38 import android.net.Uri;
39 import android.os.Binder;
40 import android.os.Message;
41 import android.os.Process;
42 import android.os.SystemClock;
43 import android.os.SystemProperties;
44 import android.os.UserHandle;
45 import android.provider.Settings;
46 import android.util.ArrayMap;
47 import android.util.ArraySet;
48 import android.util.EventLog;
49 import android.util.Slog;
50 import android.util.SparseArray;
51 import android.util.TimeUtils;
52 import android.util.proto.ProtoOutputStream;
53 
54 import com.android.internal.app.ProcessMap;
55 import com.android.internal.logging.MetricsLogger;
56 import com.android.internal.logging.nano.MetricsProto;
57 import com.android.server.PackageWatchdog;
58 import com.android.server.wm.WindowProcessController;
59 
60 import java.io.FileDescriptor;
61 import java.io.PrintWriter;
62 import java.util.Collections;
63 import java.util.List;
64 
65 /**
66  * Controls error conditions in applications.
67  */
68 class AppErrors {
69 
70     private static final String TAG = TAG_WITH_CLASS_NAME ? "AppErrors" : TAG_AM;
71 
72     private final ActivityManagerService mService;
73     private final Context mContext;
74     private final PackageWatchdog mPackageWatchdog;
75 
76     private ArraySet<String> mAppsNotReportingCrashes;
77 
78     /**
79      * The last time that various processes have crashed since they were last explicitly started.
80      */
81     private final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<>();
82 
83     /**
84      * The last time that various processes have crashed (not reset even when explicitly started).
85      */
86     private final ProcessMap<Long> mProcessCrashTimesPersistent = new ProcessMap<>();
87 
88     /**
89      * The last time that various processes have crashed and shown an error dialog.
90      */
91     private final ProcessMap<Long> mProcessCrashShowDialogTimes = new ProcessMap<>();
92 
93     /**
94      * Set of applications that we consider to be bad, and will reject
95      * incoming broadcasts from (which the user has no control over).
96      * Processes are added to this set when they have crashed twice within
97      * a minimum amount of time; they are removed from it when they are
98      * later restarted (hopefully due to some user action).  The value is the
99      * time it was added to the list.
100      */
101     private final ProcessMap<BadProcessInfo> mBadProcesses = new ProcessMap<>();
102 
103 
AppErrors(Context context, ActivityManagerService service, PackageWatchdog watchdog)104     AppErrors(Context context, ActivityManagerService service, PackageWatchdog watchdog) {
105         context.assertRuntimeOverlayThemable();
106         mService = service;
107         mContext = context;
108         mPackageWatchdog = watchdog;
109     }
110 
dumpDebug(ProtoOutputStream proto, long fieldId, String dumpPackage)111     void dumpDebug(ProtoOutputStream proto, long fieldId, String dumpPackage) {
112         if (mProcessCrashTimes.getMap().isEmpty() && mBadProcesses.getMap().isEmpty()) {
113             return;
114         }
115 
116         final long token = proto.start(fieldId);
117         final long now = SystemClock.uptimeMillis();
118         proto.write(AppErrorsProto.NOW_UPTIME_MS, now);
119 
120         if (!mProcessCrashTimes.getMap().isEmpty()) {
121             final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap();
122             final int procCount = pmap.size();
123             for (int ip = 0; ip < procCount; ip++) {
124                 final long ctoken = proto.start(AppErrorsProto.PROCESS_CRASH_TIMES);
125                 final String pname = pmap.keyAt(ip);
126                 final SparseArray<Long> uids = pmap.valueAt(ip);
127                 final int uidCount = uids.size();
128 
129                 proto.write(AppErrorsProto.ProcessCrashTime.PROCESS_NAME, pname);
130                 for (int i = 0; i < uidCount; i++) {
131                     final int puid = uids.keyAt(i);
132                     final ProcessRecord r = mService.getProcessNames().get(pname, puid);
133                     if (dumpPackage != null && (r == null || !r.pkgList.containsKey(dumpPackage))) {
134                         continue;
135                     }
136                     final long etoken = proto.start(AppErrorsProto.ProcessCrashTime.ENTRIES);
137                     proto.write(AppErrorsProto.ProcessCrashTime.Entry.UID, puid);
138                     proto.write(AppErrorsProto.ProcessCrashTime.Entry.LAST_CRASHED_AT_MS,
139                             uids.valueAt(i));
140                     proto.end(etoken);
141                 }
142                 proto.end(ctoken);
143             }
144 
145         }
146 
147         if (!mBadProcesses.getMap().isEmpty()) {
148             final ArrayMap<String, SparseArray<BadProcessInfo>> pmap = mBadProcesses.getMap();
149             final int processCount = pmap.size();
150             for (int ip = 0; ip < processCount; ip++) {
151                 final long btoken = proto.start(AppErrorsProto.BAD_PROCESSES);
152                 final String pname = pmap.keyAt(ip);
153                 final SparseArray<BadProcessInfo> uids = pmap.valueAt(ip);
154                 final int uidCount = uids.size();
155 
156                 proto.write(AppErrorsProto.BadProcess.PROCESS_NAME, pname);
157                 for (int i = 0; i < uidCount; i++) {
158                     final int puid = uids.keyAt(i);
159                     final ProcessRecord r = mService.getProcessNames().get(pname, puid);
160                     if (dumpPackage != null && (r == null
161                             || !r.pkgList.containsKey(dumpPackage))) {
162                         continue;
163                     }
164                     final BadProcessInfo info = uids.valueAt(i);
165                     final long etoken = proto.start(AppErrorsProto.BadProcess.ENTRIES);
166                     proto.write(AppErrorsProto.BadProcess.Entry.UID, puid);
167                     proto.write(AppErrorsProto.BadProcess.Entry.CRASHED_AT_MS, info.time);
168                     proto.write(AppErrorsProto.BadProcess.Entry.SHORT_MSG, info.shortMsg);
169                     proto.write(AppErrorsProto.BadProcess.Entry.LONG_MSG, info.longMsg);
170                     proto.write(AppErrorsProto.BadProcess.Entry.STACK, info.stack);
171                     proto.end(etoken);
172                 }
173                 proto.end(btoken);
174             }
175         }
176 
177         proto.end(token);
178     }
179 
dumpLocked(FileDescriptor fd, PrintWriter pw, boolean needSep, String dumpPackage)180     boolean dumpLocked(FileDescriptor fd, PrintWriter pw, boolean needSep, String dumpPackage) {
181         if (!mProcessCrashTimes.getMap().isEmpty()) {
182             boolean printed = false;
183             final long now = SystemClock.uptimeMillis();
184             final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap();
185             final int processCount = pmap.size();
186             for (int ip = 0; ip < processCount; ip++) {
187                 final String pname = pmap.keyAt(ip);
188                 final SparseArray<Long> uids = pmap.valueAt(ip);
189                 final int uidCount = uids.size();
190                 for (int i = 0; i < uidCount; i++) {
191                     final int puid = uids.keyAt(i);
192                     final ProcessRecord r = mService.getProcessNames().get(pname, puid);
193                     if (dumpPackage != null && (r == null
194                             || !r.pkgList.containsKey(dumpPackage))) {
195                         continue;
196                     }
197                     if (!printed) {
198                         if (needSep) pw.println();
199                         needSep = true;
200                         pw.println("  Time since processes crashed:");
201                         printed = true;
202                     }
203                     pw.print("    Process "); pw.print(pname);
204                     pw.print(" uid "); pw.print(puid);
205                     pw.print(": last crashed ");
206                     TimeUtils.formatDuration(now-uids.valueAt(i), pw);
207                     pw.println(" ago");
208                 }
209             }
210         }
211 
212         if (!mBadProcesses.getMap().isEmpty()) {
213             boolean printed = false;
214             final ArrayMap<String, SparseArray<BadProcessInfo>> pmap = mBadProcesses.getMap();
215             final int processCount = pmap.size();
216             for (int ip = 0; ip < processCount; ip++) {
217                 final String pname = pmap.keyAt(ip);
218                 final SparseArray<BadProcessInfo> uids = pmap.valueAt(ip);
219                 final int uidCount = uids.size();
220                 for (int i = 0; i < uidCount; i++) {
221                     final int puid = uids.keyAt(i);
222                     final ProcessRecord r = mService.getProcessNames().get(pname, puid);
223                     if (dumpPackage != null && (r == null
224                             || !r.pkgList.containsKey(dumpPackage))) {
225                         continue;
226                     }
227                     if (!printed) {
228                         if (needSep) pw.println();
229                         needSep = true;
230                         pw.println("  Bad processes:");
231                         printed = true;
232                     }
233                     final BadProcessInfo info = uids.valueAt(i);
234                     pw.print("    Bad process "); pw.print(pname);
235                     pw.print(" uid "); pw.print(puid);
236                     pw.print(": crashed at time "); pw.println(info.time);
237                     if (info.shortMsg != null) {
238                         pw.print("      Short msg: "); pw.println(info.shortMsg);
239                     }
240                     if (info.longMsg != null) {
241                         pw.print("      Long msg: "); pw.println(info.longMsg);
242                     }
243                     if (info.stack != null) {
244                         pw.println("      Stack:");
245                         int lastPos = 0;
246                         for (int pos = 0; pos < info.stack.length(); pos++) {
247                             if (info.stack.charAt(pos) == '\n') {
248                                 pw.print("        ");
249                                 pw.write(info.stack, lastPos, pos-lastPos);
250                                 pw.println();
251                                 lastPos = pos+1;
252                             }
253                         }
254                         if (lastPos < info.stack.length()) {
255                             pw.print("        ");
256                             pw.write(info.stack, lastPos, info.stack.length()-lastPos);
257                             pw.println();
258                         }
259                     }
260                 }
261             }
262         }
263         return needSep;
264     }
265 
isBadProcessLocked(ApplicationInfo info)266     boolean isBadProcessLocked(ApplicationInfo info) {
267         return mBadProcesses.get(info.processName, info.uid) != null;
268     }
269 
clearBadProcessLocked(ApplicationInfo info)270     void clearBadProcessLocked(ApplicationInfo info) {
271         mBadProcesses.remove(info.processName, info.uid);
272     }
273 
resetProcessCrashTimeLocked(ApplicationInfo info)274     void resetProcessCrashTimeLocked(ApplicationInfo info) {
275         mProcessCrashTimes.remove(info.processName, info.uid);
276     }
277 
resetProcessCrashTimeLocked(boolean resetEntireUser, int appId, int userId)278     void resetProcessCrashTimeLocked(boolean resetEntireUser, int appId, int userId) {
279         final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap();
280         for (int ip = pmap.size() - 1; ip >= 0; ip--) {
281             SparseArray<Long> ba = pmap.valueAt(ip);
282             for (int i = ba.size() - 1; i >= 0; i--) {
283                 boolean remove = false;
284                 final int entUid = ba.keyAt(i);
285                 if (!resetEntireUser) {
286                     if (userId == UserHandle.USER_ALL) {
287                         if (UserHandle.getAppId(entUid) == appId) {
288                             remove = true;
289                         }
290                     } else {
291                         if (entUid == UserHandle.getUid(userId, appId)) {
292                             remove = true;
293                         }
294                     }
295                 } else if (UserHandle.getUserId(entUid) == userId) {
296                     remove = true;
297                 }
298                 if (remove) {
299                     ba.removeAt(i);
300                 }
301             }
302             if (ba.size() == 0) {
303                 pmap.removeAt(ip);
304             }
305         }
306     }
307 
loadAppsNotReportingCrashesFromConfigLocked(String appsNotReportingCrashesConfig)308     void loadAppsNotReportingCrashesFromConfigLocked(String appsNotReportingCrashesConfig) {
309         if (appsNotReportingCrashesConfig != null) {
310             final String[] split = appsNotReportingCrashesConfig.split(",");
311             if (split.length > 0) {
312                 mAppsNotReportingCrashes = new ArraySet<>();
313                 Collections.addAll(mAppsNotReportingCrashes, split);
314             }
315         }
316     }
317 
killAppAtUserRequestLocked(ProcessRecord app)318     void killAppAtUserRequestLocked(ProcessRecord app) {
319         ProcessRecord.ErrorDialogController controller =
320                 app.getDialogController();
321 
322         int reasonCode = ApplicationExitInfo.REASON_ANR;
323         int subReason = ApplicationExitInfo.SUBREASON_UNKNOWN;
324         if (controller.hasDebugWaitingDialog()) {
325             reasonCode = ApplicationExitInfo.REASON_OTHER;
326             subReason = ApplicationExitInfo.SUBREASON_WAIT_FOR_DEBUGGER;
327         }
328 
329         controller.clearAllErrorDialogs();
330         killAppImmediateLocked(app, reasonCode, subReason,
331                 "user-terminated", "user request after error");
332     }
333 
killAppImmediateLocked(ProcessRecord app, int reasonCode, int subReason, String reason, String killReason)334     private void killAppImmediateLocked(ProcessRecord app, int reasonCode, int subReason,
335             String reason, String killReason) {
336         app.setCrashing(false);
337         app.crashingReport = null;
338         app.setNotResponding(false);
339         app.notRespondingReport = null;
340         if (app.pid > 0 && app.pid != MY_PID) {
341             handleAppCrashLocked(app, reason,
342                     null /*shortMsg*/, null /*longMsg*/, null /*stackTrace*/, null /*data*/);
343             app.kill(killReason, reasonCode, subReason, true);
344         }
345     }
346 
347     /**
348      * Induce a crash in the given app.
349      *
350      * @param uid if nonnegative, the required matching uid of the target to crash
351      * @param initialPid fast-path match for the target to crash
352      * @param packageName fallback match if the stated pid is not found or doesn't match uid
353      * @param userId If nonnegative, required to identify a match by package name
354      * @param message
355      */
scheduleAppCrashLocked(int uid, int initialPid, String packageName, int userId, String message, boolean force)356     void scheduleAppCrashLocked(int uid, int initialPid, String packageName, int userId,
357             String message, boolean force) {
358         ProcessRecord proc = null;
359 
360         // Figure out which process to kill.  We don't trust that initialPid
361         // still has any relation to current pids, so must scan through the
362         // list.
363 
364         synchronized (mService.mPidsSelfLocked) {
365             for (int i=0; i<mService.mPidsSelfLocked.size(); i++) {
366                 ProcessRecord p = mService.mPidsSelfLocked.valueAt(i);
367                 if (uid >= 0 && p.uid != uid) {
368                     continue;
369                 }
370                 if (p.pid == initialPid) {
371                     proc = p;
372                     break;
373                 }
374                 if (p.pkgList.containsKey(packageName)
375                         && (userId < 0 || p.userId == userId)) {
376                     proc = p;
377                 }
378             }
379         }
380 
381         if (proc == null) {
382             Slog.w(TAG, "crashApplication: nothing for uid=" + uid
383                     + " initialPid=" + initialPid
384                     + " packageName=" + packageName
385                     + " userId=" + userId);
386             return;
387         }
388 
389         proc.scheduleCrash(message);
390         if (force) {
391             // If the app is responsive, the scheduled crash will happen as expected
392             // and then the delayed summary kill will be a no-op.
393             final ProcessRecord p = proc;
394             mService.mHandler.postDelayed(
395                     () -> {
396                         synchronized (mService) {
397                             killAppImmediateLocked(p, ApplicationExitInfo.REASON_OTHER,
398                                     ApplicationExitInfo.SUBREASON_INVALID_STATE,
399                                     "forced", "killed for invalid state");
400                         }
401                     },
402                     5000L);
403         }
404     }
405 
406     /**
407      * Bring up the "unexpected error" dialog box for a crashing app.
408      * Deal with edge cases (intercepts from instrumented applications,
409      * ActivityController, error intent receivers, that sort of thing).
410      * @param r the application crashing
411      * @param crashInfo describing the failure
412      */
crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo)413     void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
414         final int callingPid = Binder.getCallingPid();
415         final int callingUid = Binder.getCallingUid();
416 
417         final long origId = Binder.clearCallingIdentity();
418         try {
419             crashApplicationInner(r, crashInfo, callingPid, callingUid);
420         } finally {
421             Binder.restoreCallingIdentity(origId);
422         }
423     }
424 
crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo, int callingPid, int callingUid)425     void crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo,
426             int callingPid, int callingUid) {
427         long timeMillis = System.currentTimeMillis();
428         String shortMsg = crashInfo.exceptionClassName;
429         String longMsg = crashInfo.exceptionMessage;
430         String stackTrace = crashInfo.stackTrace;
431         if (shortMsg != null && longMsg != null) {
432             longMsg = shortMsg + ": " + longMsg;
433         } else if (shortMsg != null) {
434             longMsg = shortMsg;
435         }
436 
437         if (r != null) {
438             mPackageWatchdog.onPackageFailure(r.getPackageListWithVersionCode(),
439                     PackageWatchdog.FAILURE_REASON_APP_CRASH);
440 
441             mService.mProcessList.noteAppKill(r, (crashInfo != null
442                       && "Native crash".equals(crashInfo.exceptionClassName))
443                       ? ApplicationExitInfo.REASON_CRASH_NATIVE
444                       : ApplicationExitInfo.REASON_CRASH,
445                       ApplicationExitInfo.SUBREASON_UNKNOWN,
446                     "crash");
447         }
448 
449         final int relaunchReason = r != null
450                 ? r.getWindowProcessController().computeRelaunchReason() : RELAUNCH_REASON_NONE;
451 
452         AppErrorResult result = new AppErrorResult();
453         int taskId;
454         synchronized (mService) {
455             /**
456              * If crash is handled by instance of {@link android.app.IActivityController},
457              * finish now and don't show the app error dialog.
458              */
459             if (handleAppCrashInActivityController(r, crashInfo, shortMsg, longMsg, stackTrace,
460                     timeMillis, callingPid, callingUid)) {
461                 return;
462             }
463 
464             // Suppress crash dialog if the process is being relaunched due to a crash during a free
465             // resize.
466             if (relaunchReason == RELAUNCH_REASON_FREE_RESIZE) {
467                 return;
468             }
469 
470             /**
471              * If this process was running instrumentation, finish now - it will be handled in
472              * {@link ActivityManagerService#handleAppDiedLocked}.
473              */
474             if (r != null && r.getActiveInstrumentation() != null) {
475                 return;
476             }
477 
478             // Log crash in battery stats.
479             if (r != null) {
480                 mService.mBatteryStatsService.noteProcessCrash(r.processName, r.uid);
481             }
482 
483             AppErrorDialog.Data data = new AppErrorDialog.Data();
484             data.result = result;
485             data.proc = r;
486 
487             // If we can't identify the process or it's already exceeded its crash quota,
488             // quit right away without showing a crash dialog.
489             if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, data)) {
490                 return;
491             }
492 
493             final Message msg = Message.obtain();
494             msg.what = ActivityManagerService.SHOW_ERROR_UI_MSG;
495 
496             taskId = data.taskId;
497             msg.obj = data;
498             mService.mUiHandler.sendMessage(msg);
499         }
500 
501         int res = result.get();
502 
503         Intent appErrorIntent = null;
504         MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res);
505         if (res == AppErrorDialog.TIMEOUT || res == AppErrorDialog.CANCEL) {
506             res = AppErrorDialog.FORCE_QUIT;
507         }
508         synchronized (mService) {
509             if (res == AppErrorDialog.MUTE) {
510                 stopReportingCrashesLocked(r);
511             }
512             if (res == AppErrorDialog.RESTART) {
513                 mService.mProcessList.removeProcessLocked(r, false, true,
514                         ApplicationExitInfo.REASON_CRASH, "crash");
515                 if (taskId != INVALID_TASK_ID) {
516                     try {
517                         mService.startActivityFromRecents(taskId,
518                                 ActivityOptions.makeBasic().toBundle());
519                     } catch (IllegalArgumentException e) {
520                         // Hmm...that didn't work. Task should either be in recents or associated
521                         // with a stack.
522                         Slog.e(TAG, "Could not restart taskId=" + taskId, e);
523                     }
524                 }
525             }
526             if (res == AppErrorDialog.FORCE_QUIT) {
527                 long orig = Binder.clearCallingIdentity();
528                 try {
529                     // Kill it with fire!
530                     mService.mAtmInternal.onHandleAppCrash(r.getWindowProcessController());
531                     if (!r.isPersistent()) {
532                         mService.mProcessList.removeProcessLocked(r, false, false,
533                                 ApplicationExitInfo.REASON_CRASH, "crash");
534                         mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
535                     }
536                 } finally {
537                     Binder.restoreCallingIdentity(orig);
538                 }
539             }
540             if (res == AppErrorDialog.APP_INFO) {
541                 appErrorIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
542                 appErrorIntent.setData(Uri.parse("package:" + r.info.packageName));
543                 appErrorIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
544             }
545             if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
546                 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
547             }
548             if (r != null && !r.isolated && res != AppErrorDialog.RESTART) {
549                 // XXX Can't keep track of crash time for isolated processes,
550                 // since they don't have a persistent identity.
551                 mProcessCrashTimes.put(r.info.processName, r.uid,
552                         SystemClock.uptimeMillis());
553             }
554         }
555 
556         if (appErrorIntent != null) {
557             try {
558                 mContext.startActivityAsUser(appErrorIntent, new UserHandle(r.userId));
559             } catch (ActivityNotFoundException e) {
560                 Slog.w(TAG, "bug report receiver dissappeared", e);
561             }
562         }
563     }
564 
handleAppCrashInActivityController(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo, String shortMsg, String longMsg, String stackTrace, long timeMillis, int callingPid, int callingUid)565     private boolean handleAppCrashInActivityController(ProcessRecord r,
566                                                        ApplicationErrorReport.CrashInfo crashInfo,
567                                                        String shortMsg, String longMsg,
568                                                        String stackTrace, long timeMillis,
569                                                        int callingPid, int callingUid) {
570         String name = r != null ? r.processName : null;
571         int pid = r != null ? r.pid : callingPid;
572         int uid = r != null ? r.info.uid : callingUid;
573 
574         return mService.mAtmInternal.handleAppCrashInActivityController(
575                 name, pid, shortMsg, longMsg, timeMillis, crashInfo.stackTrace, () -> {
576                 if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"))
577                         && "Native crash".equals(crashInfo.exceptionClassName)) {
578                     Slog.w(TAG, "Skip killing native crashed app " + name
579                             + "(" + pid + ") during testing");
580                 } else {
581                     Slog.w(TAG, "Force-killing crashed app " + name + " at watcher's request");
582                     if (r != null) {
583                         if (!makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, null)) {
584                             r.kill("crash", ApplicationExitInfo.REASON_CRASH, true);
585                         }
586                     } else {
587                         // Huh.
588                         Process.killProcess(pid);
589                         ProcessList.killProcessGroup(uid, pid);
590                         mService.mProcessList.noteAppKill(pid, uid,
591                                 ApplicationExitInfo.REASON_CRASH,
592                                 ApplicationExitInfo.SUBREASON_UNKNOWN,
593                                 "crash");
594                     }
595                 }
596         });
597     }
598 
599     private boolean makeAppCrashingLocked(ProcessRecord app,
600             String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
601         app.setCrashing(true);
602         app.crashingReport = generateProcessError(app,
603                 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
604         app.startAppProblemLocked();
605         app.getWindowProcessController().stopFreezingActivities();
606         return handleAppCrashLocked(app, "force-crash" /*reason*/, shortMsg, longMsg, stackTrace,
607                 data);
608     }
609 
610     /**
611      * Generate a process error record, suitable for attachment to a ProcessRecord.
612      *
613      * @param app The ProcessRecord in which the error occurred.
614      * @param condition Crashing, Application Not Responding, etc.  Values are defined in
615      *                      ActivityManager.ProcessErrorStateInfo
616      * @param activity The activity associated with the crash, if known.
617      * @param shortMsg Short message describing the crash.
618      * @param longMsg Long message describing the crash.
619      * @param stackTrace Full crash stack trace, may be null.
620      *
621      * @return Returns a fully-formed ProcessErrorStateInfo record.
622      */
623     ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
624             int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
625         ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
626 
627         report.condition = condition;
628         report.processName = app.processName;
629         report.pid = app.pid;
630         report.uid = app.info.uid;
631         report.tag = activity;
632         report.shortMsg = shortMsg;
633         report.longMsg = longMsg;
634         report.stackTrace = stackTrace;
635 
636         return report;
637     }
638 
639     Intent createAppErrorIntentLocked(ProcessRecord r,
640             long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
641         ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
642         if (report == null) {
643             return null;
644         }
645         Intent result = new Intent(Intent.ACTION_APP_ERROR);
646         result.setComponent(r.errorReportReceiver);
647         result.putExtra(Intent.EXTRA_BUG_REPORT, report);
648         result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
649         return result;
650     }
651 
652     private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
653             long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
654         if (r.errorReportReceiver == null) {
655             return null;
656         }
657 
658         if (!r.isCrashing() && !r.isNotResponding() && !r.forceCrashReport) {
659             return null;
660         }
661 
662         ApplicationErrorReport report = new ApplicationErrorReport();
663         report.packageName = r.info.packageName;
664         report.installerPackageName = r.errorReportReceiver.getPackageName();
665         report.processName = r.processName;
666         report.time = timeMillis;
667         report.systemApp = (r.info.flags & FLAG_SYSTEM) != 0;
668 
669         if (r.isCrashing() || r.forceCrashReport) {
670             report.type = ApplicationErrorReport.TYPE_CRASH;
671             report.crashInfo = crashInfo;
672         } else if (r.isNotResponding()) {
673             report.type = ApplicationErrorReport.TYPE_ANR;
674             report.anrInfo = new ApplicationErrorReport.AnrInfo();
675 
676             report.anrInfo.activity = r.notRespondingReport.tag;
677             report.anrInfo.cause = r.notRespondingReport.shortMsg;
678             report.anrInfo.info = r.notRespondingReport.longMsg;
679         }
680 
681         return report;
682     }
683 
684     boolean handleAppCrashLocked(ProcessRecord app, String reason,
685             String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
686         final long now = SystemClock.uptimeMillis();
687         final boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
688                 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
689 
690         final boolean procIsBoundForeground =
691             (app.getCurProcState() == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
692 
693         Long crashTime;
694         Long crashTimePersistent;
695         boolean tryAgain = false;
696 
697         if (!app.isolated) {
698             crashTime = mProcessCrashTimes.get(app.info.processName, app.uid);
699             crashTimePersistent = mProcessCrashTimesPersistent.get(app.info.processName, app.uid);
700         } else {
701             crashTime = crashTimePersistent = null;
702         }
703 
704         // Bump up the crash count of any services currently running in the proc.
705         for (int i = app.numberOfRunningServices() - 1; i >= 0; i--) {
706             // Any services running in the application need to be placed
707             // back in the pending list.
708             ServiceRecord sr = app.getRunningServiceAt(i);
709             // If the service was restarted a while ago, then reset crash count, else increment it.
710             if (now > sr.restartTime + ProcessList.MIN_CRASH_INTERVAL) {
711                 sr.crashCount = 1;
712             } else {
713                 sr.crashCount++;
714             }
715             // Allow restarting for started or bound foreground services that are crashing.
716             // This includes wallpapers.
717             if (sr.crashCount < mService.mConstants.BOUND_SERVICE_MAX_CRASH_RETRY
718                     && (sr.isForeground || procIsBoundForeground)) {
719                 tryAgain = true;
720             }
721         }
722 
723         if (crashTime != null && now < crashTime + ProcessList.MIN_CRASH_INTERVAL) {
724             // The process crashed again very quickly. If it was a bound foreground service, let's
725             // try to restart again in a while, otherwise the process loses!
726             Slog.w(TAG, "Process " + app.info.processName
727                     + " has crashed too many times: killing!");
728             EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
729                     app.userId, app.info.processName, app.uid);
730             mService.mAtmInternal.onHandleAppCrash(app.getWindowProcessController());
731             if (!app.isPersistent()) {
732                 // We don't want to start this process again until the user
733                 // explicitly does so...  but for persistent process, we really
734                 // need to keep it running.  If a persistent process is actually
735                 // repeatedly crashing, then badness for everyone.
736                 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.userId, app.uid,
737                         app.info.processName);
738                 if (!app.isolated) {
739                     // XXX We don't have a way to mark isolated processes
740                     // as bad, since they don't have a peristent identity.
741                     mBadProcesses.put(app.info.processName, app.uid,
742                             new BadProcessInfo(now, shortMsg, longMsg, stackTrace));
743                     mProcessCrashTimes.remove(app.info.processName, app.uid);
744                 }
745                 app.bad = true;
746                 app.removed = true;
747                 // Don't let services in this process be restarted and potentially
748                 // annoy the user repeatedly.  Unless it is persistent, since those
749                 // processes run critical code.
750                 mService.mProcessList.removeProcessLocked(app, false, tryAgain,
751                         ApplicationExitInfo.REASON_CRASH, "crash");
752                 mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
753                 if (!showBackground) {
754                     return false;
755                 }
756             }
757             mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
758         } else {
759             final int affectedTaskId = mService.mAtmInternal.finishTopCrashedActivities(
760                             app.getWindowProcessController(), reason);
761             if (data != null) {
762                 data.taskId = affectedTaskId;
763             }
764             if (data != null && crashTimePersistent != null
765                     && now < crashTimePersistent + ProcessList.MIN_CRASH_INTERVAL) {
766                 data.repeating = true;
767             }
768         }
769 
770         if (data != null && tryAgain) {
771             data.isRestartableForService = true;
772         }
773 
774         // If the crashing process is what we consider to be the "home process" and it has been
775         // replaced by a third-party app, clear the package preferred activities from packages
776         // with a home activity running in the process to prevent a repeatedly crashing app
777         // from blocking the user to manually clear the list.
778         final WindowProcessController proc = app.getWindowProcessController();
779         final WindowProcessController homeProc = mService.mAtmInternal.getHomeProcess();
780         if (proc == homeProc && proc.hasActivities()
781                 && (((ProcessRecord) homeProc.mOwner).info.flags & FLAG_SYSTEM) == 0) {
782             proc.clearPackagePreferredForHomeActivities();
783         }
784 
785         if (!app.isolated) {
786             // XXX Can't keep track of crash times for isolated processes,
787             // because they don't have a persistent identity.
788             mProcessCrashTimes.put(app.info.processName, app.uid, now);
789             mProcessCrashTimesPersistent.put(app.info.processName, app.uid, now);
790         }
791 
792         if (app.crashHandler != null) mService.mHandler.post(app.crashHandler);
793         return true;
794     }
795 
796     void handleShowAppErrorUi(Message msg) {
797         AppErrorDialog.Data data = (AppErrorDialog.Data) msg.obj;
798         boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
799                 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
800 
801         final int userId;
802         synchronized (mService) {
803             final ProcessRecord proc = data.proc;
804             final AppErrorResult res = data.result;
805             if (proc == null) {
806                 Slog.e(TAG, "handleShowAppErrorUi: proc is null");
807                 return;
808             }
809             userId = proc.userId;
810             if (proc.getDialogController().hasCrashDialogs()) {
811                 Slog.e(TAG, "App already has crash dialog: " + proc);
812                 if (res != null) {
813                     res.set(AppErrorDialog.ALREADY_SHOWING);
814                 }
815                 return;
816             }
817             boolean isBackground = (UserHandle.getAppId(proc.uid)
818                     >= Process.FIRST_APPLICATION_UID
819                     && proc.pid != MY_PID);
820             for (int profileId : mService.mUserController.getCurrentProfileIds()) {
821                 isBackground &= (userId != profileId);
822             }
823             if (isBackground && !showBackground) {
824                 Slog.w(TAG, "Skipping crash dialog of " + proc + ": background");
825                 if (res != null) {
826                     res.set(AppErrorDialog.BACKGROUND_USER);
827                 }
828                 return;
829             }
830             Long crashShowErrorTime = null;
831             if (!proc.isolated) {
832                 crashShowErrorTime = mProcessCrashShowDialogTimes.get(proc.info.processName,
833                         proc.uid);
834             }
835             final boolean showFirstCrash = Settings.Global.getInt(
836                     mContext.getContentResolver(),
837                     Settings.Global.SHOW_FIRST_CRASH_DIALOG, 0) != 0;
838             final boolean showFirstCrashDevOption = Settings.Secure.getIntForUser(
839                     mContext.getContentResolver(),
840                     Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION,
841                     0,
842                     mService.mUserController.getCurrentUserId()) != 0;
843             final boolean crashSilenced = mAppsNotReportingCrashes != null &&
844                     mAppsNotReportingCrashes.contains(proc.info.packageName);
845             final long now = SystemClock.uptimeMillis();
846             final boolean shouldThottle = crashShowErrorTime != null
847                     && now < crashShowErrorTime + ProcessList.MIN_CRASH_INTERVAL;
848             if ((mService.mAtmInternal.canShowErrorDialogs() || showBackground)
849                     && !crashSilenced && !shouldThottle
850                     && (showFirstCrash || showFirstCrashDevOption || data.repeating)) {
851                 proc.getDialogController().showCrashDialogs(data);
852                 if (!proc.isolated) {
853                     mProcessCrashShowDialogTimes.put(proc.info.processName, proc.uid, now);
854                 }
855             } else {
856                 // The device is asleep, so just pretend that the user
857                 // saw a crash dialog and hit "force quit".
858                 if (res != null) {
859                     res.set(AppErrorDialog.CANT_SHOW);
860                 }
861             }
862         }
863     }
864 
865     private void stopReportingCrashesLocked(ProcessRecord proc) {
866         if (mAppsNotReportingCrashes == null) {
867             mAppsNotReportingCrashes = new ArraySet<>();
868         }
869         mAppsNotReportingCrashes.add(proc.info.packageName);
870     }
871 
872     void handleShowAnrUi(Message msg) {
873         List<VersionedPackage> packageList = null;
874         synchronized (mService) {
875             AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj;
876             final ProcessRecord proc = data.proc;
877             if (proc == null) {
878                 Slog.e(TAG, "handleShowAnrUi: proc is null");
879                 return;
880             }
881             if (!proc.isPersistent()) {
882                 packageList = proc.getPackageListWithVersionCode();
883             }
884             if (proc.getDialogController().hasAnrDialogs()) {
885                 Slog.e(TAG, "App already has anr dialog: " + proc);
886                 MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
887                         AppNotRespondingDialog.ALREADY_SHOWING);
888                 return;
889             }
890 
891             boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
892                     Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
893             if (mService.mAtmInternal.canShowErrorDialogs() || showBackground) {
894                 proc.getDialogController().showAnrDialogs(data);
895             } else {
896                 MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
897                         AppNotRespondingDialog.CANT_SHOW);
898                 // Just kill the app if there is no dialog to be shown.
899                 mService.killAppAtUsersRequest(proc);
900             }
901         }
902         // Notify PackageWatchdog without the lock held
903         if (packageList != null) {
904             mPackageWatchdog.onPackageFailure(packageList,
905                     PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING);
906         }
907     }
908 
909     /**
910      * Information about a process that is currently marked as bad.
911      */
912     static final class BadProcessInfo {
913         BadProcessInfo(long time, String shortMsg, String longMsg, String stack) {
914             this.time = time;
915             this.shortMsg = shortMsg;
916             this.longMsg = longMsg;
917             this.stack = stack;
918         }
919 
920         final long time;
921         final String shortMsg;
922         final String longMsg;
923         final String stack;
924     }
925 
926 }
927