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