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