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 com.android.internal.app.ProcessMap;
20 import com.android.internal.logging.MetricsLogger;
21 import com.android.internal.logging.nano.MetricsProto;
22 import com.android.internal.os.ProcessCpuTracker;
23 import com.android.server.RescueParty;
24 import com.android.server.Watchdog;
25 
26 import android.app.ActivityManager;
27 import android.app.ActivityOptions;
28 import android.app.ActivityThread;
29 import android.app.AppOpsManager;
30 import android.app.ApplicationErrorReport;
31 import android.app.Dialog;
32 import android.content.ActivityNotFoundException;
33 import android.content.Context;
34 import android.content.Intent;
35 import android.content.pm.ApplicationInfo;
36 import android.os.Binder;
37 import android.os.Message;
38 import android.os.Process;
39 import android.os.RemoteException;
40 import android.os.SystemClock;
41 import android.os.SystemProperties;
42 import android.os.UserHandle;
43 import android.provider.Settings;
44 import android.util.ArrayMap;
45 import android.util.ArraySet;
46 import android.util.EventLog;
47 import android.util.Log;
48 import android.util.Slog;
49 import android.util.SparseArray;
50 import android.util.TimeUtils;
51 
52 import java.io.File;
53 import java.io.FileDescriptor;
54 import java.io.PrintWriter;
55 import java.util.ArrayList;
56 import java.util.Collections;
57 import java.util.HashMap;
58 import java.util.Set;
59 
60 import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST;
61 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
62 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
63 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
64 import static com.android.server.am.ActivityManagerService.MY_PID;
65 import static com.android.server.am.ActivityManagerService.SYSTEM_DEBUGGABLE;
66 
67 /**
68  * Controls error conditions in applications.
69  */
70 class AppErrors {
71 
72     private static final String TAG = TAG_WITH_CLASS_NAME ? "AppErrors" : TAG_AM;
73 
74     private final ActivityManagerService mService;
75     private final Context mContext;
76 
77     private ArraySet<String> mAppsNotReportingCrashes;
78 
79     /**
80      * The last time that various processes have crashed since they were last explicitly started.
81      */
82     private final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<>();
83 
84     /**
85      * The last time that various processes have crashed (not reset even when explicitly started).
86      */
87     private final ProcessMap<Long> mProcessCrashTimesPersistent = new ProcessMap<>();
88 
89     /**
90      * Set of applications that we consider to be bad, and will reject
91      * incoming broadcasts from (which the user has no control over).
92      * Processes are added to this set when they have crashed twice within
93      * a minimum amount of time; they are removed from it when they are
94      * later restarted (hopefully due to some user action).  The value is the
95      * time it was added to the list.
96      */
97     private final ProcessMap<BadProcessInfo> mBadProcesses = new ProcessMap<>();
98 
99 
AppErrors(Context context, ActivityManagerService service)100     AppErrors(Context context, ActivityManagerService service) {
101         context.assertRuntimeOverlayThemable();
102         mService = service;
103         mContext = context;
104     }
105 
dumpLocked(FileDescriptor fd, PrintWriter pw, boolean needSep, String dumpPackage)106     boolean dumpLocked(FileDescriptor fd, PrintWriter pw, boolean needSep,
107             String dumpPackage) {
108         if (!mProcessCrashTimes.getMap().isEmpty()) {
109             boolean printed = false;
110             final long now = SystemClock.uptimeMillis();
111             final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap();
112             final int processCount = pmap.size();
113             for (int ip = 0; ip < processCount; ip++) {
114                 final String pname = pmap.keyAt(ip);
115                 final SparseArray<Long> uids = pmap.valueAt(ip);
116                 final int uidCount = uids.size();
117                 for (int i = 0; i < uidCount; i++) {
118                     final int puid = uids.keyAt(i);
119                     final ProcessRecord r = mService.mProcessNames.get(pname, puid);
120                     if (dumpPackage != null && (r == null
121                             || !r.pkgList.containsKey(dumpPackage))) {
122                         continue;
123                     }
124                     if (!printed) {
125                         if (needSep) pw.println();
126                         needSep = true;
127                         pw.println("  Time since processes crashed:");
128                         printed = true;
129                     }
130                     pw.print("    Process "); pw.print(pname);
131                     pw.print(" uid "); pw.print(puid);
132                     pw.print(": last crashed ");
133                     TimeUtils.formatDuration(now-uids.valueAt(i), pw);
134                     pw.println(" ago");
135                 }
136             }
137         }
138 
139         if (!mBadProcesses.getMap().isEmpty()) {
140             boolean printed = false;
141             final ArrayMap<String, SparseArray<BadProcessInfo>> pmap = mBadProcesses.getMap();
142             final int processCount = pmap.size();
143             for (int ip = 0; ip < processCount; ip++) {
144                 final String pname = pmap.keyAt(ip);
145                 final SparseArray<BadProcessInfo> uids = pmap.valueAt(ip);
146                 final int uidCount = uids.size();
147                 for (int i = 0; i < uidCount; i++) {
148                     final int puid = uids.keyAt(i);
149                     final ProcessRecord r = mService.mProcessNames.get(pname, puid);
150                     if (dumpPackage != null && (r == null
151                             || !r.pkgList.containsKey(dumpPackage))) {
152                         continue;
153                     }
154                     if (!printed) {
155                         if (needSep) pw.println();
156                         needSep = true;
157                         pw.println("  Bad processes:");
158                         printed = true;
159                     }
160                     final BadProcessInfo info = uids.valueAt(i);
161                     pw.print("    Bad process "); pw.print(pname);
162                     pw.print(" uid "); pw.print(puid);
163                     pw.print(": crashed at time "); pw.println(info.time);
164                     if (info.shortMsg != null) {
165                         pw.print("      Short msg: "); pw.println(info.shortMsg);
166                     }
167                     if (info.longMsg != null) {
168                         pw.print("      Long msg: "); pw.println(info.longMsg);
169                     }
170                     if (info.stack != null) {
171                         pw.println("      Stack:");
172                         int lastPos = 0;
173                         for (int pos = 0; pos < info.stack.length(); pos++) {
174                             if (info.stack.charAt(pos) == '\n') {
175                                 pw.print("        ");
176                                 pw.write(info.stack, lastPos, pos-lastPos);
177                                 pw.println();
178                                 lastPos = pos+1;
179                             }
180                         }
181                         if (lastPos < info.stack.length()) {
182                             pw.print("        ");
183                             pw.write(info.stack, lastPos, info.stack.length()-lastPos);
184                             pw.println();
185                         }
186                     }
187                 }
188             }
189         }
190         return needSep;
191     }
192 
isBadProcessLocked(ApplicationInfo info)193     boolean isBadProcessLocked(ApplicationInfo info) {
194         return mBadProcesses.get(info.processName, info.uid) != null;
195     }
196 
clearBadProcessLocked(ApplicationInfo info)197     void clearBadProcessLocked(ApplicationInfo info) {
198         mBadProcesses.remove(info.processName, info.uid);
199     }
200 
resetProcessCrashTimeLocked(ApplicationInfo info)201     void resetProcessCrashTimeLocked(ApplicationInfo info) {
202         mProcessCrashTimes.remove(info.processName, info.uid);
203     }
204 
resetProcessCrashTimeLocked(boolean resetEntireUser, int appId, int userId)205     void resetProcessCrashTimeLocked(boolean resetEntireUser, int appId, int userId) {
206         final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap();
207         for (int ip = pmap.size() - 1; ip >= 0; ip--) {
208             SparseArray<Long> ba = pmap.valueAt(ip);
209             for (int i = ba.size() - 1; i >= 0; i--) {
210                 boolean remove = false;
211                 final int entUid = ba.keyAt(i);
212                 if (!resetEntireUser) {
213                     if (userId == UserHandle.USER_ALL) {
214                         if (UserHandle.getAppId(entUid) == appId) {
215                             remove = true;
216                         }
217                     } else {
218                         if (entUid == UserHandle.getUid(userId, appId)) {
219                             remove = true;
220                         }
221                     }
222                 } else if (UserHandle.getUserId(entUid) == userId) {
223                     remove = true;
224                 }
225                 if (remove) {
226                     ba.removeAt(i);
227                 }
228             }
229             if (ba.size() == 0) {
230                 pmap.removeAt(ip);
231             }
232         }
233     }
234 
loadAppsNotReportingCrashesFromConfigLocked(String appsNotReportingCrashesConfig)235     void loadAppsNotReportingCrashesFromConfigLocked(String appsNotReportingCrashesConfig) {
236         if (appsNotReportingCrashesConfig != null) {
237             final String[] split = appsNotReportingCrashesConfig.split(",");
238             if (split.length > 0) {
239                 mAppsNotReportingCrashes = new ArraySet<>();
240                 Collections.addAll(mAppsNotReportingCrashes, split);
241             }
242         }
243     }
244 
killAppAtUserRequestLocked(ProcessRecord app, Dialog fromDialog)245     void killAppAtUserRequestLocked(ProcessRecord app, Dialog fromDialog) {
246         app.crashing = false;
247         app.crashingReport = null;
248         app.notResponding = false;
249         app.notRespondingReport = null;
250         if (app.anrDialog == fromDialog) {
251             app.anrDialog = null;
252         }
253         if (app.waitDialog == fromDialog) {
254             app.waitDialog = null;
255         }
256         if (app.pid > 0 && app.pid != MY_PID) {
257             handleAppCrashLocked(app, "user-terminated" /*reason*/,
258                     null /*shortMsg*/, null /*longMsg*/, null /*stackTrace*/, null /*data*/);
259             app.kill("user request after error", true);
260         }
261     }
262 
263     /**
264      * Induce a crash in the given app.
265      *
266      * @param uid if nonnegative, the required matching uid of the target to crash
267      * @param initialPid fast-path match for the target to crash
268      * @param packageName fallback match if the stated pid is not found or doesn't match uid
269      * @param userId If nonnegative, required to identify a match by package name
270      * @param message
271      */
scheduleAppCrashLocked(int uid, int initialPid, String packageName, int userId, String message)272     void scheduleAppCrashLocked(int uid, int initialPid, String packageName, int userId,
273             String message) {
274         ProcessRecord proc = null;
275 
276         // Figure out which process to kill.  We don't trust that initialPid
277         // still has any relation to current pids, so must scan through the
278         // list.
279 
280         synchronized (mService.mPidsSelfLocked) {
281             for (int i=0; i<mService.mPidsSelfLocked.size(); i++) {
282                 ProcessRecord p = mService.mPidsSelfLocked.valueAt(i);
283                 if (uid >= 0 && p.uid != uid) {
284                     continue;
285                 }
286                 if (p.pid == initialPid) {
287                     proc = p;
288                     break;
289                 }
290                 if (p.pkgList.containsKey(packageName)
291                         && (userId < 0 || p.userId == userId)) {
292                     proc = p;
293                 }
294             }
295         }
296 
297         if (proc == null) {
298             Slog.w(TAG, "crashApplication: nothing for uid=" + uid
299                     + " initialPid=" + initialPid
300                     + " packageName=" + packageName
301                     + " userId=" + userId);
302             return;
303         }
304 
305         proc.scheduleCrash(message);
306     }
307 
308     /**
309      * Bring up the "unexpected error" dialog box for a crashing app.
310      * Deal with edge cases (intercepts from instrumented applications,
311      * ActivityController, error intent receivers, that sort of thing).
312      * @param r the application crashing
313      * @param crashInfo describing the failure
314      */
crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo)315     void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
316         final int callingPid = Binder.getCallingPid();
317         final int callingUid = Binder.getCallingUid();
318 
319         final long origId = Binder.clearCallingIdentity();
320         try {
321             crashApplicationInner(r, crashInfo, callingPid, callingUid);
322         } finally {
323             Binder.restoreCallingIdentity(origId);
324         }
325     }
326 
crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo, int callingPid, int callingUid)327     void crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo,
328             int callingPid, int callingUid) {
329         long timeMillis = System.currentTimeMillis();
330         String shortMsg = crashInfo.exceptionClassName;
331         String longMsg = crashInfo.exceptionMessage;
332         String stackTrace = crashInfo.stackTrace;
333         if (shortMsg != null && longMsg != null) {
334             longMsg = shortMsg + ": " + longMsg;
335         } else if (shortMsg != null) {
336             longMsg = shortMsg;
337         }
338 
339         // If a persistent app is stuck in a crash loop, the device isn't very
340         // usable, so we want to consider sending out a rescue party.
341         if (r != null && r.persistent) {
342             RescueParty.notePersistentAppCrash(mContext, r.uid);
343         }
344 
345         AppErrorResult result = new AppErrorResult();
346         TaskRecord task;
347         synchronized (mService) {
348             /**
349              * If crash is handled by instance of {@link android.app.IActivityController},
350              * finish now and don't show the app error dialog.
351              */
352             if (handleAppCrashInActivityController(r, crashInfo, shortMsg, longMsg, stackTrace,
353                     timeMillis, callingPid, callingUid)) {
354                 return;
355             }
356 
357             /**
358              * If this process was running instrumentation, finish now - it will be handled in
359              * {@link ActivityManagerService#handleAppDiedLocked}.
360              */
361             if (r != null && r.instr != null) {
362                 return;
363             }
364 
365             // Log crash in battery stats.
366             if (r != null) {
367                 mService.mBatteryStatsService.noteProcessCrash(r.processName, r.uid);
368             }
369 
370             AppErrorDialog.Data data = new AppErrorDialog.Data();
371             data.result = result;
372             data.proc = r;
373 
374             // If we can't identify the process or it's already exceeded its crash quota,
375             // quit right away without showing a crash dialog.
376             if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, data)) {
377                 return;
378             }
379 
380             final Message msg = Message.obtain();
381             msg.what = ActivityManagerService.SHOW_ERROR_UI_MSG;
382 
383             task = data.task;
384             msg.obj = data;
385             mService.mUiHandler.sendMessage(msg);
386         }
387 
388         int res = result.get();
389 
390         Intent appErrorIntent = null;
391         MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res);
392         if (res == AppErrorDialog.TIMEOUT || res == AppErrorDialog.CANCEL) {
393             res = AppErrorDialog.FORCE_QUIT;
394         }
395         synchronized (mService) {
396             if (res == AppErrorDialog.MUTE) {
397                 stopReportingCrashesLocked(r);
398             }
399             if (res == AppErrorDialog.RESTART) {
400                 mService.removeProcessLocked(r, false, true, "crash");
401                 if (task != null) {
402                     try {
403                         mService.startActivityFromRecents(task.taskId,
404                                 ActivityOptions.makeBasic().toBundle());
405                     } catch (IllegalArgumentException e) {
406                         // Hmm, that didn't work, app might have crashed before creating a
407                         // recents entry. Let's see if we have a safe-to-restart intent.
408                         final Set<String> cats = task.intent.getCategories();
409                         if (cats != null && cats.contains(Intent.CATEGORY_LAUNCHER)) {
410                             mService.startActivityInPackage(task.mCallingUid,
411                                     task.mCallingPackage, task.intent,
412                                     null, null, null, 0, 0,
413                                     ActivityOptions.makeBasic().toBundle(),
414                                     task.userId, null, null, "AppErrors");
415                         }
416                     }
417                 }
418             }
419             if (res == AppErrorDialog.FORCE_QUIT) {
420                 long orig = Binder.clearCallingIdentity();
421                 try {
422                     // Kill it with fire!
423                     mService.mStackSupervisor.handleAppCrashLocked(r);
424                     if (!r.persistent) {
425                         mService.removeProcessLocked(r, false, false, "crash");
426                         mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
427                     }
428                 } finally {
429                     Binder.restoreCallingIdentity(orig);
430                 }
431             }
432             if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
433                 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
434             }
435             if (r != null && !r.isolated && res != AppErrorDialog.RESTART) {
436                 // XXX Can't keep track of crash time for isolated processes,
437                 // since they don't have a persistent identity.
438                 mProcessCrashTimes.put(r.info.processName, r.uid,
439                         SystemClock.uptimeMillis());
440             }
441         }
442 
443         if (appErrorIntent != null) {
444             try {
445                 mContext.startActivityAsUser(appErrorIntent, new UserHandle(r.userId));
446             } catch (ActivityNotFoundException e) {
447                 Slog.w(TAG, "bug report receiver dissappeared", e);
448             }
449         }
450     }
451 
handleAppCrashInActivityController(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo, String shortMsg, String longMsg, String stackTrace, long timeMillis, int callingPid, int callingUid)452     private boolean handleAppCrashInActivityController(ProcessRecord r,
453                                                        ApplicationErrorReport.CrashInfo crashInfo,
454                                                        String shortMsg, String longMsg,
455                                                        String stackTrace, long timeMillis,
456                                                        int callingPid, int callingUid) {
457         if (mService.mController == null) {
458             return false;
459         }
460 
461         try {
462             String name = r != null ? r.processName : null;
463             int pid = r != null ? r.pid : callingPid;
464             int uid = r != null ? r.info.uid : callingUid;
465             if (!mService.mController.appCrashed(name, pid,
466                     shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
467                 if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"))
468                         && "Native crash".equals(crashInfo.exceptionClassName)) {
469                     Slog.w(TAG, "Skip killing native crashed app " + name
470                             + "(" + pid + ") during testing");
471                 } else {
472                     Slog.w(TAG, "Force-killing crashed app " + name
473                             + " at watcher's request");
474                     if (r != null) {
475                         if (!makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, null))
476                         {
477                             r.kill("crash", true);
478                         }
479                     } else {
480                         // Huh.
481                         Process.killProcess(pid);
482                         ActivityManagerService.killProcessGroup(uid, pid);
483                     }
484                 }
485                 return true;
486             }
487         } catch (RemoteException e) {
488             mService.mController = null;
489             Watchdog.getInstance().setActivityController(null);
490         }
491         return false;
492     }
493 
makeAppCrashingLocked(ProcessRecord app, String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data)494     private boolean makeAppCrashingLocked(ProcessRecord app,
495             String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
496         app.crashing = true;
497         app.crashingReport = generateProcessError(app,
498                 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
499         startAppProblemLocked(app);
500         app.stopFreezingAllLocked();
501         return handleAppCrashLocked(app, "force-crash" /*reason*/, shortMsg, longMsg, stackTrace,
502                 data);
503     }
504 
startAppProblemLocked(ProcessRecord app)505     void startAppProblemLocked(ProcessRecord app) {
506         // If this app is not running under the current user, then we
507         // can't give it a report button because that would require
508         // launching the report UI under a different user.
509         app.errorReportReceiver = null;
510 
511         for (int userId : mService.mUserController.getCurrentProfileIdsLocked()) {
512             if (app.userId == userId) {
513                 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
514                         mContext, app.info.packageName, app.info.flags);
515             }
516         }
517         mService.skipCurrentReceiverLocked(app);
518     }
519 
520     /**
521      * Generate a process error record, suitable for attachment to a ProcessRecord.
522      *
523      * @param app The ProcessRecord in which the error occurred.
524      * @param condition Crashing, Application Not Responding, etc.  Values are defined in
525      *                      ActivityManager.AppErrorStateInfo
526      * @param activity The activity associated with the crash, if known.
527      * @param shortMsg Short message describing the crash.
528      * @param longMsg Long message describing the crash.
529      * @param stackTrace Full crash stack trace, may be null.
530      *
531      * @return Returns a fully-formed AppErrorStateInfo record.
532      */
generateProcessError(ProcessRecord app, int condition, String activity, String shortMsg, String longMsg, String stackTrace)533     private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
534             int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
535         ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
536 
537         report.condition = condition;
538         report.processName = app.processName;
539         report.pid = app.pid;
540         report.uid = app.info.uid;
541         report.tag = activity;
542         report.shortMsg = shortMsg;
543         report.longMsg = longMsg;
544         report.stackTrace = stackTrace;
545 
546         return report;
547     }
548 
createAppErrorIntentLocked(ProcessRecord r, long timeMillis, ApplicationErrorReport.CrashInfo crashInfo)549     Intent createAppErrorIntentLocked(ProcessRecord r,
550             long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
551         ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
552         if (report == null) {
553             return null;
554         }
555         Intent result = new Intent(Intent.ACTION_APP_ERROR);
556         result.setComponent(r.errorReportReceiver);
557         result.putExtra(Intent.EXTRA_BUG_REPORT, report);
558         result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
559         return result;
560     }
561 
createAppErrorReportLocked(ProcessRecord r, long timeMillis, ApplicationErrorReport.CrashInfo crashInfo)562     private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
563             long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
564         if (r.errorReportReceiver == null) {
565             return null;
566         }
567 
568         if (!r.crashing && !r.notResponding && !r.forceCrashReport) {
569             return null;
570         }
571 
572         ApplicationErrorReport report = new ApplicationErrorReport();
573         report.packageName = r.info.packageName;
574         report.installerPackageName = r.errorReportReceiver.getPackageName();
575         report.processName = r.processName;
576         report.time = timeMillis;
577         report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
578 
579         if (r.crashing || r.forceCrashReport) {
580             report.type = ApplicationErrorReport.TYPE_CRASH;
581             report.crashInfo = crashInfo;
582         } else if (r.notResponding) {
583             report.type = ApplicationErrorReport.TYPE_ANR;
584             report.anrInfo = new ApplicationErrorReport.AnrInfo();
585 
586             report.anrInfo.activity = r.notRespondingReport.tag;
587             report.anrInfo.cause = r.notRespondingReport.shortMsg;
588             report.anrInfo.info = r.notRespondingReport.longMsg;
589         }
590 
591         return report;
592     }
593 
handleAppCrashLocked(ProcessRecord app, String reason, String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data)594     boolean handleAppCrashLocked(ProcessRecord app, String reason,
595             String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
596         long now = SystemClock.uptimeMillis();
597         boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
598                 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
599 
600         Long crashTime;
601         Long crashTimePersistent;
602         if (!app.isolated) {
603             crashTime = mProcessCrashTimes.get(app.info.processName, app.uid);
604             crashTimePersistent = mProcessCrashTimesPersistent.get(app.info.processName, app.uid);
605         } else {
606             crashTime = crashTimePersistent = null;
607         }
608         if (crashTime != null && now < crashTime+ProcessList.MIN_CRASH_INTERVAL) {
609             // This process loses!
610             Slog.w(TAG, "Process " + app.info.processName
611                     + " has crashed too many times: killing!");
612             EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
613                     app.userId, app.info.processName, app.uid);
614             mService.mStackSupervisor.handleAppCrashLocked(app);
615             if (!app.persistent) {
616                 // We don't want to start this process again until the user
617                 // explicitly does so...  but for persistent process, we really
618                 // need to keep it running.  If a persistent process is actually
619                 // repeatedly crashing, then badness for everyone.
620                 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.userId, app.uid,
621                         app.info.processName);
622                 if (!app.isolated) {
623                     // XXX We don't have a way to mark isolated processes
624                     // as bad, since they don't have a peristent identity.
625                     mBadProcesses.put(app.info.processName, app.uid,
626                             new BadProcessInfo(now, shortMsg, longMsg, stackTrace));
627                     mProcessCrashTimes.remove(app.info.processName, app.uid);
628                 }
629                 app.bad = true;
630                 app.removed = true;
631                 // Don't let services in this process be restarted and potentially
632                 // annoy the user repeatedly.  Unless it is persistent, since those
633                 // processes run critical code.
634                 mService.removeProcessLocked(app, false, false, "crash");
635                 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
636                 if (!showBackground) {
637                     return false;
638                 }
639             }
640             mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
641         } else {
642             TaskRecord affectedTask =
643                     mService.mStackSupervisor.finishTopRunningActivityLocked(app, reason);
644             if (data != null) {
645                 data.task = affectedTask;
646             }
647             if (data != null && crashTimePersistent != null
648                     && now < crashTimePersistent + ProcessList.MIN_CRASH_INTERVAL) {
649                 data.repeating = true;
650             }
651         }
652 
653         boolean procIsBoundForeground =
654                 (app.curProcState == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
655         // Bump up the crash count of any services currently running in the proc.
656         for (int i=app.services.size()-1; i>=0; i--) {
657             // Any services running in the application need to be placed
658             // back in the pending list.
659             ServiceRecord sr = app.services.valueAt(i);
660             sr.crashCount++;
661 
662             // Allow restarting for started or bound foreground services that are crashing the
663             // first time. This includes wallpapers.
664             if ((data != null) && (sr.crashCount <= 1)
665                     && (sr.isForeground || procIsBoundForeground)) {
666                 data.isRestartableForService = true;
667             }
668         }
669 
670         // If the crashing process is what we consider to be the "home process" and it has been
671         // replaced by a third-party app, clear the package preferred activities from packages
672         // with a home activity running in the process to prevent a repeatedly crashing app
673         // from blocking the user to manually clear the list.
674         final ArrayList<ActivityRecord> activities = app.activities;
675         if (app == mService.mHomeProcess && activities.size() > 0
676                 && (mService.mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
677             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
678                 final ActivityRecord r = activities.get(activityNdx);
679                 if (r.isHomeActivity()) {
680                     Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
681                     try {
682                         ActivityThread.getPackageManager()
683                                 .clearPackagePreferredActivities(r.packageName);
684                     } catch (RemoteException c) {
685                         // pm is in same process, this will never happen.
686                     }
687                 }
688             }
689         }
690 
691         if (!app.isolated) {
692             // XXX Can't keep track of crash times for isolated processes,
693             // because they don't have a perisistent identity.
694             mProcessCrashTimes.put(app.info.processName, app.uid, now);
695             mProcessCrashTimesPersistent.put(app.info.processName, app.uid, now);
696         }
697 
698         if (app.crashHandler != null) mService.mHandler.post(app.crashHandler);
699         return true;
700     }
701 
handleShowAppErrorUi(Message msg)702     void handleShowAppErrorUi(Message msg) {
703         AppErrorDialog.Data data = (AppErrorDialog.Data) msg.obj;
704         boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
705                 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
706         synchronized (mService) {
707             ProcessRecord proc = data.proc;
708             AppErrorResult res = data.result;
709             if (proc != null && proc.crashDialog != null) {
710                 Slog.e(TAG, "App already has crash dialog: " + proc);
711                 if (res != null) {
712                     res.set(AppErrorDialog.ALREADY_SHOWING);
713                 }
714                 return;
715             }
716             boolean isBackground = (UserHandle.getAppId(proc.uid)
717                     >= Process.FIRST_APPLICATION_UID
718                     && proc.pid != MY_PID);
719             for (int userId : mService.mUserController.getCurrentProfileIdsLocked()) {
720                 isBackground &= (proc.userId != userId);
721             }
722             if (isBackground && !showBackground) {
723                 Slog.w(TAG, "Skipping crash dialog of " + proc + ": background");
724                 if (res != null) {
725                     res.set(AppErrorDialog.BACKGROUND_USER);
726                 }
727                 return;
728             }
729             final boolean crashSilenced = mAppsNotReportingCrashes != null &&
730                     mAppsNotReportingCrashes.contains(proc.info.packageName);
731             if ((mService.canShowErrorDialogs() || showBackground) && !crashSilenced) {
732                 proc.crashDialog = new AppErrorDialog(mContext, mService, data);
733             } else {
734                 // The device is asleep, so just pretend that the user
735                 // saw a crash dialog and hit "force quit".
736                 if (res != null) {
737                     res.set(AppErrorDialog.CANT_SHOW);
738                 }
739             }
740         }
741         // If we've created a crash dialog, show it without the lock held
742         if(data.proc.crashDialog != null) {
743             Slog.i(TAG, "Showing crash dialog for package " + data.proc.info.packageName
744                     + " u" + data.proc.userId);
745             data.proc.crashDialog.show();
746         }
747     }
748 
stopReportingCrashesLocked(ProcessRecord proc)749     void stopReportingCrashesLocked(ProcessRecord proc) {
750         if (mAppsNotReportingCrashes == null) {
751             mAppsNotReportingCrashes = new ArraySet<>();
752         }
753         mAppsNotReportingCrashes.add(proc.info.packageName);
754     }
755 
isInterestingForBackgroundTraces(ProcessRecord app)756     static boolean isInterestingForBackgroundTraces(ProcessRecord app) {
757         // The system_server is always considered interesting.
758         if (app.pid == MY_PID) {
759             return true;
760         }
761 
762         // A package is considered interesting if any of the following is true :
763         //
764         // - It's displaying an activity.
765         // - It's the SystemUI.
766         // - It has an overlay or a top UI visible.
767         //
768         // NOTE: The check whether a given ProcessRecord belongs to the systemui
769         // process is a bit of a kludge, but the same pattern seems repeated at
770         // several places in the system server.
771         return app.isInterestingToUserLocked() ||
772             (app.info != null && "com.android.systemui".equals(app.info.packageName)) ||
773             (app.hasTopUi || app.hasOverlayUi);
774     }
775 
appNotResponding(ProcessRecord app, ActivityRecord activity, ActivityRecord parent, boolean aboveSystem, final String annotation)776     final void appNotResponding(ProcessRecord app, ActivityRecord activity,
777             ActivityRecord parent, boolean aboveSystem, final String annotation) {
778         ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
779         SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
780 
781         if (mService.mController != null) {
782             try {
783                 // 0 == continue, -1 = kill process immediately
784                 int res = mService.mController.appEarlyNotResponding(
785                         app.processName, app.pid, annotation);
786                 if (res < 0 && app.pid != MY_PID) {
787                     app.kill("anr", true);
788                 }
789             } catch (RemoteException e) {
790                 mService.mController = null;
791                 Watchdog.getInstance().setActivityController(null);
792             }
793         }
794 
795         long anrTime = SystemClock.uptimeMillis();
796         if (ActivityManagerService.MONITOR_CPU_USAGE) {
797             mService.updateCpuStatsNow();
798         }
799 
800         // Unless configured otherwise, swallow ANRs in background processes & kill the process.
801         boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
802                 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
803 
804         boolean isSilentANR;
805 
806         synchronized (mService) {
807             // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
808             if (mService.mShuttingDown) {
809                 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
810                 return;
811             } else if (app.notResponding) {
812                 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
813                 return;
814             } else if (app.crashing) {
815                 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
816                 return;
817             } else if (app.killedByAm) {
818                 Slog.i(TAG, "App already killed by AM skipping ANR: " + app + " " + annotation);
819                 return;
820             } else if (app.killed) {
821                 Slog.i(TAG, "Skipping died app ANR: " + app + " " + annotation);
822                 return;
823             }
824 
825             // In case we come through here for the same app before completing
826             // this one, mark as anring now so we will bail out.
827             app.notResponding = true;
828 
829             // Log the ANR to the event log.
830             EventLog.writeEvent(EventLogTags.AM_ANR, app.userId, app.pid,
831                     app.processName, app.info.flags, annotation);
832 
833             // Dump thread traces as quickly as we can, starting with "interesting" processes.
834             firstPids.add(app.pid);
835 
836             // Don't dump other PIDs if it's a background ANR
837             isSilentANR = !showBackground && !isInterestingForBackgroundTraces(app);
838             if (!isSilentANR) {
839                 int parentPid = app.pid;
840                 if (parent != null && parent.app != null && parent.app.pid > 0) {
841                     parentPid = parent.app.pid;
842                 }
843                 if (parentPid != app.pid) firstPids.add(parentPid);
844 
845                 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
846 
847                 for (int i = mService.mLruProcesses.size() - 1; i >= 0; i--) {
848                     ProcessRecord r = mService.mLruProcesses.get(i);
849                     if (r != null && r.thread != null) {
850                         int pid = r.pid;
851                         if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
852                             if (r.persistent) {
853                                 firstPids.add(pid);
854                                 if (DEBUG_ANR) Slog.i(TAG, "Adding persistent proc: " + r);
855                             } else if (r.treatLikeActivity) {
856                                 firstPids.add(pid);
857                                 if (DEBUG_ANR) Slog.i(TAG, "Adding likely IME: " + r);
858                             } else {
859                                 lastPids.put(pid, Boolean.TRUE);
860                                 if (DEBUG_ANR) Slog.i(TAG, "Adding ANR proc: " + r);
861                             }
862                         }
863                     }
864                 }
865             }
866         }
867 
868         // Log the ANR to the main log.
869         StringBuilder info = new StringBuilder();
870         info.setLength(0);
871         info.append("ANR in ").append(app.processName);
872         if (activity != null && activity.shortComponentName != null) {
873             info.append(" (").append(activity.shortComponentName).append(")");
874         }
875         info.append("\n");
876         info.append("PID: ").append(app.pid).append("\n");
877         if (annotation != null) {
878             info.append("Reason: ").append(annotation).append("\n");
879         }
880         if (parent != null && parent != activity) {
881             info.append("Parent: ").append(parent.shortComponentName).append("\n");
882         }
883 
884         ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);
885 
886         // don't dump native PIDs for background ANRs unless it is the process of interest
887         String[] nativeProcs = null;
888         if (isSilentANR) {
889             for (int i = 0; i < NATIVE_STACKS_OF_INTEREST.length; i++) {
890                 if (NATIVE_STACKS_OF_INTEREST[i].equals(app.processName)) {
891                     nativeProcs = new String[] { app.processName };
892                     break;
893                 }
894             }
895         } else {
896             nativeProcs = NATIVE_STACKS_OF_INTEREST;
897         }
898 
899         int[] pids = nativeProcs == null ? null : Process.getPidsForCommands(nativeProcs);
900         ArrayList<Integer> nativePids = null;
901 
902         if (pids != null) {
903             nativePids = new ArrayList<Integer>(pids.length);
904             for (int i : pids) {
905                 nativePids.add(i);
906             }
907         }
908 
909         // For background ANRs, don't pass the ProcessCpuTracker to
910         // avoid spending 1/2 second collecting stats to rank lastPids.
911         File tracesFile = mService.dumpStackTraces(true, firstPids,
912                                                    (isSilentANR) ? null : processCpuTracker,
913                                                    (isSilentANR) ? null : lastPids,
914                                                    nativePids);
915 
916         String cpuInfo = null;
917         if (ActivityManagerService.MONITOR_CPU_USAGE) {
918             mService.updateCpuStatsNow();
919             synchronized (mService.mProcessCpuTracker) {
920                 cpuInfo = mService.mProcessCpuTracker.printCurrentState(anrTime);
921             }
922             info.append(processCpuTracker.printCurrentLoad());
923             info.append(cpuInfo);
924         }
925 
926         info.append(processCpuTracker.printCurrentState(anrTime));
927 
928         Slog.e(TAG, info.toString());
929         if (tracesFile == null) {
930             // There is no trace file, so dump (only) the alleged culprit's threads to the log
931             Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
932         }
933 
934         mService.addErrorToDropBox("anr", app, app.processName, activity, parent, annotation,
935                 cpuInfo, tracesFile, null);
936 
937         if (mService.mController != null) {
938             try {
939                 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
940                 int res = mService.mController.appNotResponding(
941                         app.processName, app.pid, info.toString());
942                 if (res != 0) {
943                     if (res < 0 && app.pid != MY_PID) {
944                         app.kill("anr", true);
945                     } else {
946                         synchronized (mService) {
947                             mService.mServices.scheduleServiceTimeoutLocked(app);
948                         }
949                     }
950                     return;
951                 }
952             } catch (RemoteException e) {
953                 mService.mController = null;
954                 Watchdog.getInstance().setActivityController(null);
955             }
956         }
957 
958         synchronized (mService) {
959             mService.mBatteryStatsService.noteProcessAnr(app.processName, app.uid);
960 
961             if (isSilentANR) {
962                 app.kill("bg anr", true);
963                 return;
964             }
965 
966             // Set the app's notResponding state, and look up the errorReportReceiver
967             makeAppNotRespondingLocked(app,
968                     activity != null ? activity.shortComponentName : null,
969                     annotation != null ? "ANR " + annotation : "ANR",
970                     info.toString());
971 
972             // Bring up the infamous App Not Responding dialog
973             Message msg = Message.obtain();
974             HashMap<String, Object> map = new HashMap<String, Object>();
975             msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG;
976             msg.obj = map;
977             msg.arg1 = aboveSystem ? 1 : 0;
978             map.put("app", app);
979             if (activity != null) {
980                 map.put("activity", activity);
981             }
982 
983             mService.mUiHandler.sendMessage(msg);
984         }
985     }
986 
makeAppNotRespondingLocked(ProcessRecord app, String activity, String shortMsg, String longMsg)987     private void makeAppNotRespondingLocked(ProcessRecord app,
988             String activity, String shortMsg, String longMsg) {
989         app.notResponding = true;
990         app.notRespondingReport = generateProcessError(app,
991                 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
992                 activity, shortMsg, longMsg, null);
993         startAppProblemLocked(app);
994         app.stopFreezingAllLocked();
995     }
996 
handleShowAnrUi(Message msg)997     void handleShowAnrUi(Message msg) {
998         Dialog d = null;
999         synchronized (mService) {
1000             HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1001             ProcessRecord proc = (ProcessRecord)data.get("app");
1002             if (proc != null && proc.anrDialog != null) {
1003                 Slog.e(TAG, "App already has anr dialog: " + proc);
1004                 MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
1005                         AppNotRespondingDialog.ALREADY_SHOWING);
1006                 return;
1007             }
1008 
1009             Intent intent = new Intent("android.intent.action.ANR");
1010             if (!mService.mProcessesReady) {
1011                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
1012                         | Intent.FLAG_RECEIVER_FOREGROUND);
1013             }
1014             mService.broadcastIntentLocked(null, null, intent,
1015                     null, null, 0, null, null, null, AppOpsManager.OP_NONE,
1016                     null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);
1017 
1018             boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
1019                     Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
1020             if (mService.canShowErrorDialogs() || showBackground) {
1021                 d = new AppNotRespondingDialog(mService,
1022                         mContext, proc, (ActivityRecord)data.get("activity"),
1023                         msg.arg1 != 0);
1024                 proc.anrDialog = d;
1025             } else {
1026                 MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
1027                         AppNotRespondingDialog.CANT_SHOW);
1028                 // Just kill the app if there is no dialog to be shown.
1029                 mService.killAppAtUsersRequest(proc, null);
1030             }
1031         }
1032         // If we've created a crash dialog, show it without the lock held
1033         if (d != null) {
1034             d.show();
1035         }
1036     }
1037 
1038     /**
1039      * Information about a process that is currently marked as bad.
1040      */
1041     static final class BadProcessInfo {
BadProcessInfo(long time, String shortMsg, String longMsg, String stack)1042         BadProcessInfo(long time, String shortMsg, String longMsg, String stack) {
1043             this.time = time;
1044             this.shortMsg = shortMsg;
1045             this.longMsg = longMsg;
1046             this.stack = stack;
1047         }
1048 
1049         final long time;
1050         final String shortMsg;
1051         final String longMsg;
1052         final String stack;
1053     }
1054 
1055 }
1056