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                     () -> killAppImmediateLocked(p, "forced", "killed for invalid state"),
387                     5000L);
388         }
389     }
390 
391     /**
392      * Bring up the "unexpected error" dialog box for a crashing app.
393      * Deal with edge cases (intercepts from instrumented applications,
394      * ActivityController, error intent receivers, that sort of thing).
395      * @param r the application crashing
396      * @param crashInfo describing the failure
397      */
crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo)398     void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
399         final int callingPid = Binder.getCallingPid();
400         final int callingUid = Binder.getCallingUid();
401 
402         final long origId = Binder.clearCallingIdentity();
403         try {
404             crashApplicationInner(r, crashInfo, callingPid, callingUid);
405         } finally {
406             Binder.restoreCallingIdentity(origId);
407         }
408     }
409 
crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo, int callingPid, int callingUid)410     void crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo,
411             int callingPid, int callingUid) {
412         long timeMillis = System.currentTimeMillis();
413         String shortMsg = crashInfo.exceptionClassName;
414         String longMsg = crashInfo.exceptionMessage;
415         String stackTrace = crashInfo.stackTrace;
416         if (shortMsg != null && longMsg != null) {
417             longMsg = shortMsg + ": " + longMsg;
418         } else if (shortMsg != null) {
419             longMsg = shortMsg;
420         }
421 
422         if (r != null) {
423             boolean isApexModule = false;
424             try {
425                 for (String androidPackage : r.getPackageList()) {
426                     ModuleInfo moduleInfo = mContext.getPackageManager().getModuleInfo(
427                             androidPackage, /*flags=*/ 0);
428                     if (moduleInfo != null) {
429                         isApexModule = true;
430                         break;
431                     }
432                 }
433             } catch (IllegalStateException | PackageManager.NameNotFoundException e) {
434                 // Call to PackageManager#getModuleInfo() can result in NameNotFoundException or
435                 // IllegalStateException. In case they are thrown, there isn't much we can do
436                 // other than proceed with app crash handling.
437             }
438 
439             if (r.isPersistent() || isApexModule) {
440                 // If a persistent app or apex module is stuck in a crash loop, the device isn't
441                 // very usable, so we want to consider sending out a rescue party.
442                 RescueParty.noteAppCrash(mContext, r.uid);
443             }
444 
445             mPackageWatchdog.onPackageFailure(r.getPackageListWithVersionCode(),
446                     PackageWatchdog.FAILURE_REASON_APP_CRASH);
447         }
448 
449         final int relaunchReason = r != null
450                 ? r.getWindowProcessController().computeRelaunchReason() : RELAUNCH_REASON_NONE;
451 
452         AppErrorResult result = new AppErrorResult();
453         int taskId;
454         synchronized (mService) {
455             /**
456              * If crash is handled by instance of {@link android.app.IActivityController},
457              * finish now and don't show the app error dialog.
458              */
459             if (handleAppCrashInActivityController(r, crashInfo, shortMsg, longMsg, stackTrace,
460                     timeMillis, callingPid, callingUid)) {
461                 return;
462             }
463 
464             // Suppress crash dialog if the process is being relaunched due to a crash during a free
465             // resize.
466             if (relaunchReason == RELAUNCH_REASON_FREE_RESIZE) {
467                 return;
468             }
469 
470             /**
471              * If this process was running instrumentation, finish now - it will be handled in
472              * {@link ActivityManagerService#handleAppDiedLocked}.
473              */
474             if (r != null && r.getActiveInstrumentation() != null) {
475                 return;
476             }
477 
478             // Log crash in battery stats.
479             if (r != null) {
480                 mService.mBatteryStatsService.noteProcessCrash(r.processName, r.uid);
481             }
482 
483             AppErrorDialog.Data data = new AppErrorDialog.Data();
484             data.result = result;
485             data.proc = r;
486 
487             // If we can't identify the process or it's already exceeded its crash quota,
488             // quit right away without showing a crash dialog.
489             if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, data)) {
490                 return;
491             }
492 
493             final Message msg = Message.obtain();
494             msg.what = ActivityManagerService.SHOW_ERROR_UI_MSG;
495 
496             taskId = data.taskId;
497             msg.obj = data;
498             mService.mUiHandler.sendMessage(msg);
499         }
500 
501         int res = result.get();
502 
503         Intent appErrorIntent = null;
504         MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res);
505         if (res == AppErrorDialog.TIMEOUT || res == AppErrorDialog.CANCEL) {
506             res = AppErrorDialog.FORCE_QUIT;
507         }
508         synchronized (mService) {
509             if (res == AppErrorDialog.MUTE) {
510                 stopReportingCrashesLocked(r);
511             }
512             if (res == AppErrorDialog.RESTART) {
513                 mService.mProcessList.removeProcessLocked(r, false, true, "crash");
514                 if (taskId != INVALID_TASK_ID) {
515                     try {
516                         mService.startActivityFromRecents(taskId,
517                                 ActivityOptions.makeBasic().toBundle());
518                     } catch (IllegalArgumentException e) {
519                         // Hmm...that didn't work. Task should either be in recents or associated
520                         // with a stack.
521                         Slog.e(TAG, "Could not restart taskId=" + taskId, e);
522                     }
523                 }
524             }
525             if (res == AppErrorDialog.FORCE_QUIT) {
526                 long orig = Binder.clearCallingIdentity();
527                 try {
528                     // Kill it with fire!
529                     mService.mAtmInternal.onHandleAppCrash(r.getWindowProcessController());
530                     if (!r.isPersistent()) {
531                         mService.mProcessList.removeProcessLocked(r, false, false, "crash");
532                         mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
533                     }
534                 } finally {
535                     Binder.restoreCallingIdentity(orig);
536                 }
537             }
538             if (res == AppErrorDialog.APP_INFO) {
539                 appErrorIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
540                 appErrorIntent.setData(Uri.parse("package:" + r.info.packageName));
541                 appErrorIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
542             }
543             if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
544                 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
545             }
546             if (r != null && !r.isolated && res != AppErrorDialog.RESTART) {
547                 // XXX Can't keep track of crash time for isolated processes,
548                 // since they don't have a persistent identity.
549                 mProcessCrashTimes.put(r.info.processName, r.uid,
550                         SystemClock.uptimeMillis());
551             }
552         }
553 
554         if (appErrorIntent != null) {
555             try {
556                 mContext.startActivityAsUser(appErrorIntent, new UserHandle(r.userId));
557             } catch (ActivityNotFoundException e) {
558                 Slog.w(TAG, "bug report receiver dissappeared", e);
559             }
560         }
561     }
562 
handleAppCrashInActivityController(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo, String shortMsg, String longMsg, String stackTrace, long timeMillis, int callingPid, int callingUid)563     private boolean handleAppCrashInActivityController(ProcessRecord r,
564                                                        ApplicationErrorReport.CrashInfo crashInfo,
565                                                        String shortMsg, String longMsg,
566                                                        String stackTrace, long timeMillis,
567                                                        int callingPid, int callingUid) {
568         String name = r != null ? r.processName : null;
569         int pid = r != null ? r.pid : callingPid;
570         int uid = r != null ? r.info.uid : callingUid;
571 
572         return mService.mAtmInternal.handleAppCrashInActivityController(
573                 name, pid, shortMsg, longMsg, timeMillis, crashInfo.stackTrace, () -> {
574             if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"))
575                     && "Native crash".equals(crashInfo.exceptionClassName)) {
576                 Slog.w(TAG, "Skip killing native crashed app " + name
577                         + "(" + pid + ") during testing");
578             } else {
579                 Slog.w(TAG, "Force-killing crashed app " + name + " at watcher's request");
580                 if (r != null) {
581                     if (!makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, null)) {
582                         r.kill("crash", true);
583                     }
584                 } else {
585                     // Huh.
586                     Process.killProcess(pid);
587                     ProcessList.killProcessGroup(uid, pid);
588                 }
589             }
590         });
591     }
592 
593     private boolean makeAppCrashingLocked(ProcessRecord app,
594             String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
595         app.setCrashing(true);
596         app.crashingReport = generateProcessError(app,
597                 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
598         app.startAppProblemLocked();
599         app.getWindowProcessController().stopFreezingActivities();
600         return handleAppCrashLocked(app, "force-crash" /*reason*/, shortMsg, longMsg, stackTrace,
601                 data);
602     }
603 
604     /**
605      * Generate a process error record, suitable for attachment to a ProcessRecord.
606      *
607      * @param app The ProcessRecord in which the error occurred.
608      * @param condition Crashing, Application Not Responding, etc.  Values are defined in
609      *                      ActivityManager.ProcessErrorStateInfo
610      * @param activity The activity associated with the crash, if known.
611      * @param shortMsg Short message describing the crash.
612      * @param longMsg Long message describing the crash.
613      * @param stackTrace Full crash stack trace, may be null.
614      *
615      * @return Returns a fully-formed ProcessErrorStateInfo record.
616      */
617     ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
618             int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
619         ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
620 
621         report.condition = condition;
622         report.processName = app.processName;
623         report.pid = app.pid;
624         report.uid = app.info.uid;
625         report.tag = activity;
626         report.shortMsg = shortMsg;
627         report.longMsg = longMsg;
628         report.stackTrace = stackTrace;
629 
630         return report;
631     }
632 
633     Intent createAppErrorIntentLocked(ProcessRecord r,
634             long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
635         ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
636         if (report == null) {
637             return null;
638         }
639         Intent result = new Intent(Intent.ACTION_APP_ERROR);
640         result.setComponent(r.errorReportReceiver);
641         result.putExtra(Intent.EXTRA_BUG_REPORT, report);
642         result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
643         return result;
644     }
645 
646     private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
647             long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
648         if (r.errorReportReceiver == null) {
649             return null;
650         }
651 
652         if (!r.isCrashing() && !r.isNotResponding() && !r.forceCrashReport) {
653             return null;
654         }
655 
656         ApplicationErrorReport report = new ApplicationErrorReport();
657         report.packageName = r.info.packageName;
658         report.installerPackageName = r.errorReportReceiver.getPackageName();
659         report.processName = r.processName;
660         report.time = timeMillis;
661         report.systemApp = (r.info.flags & FLAG_SYSTEM) != 0;
662 
663         if (r.isCrashing() || r.forceCrashReport) {
664             report.type = ApplicationErrorReport.TYPE_CRASH;
665             report.crashInfo = crashInfo;
666         } else if (r.isNotResponding()) {
667             report.type = ApplicationErrorReport.TYPE_ANR;
668             report.anrInfo = new ApplicationErrorReport.AnrInfo();
669 
670             report.anrInfo.activity = r.notRespondingReport.tag;
671             report.anrInfo.cause = r.notRespondingReport.shortMsg;
672             report.anrInfo.info = r.notRespondingReport.longMsg;
673         }
674 
675         return report;
676     }
677 
678     boolean handleAppCrashLocked(ProcessRecord app, String reason,
679             String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
680         final long now = SystemClock.uptimeMillis();
681         final boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
682                 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
683 
684         final boolean procIsBoundForeground =
685             (app.getCurProcState() == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
686 
687         Long crashTime;
688         Long crashTimePersistent;
689         boolean tryAgain = false;
690 
691         if (!app.isolated) {
692             crashTime = mProcessCrashTimes.get(app.info.processName, app.uid);
693             crashTimePersistent = mProcessCrashTimesPersistent.get(app.info.processName, app.uid);
694         } else {
695             crashTime = crashTimePersistent = null;
696         }
697 
698         // Bump up the crash count of any services currently running in the proc.
699         for (int i = app.services.size() - 1; i >= 0; i--) {
700             // Any services running in the application need to be placed
701             // back in the pending list.
702             ServiceRecord sr = app.services.valueAt(i);
703             // If the service was restarted a while ago, then reset crash count, else increment it.
704             if (now > sr.restartTime + ProcessList.MIN_CRASH_INTERVAL) {
705                 sr.crashCount = 1;
706             } else {
707                 sr.crashCount++;
708             }
709             // Allow restarting for started or bound foreground services that are crashing.
710             // This includes wallpapers.
711             if (sr.crashCount < mService.mConstants.BOUND_SERVICE_MAX_CRASH_RETRY
712                     && (sr.isForeground || procIsBoundForeground)) {
713                 tryAgain = true;
714             }
715         }
716 
717         if (crashTime != null && now < crashTime + ProcessList.MIN_CRASH_INTERVAL) {
718             // The process crashed again very quickly. If it was a bound foreground service, let's
719             // try to restart again in a while, otherwise the process loses!
720             Slog.w(TAG, "Process " + app.info.processName
721                     + " has crashed too many times: killing!");
722             EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
723                     app.userId, app.info.processName, app.uid);
724             mService.mAtmInternal.onHandleAppCrash(app.getWindowProcessController());
725             if (!app.isPersistent()) {
726                 // We don't want to start this process again until the user
727                 // explicitly does so...  but for persistent process, we really
728                 // need to keep it running.  If a persistent process is actually
729                 // repeatedly crashing, then badness for everyone.
730                 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.userId, app.uid,
731                         app.info.processName);
732                 if (!app.isolated) {
733                     // XXX We don't have a way to mark isolated processes
734                     // as bad, since they don't have a peristent identity.
735                     mBadProcesses.put(app.info.processName, app.uid,
736                             new BadProcessInfo(now, shortMsg, longMsg, stackTrace));
737                     mProcessCrashTimes.remove(app.info.processName, app.uid);
738                 }
739                 app.bad = true;
740                 app.removed = true;
741                 // Don't let services in this process be restarted and potentially
742                 // annoy the user repeatedly.  Unless it is persistent, since those
743                 // processes run critical code.
744                 mService.mProcessList.removeProcessLocked(app, false, tryAgain, "crash");
745                 mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
746                 if (!showBackground) {
747                     return false;
748                 }
749             }
750             mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
751         } else {
752             final int affectedTaskId = mService.mAtmInternal.finishTopCrashedActivities(
753                             app.getWindowProcessController(), reason);
754             if (data != null) {
755                 data.taskId = affectedTaskId;
756             }
757             if (data != null && crashTimePersistent != null
758                     && now < crashTimePersistent + ProcessList.MIN_CRASH_INTERVAL) {
759                 data.repeating = true;
760             }
761         }
762 
763         if (data != null && tryAgain) {
764             data.isRestartableForService = true;
765         }
766 
767         // If the crashing process is what we consider to be the "home process" and it has been
768         // replaced by a third-party app, clear the package preferred activities from packages
769         // with a home activity running in the process to prevent a repeatedly crashing app
770         // from blocking the user to manually clear the list.
771         final WindowProcessController proc = app.getWindowProcessController();
772         final WindowProcessController homeProc = mService.mAtmInternal.getHomeProcess();
773         if (proc == homeProc && proc.hasActivities()
774                 && (((ProcessRecord) homeProc.mOwner).info.flags & FLAG_SYSTEM) == 0) {
775             proc.clearPackagePreferredForHomeActivities();
776         }
777 
778         if (!app.isolated) {
779             // XXX Can't keep track of crash times for isolated processes,
780             // because they don't have a persistent identity.
781             mProcessCrashTimes.put(app.info.processName, app.uid, now);
782             mProcessCrashTimesPersistent.put(app.info.processName, app.uid, now);
783         }
784 
785         if (app.crashHandler != null) mService.mHandler.post(app.crashHandler);
786         return true;
787     }
788 
789     void handleShowAppErrorUi(Message msg) {
790         AppErrorDialog.Data data = (AppErrorDialog.Data) msg.obj;
791         boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
792                 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
793 
794         AppErrorDialog dialogToShow = null;
795         final String packageName;
796         final int userId;
797         synchronized (mService) {
798             final ProcessRecord proc = data.proc;
799             final AppErrorResult res = data.result;
800             if (proc == null) {
801                 Slog.e(TAG, "handleShowAppErrorUi: proc is null");
802                 return;
803             }
804             packageName = proc.info.packageName;
805             userId = proc.userId;
806             if (proc.crashDialog != null) {
807                 Slog.e(TAG, "App already has crash dialog: " + proc);
808                 if (res != null) {
809                     res.set(AppErrorDialog.ALREADY_SHOWING);
810                 }
811                 return;
812             }
813             boolean isBackground = (UserHandle.getAppId(proc.uid)
814                     >= Process.FIRST_APPLICATION_UID
815                     && proc.pid != MY_PID);
816             for (int profileId : mService.mUserController.getCurrentProfileIds()) {
817                 isBackground &= (userId != profileId);
818             }
819             if (isBackground && !showBackground) {
820                 Slog.w(TAG, "Skipping crash dialog of " + proc + ": background");
821                 if (res != null) {
822                     res.set(AppErrorDialog.BACKGROUND_USER);
823                 }
824                 return;
825             }
826             final boolean showFirstCrash = Settings.Global.getInt(
827                     mContext.getContentResolver(),
828                     Settings.Global.SHOW_FIRST_CRASH_DIALOG, 0) != 0;
829             final boolean showFirstCrashDevOption = Settings.Secure.getIntForUser(
830                     mContext.getContentResolver(),
831                     Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION,
832                     0,
833                     mService.mUserController.getCurrentUserId()) != 0;
834             final boolean crashSilenced = mAppsNotReportingCrashes != null &&
835                     mAppsNotReportingCrashes.contains(proc.info.packageName);
836             if ((mService.mAtmInternal.canShowErrorDialogs() || showBackground)
837                     && !crashSilenced
838                     && (showFirstCrash || showFirstCrashDevOption || data.repeating)) {
839                 proc.crashDialog = dialogToShow = new AppErrorDialog(mContext, mService, data);
840             } else {
841                 // The device is asleep, so just pretend that the user
842                 // saw a crash dialog and hit "force quit".
843                 if (res != null) {
844                     res.set(AppErrorDialog.CANT_SHOW);
845                 }
846             }
847         }
848         // If we've created a crash dialog, show it without the lock held
849         if (dialogToShow != null) {
850             Slog.i(TAG, "Showing crash dialog for package " + packageName + " u" + userId);
851             dialogToShow.show();
852         }
853     }
854 
855     private void stopReportingCrashesLocked(ProcessRecord proc) {
856         if (mAppsNotReportingCrashes == null) {
857             mAppsNotReportingCrashes = new ArraySet<>();
858         }
859         mAppsNotReportingCrashes.add(proc.info.packageName);
860     }
861 
862     void handleShowAnrUi(Message msg) {
863         Dialog dialogToShow = null;
864         List<VersionedPackage> packageList = null;
865         synchronized (mService) {
866             AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj;
867             final ProcessRecord proc = data.proc;
868             if (proc == null) {
869                 Slog.e(TAG, "handleShowAnrUi: proc is null");
870                 return;
871             }
872             if (!proc.isPersistent()) {
873                 packageList = proc.getPackageListWithVersionCode();
874             }
875             if (proc.anrDialog != null) {
876                 Slog.e(TAG, "App already has anr dialog: " + proc);
877                 MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
878                         AppNotRespondingDialog.ALREADY_SHOWING);
879                 return;
880             }
881 
882             boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
883                     Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
884             if (mService.mAtmInternal.canShowErrorDialogs() || showBackground) {
885                 dialogToShow = new AppNotRespondingDialog(mService, mContext, data);
886                 proc.anrDialog = dialogToShow;
887             } else {
888                 MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
889                         AppNotRespondingDialog.CANT_SHOW);
890                 // Just kill the app if there is no dialog to be shown.
891                 mService.killAppAtUsersRequest(proc, null);
892             }
893         }
894         // If we've created a crash dialog, show it without the lock held
895         if (dialogToShow != null) {
896             dialogToShow.show();
897         }
898         // Notify PackageWatchdog without the lock held
899         if (packageList != null) {
900             mPackageWatchdog.onPackageFailure(packageList,
901                     PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING);
902         }
903     }
904 
905     /**
906      * Information about a process that is currently marked as bad.
907      */
908     static final class BadProcessInfo {
909         BadProcessInfo(long time, String shortMsg, String longMsg, String stack) {
910             this.time = time;
911             this.shortMsg = shortMsg;
912             this.longMsg = longMsg;
913             this.stack = stack;
914         }
915 
916         final long time;
917         final String shortMsg;
918         final String longMsg;
919         final String stack;
920     }
921 
922 }
923