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