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.net.Uri;
37 import android.os.Binder;
38 import android.os.Message;
39 import android.os.Process;
40 import android.os.RemoteException;
41 import android.os.SystemClock;
42 import android.os.SystemProperties;
43 import android.os.UserHandle;
44 import android.provider.Settings;
45 import android.util.ArrayMap;
46 import android.util.ArraySet;
47 import android.util.EventLog;
48 import android.util.Log;
49 import android.util.Slog;
50 import android.util.StatsLog;
51 import android.util.SparseArray;
52 import android.util.TimeUtils;
53 import android.util.proto.ProtoOutputStream;
54 
55 import java.io.File;
56 import java.io.FileDescriptor;
57 import java.io.PrintWriter;
58 import java.util.ArrayList;
59 import java.util.Collections;
60 import java.util.HashMap;
61 import java.util.Set;
62 
63 import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST;
64 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
65 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
66 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
67 import static com.android.server.am.ActivityManagerService.MY_PID;
68 import static com.android.server.am.ActivityManagerService.SYSTEM_DEBUGGABLE;
69 
70 /**
71  * Controls error conditions in applications.
72  */
73 class AppErrors {
74 
75     private static final String TAG = TAG_WITH_CLASS_NAME ? "AppErrors" : TAG_AM;
76 
77     private final ActivityManagerService mService;
78     private final Context mContext;
79 
80     private ArraySet<String> mAppsNotReportingCrashes;
81 
82     /**
83      * The last time that various processes have crashed since they were last explicitly started.
84      */
85     private final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<>();
86 
87     /**
88      * The last time that various processes have crashed (not reset even when explicitly started).
89      */
90     private final ProcessMap<Long> mProcessCrashTimesPersistent = new ProcessMap<>();
91 
92     /**
93      * Set of applications that we consider to be bad, and will reject
94      * incoming broadcasts from (which the user has no control over).
95      * Processes are added to this set when they have crashed twice within
96      * a minimum amount of time; they are removed from it when they are
97      * later restarted (hopefully due to some user action).  The value is the
98      * time it was added to the list.
99      */
100     private final ProcessMap<BadProcessInfo> mBadProcesses = new ProcessMap<>();
101 
102 
AppErrors(Context context, ActivityManagerService service)103     AppErrors(Context context, ActivityManagerService service) {
104         context.assertRuntimeOverlayThemable();
105         mService = service;
106         mContext = context;
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.mProcessNames.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.mProcessNames.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.mProcessNames.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.mProcessNames.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.crashing = false;
318         app.crashingReport = null;
319         app.notResponding = 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 a persistent app is stuck in a crash loop, the device isn't very
411         // usable, so we want to consider sending out a rescue party.
412         if (r != null && r.persistent) {
413             RescueParty.notePersistentAppCrash(mContext, r.uid);
414         }
415 
416         AppErrorResult result = new AppErrorResult();
417         TaskRecord task;
418         synchronized (mService) {
419             /**
420              * If crash is handled by instance of {@link android.app.IActivityController},
421              * finish now and don't show the app error dialog.
422              */
423             if (handleAppCrashInActivityController(r, crashInfo, shortMsg, longMsg, stackTrace,
424                     timeMillis, callingPid, callingUid)) {
425                 return;
426             }
427 
428             /**
429              * If this process was running instrumentation, finish now - it will be handled in
430              * {@link ActivityManagerService#handleAppDiedLocked}.
431              */
432             if (r != null && r.instr != null) {
433                 return;
434             }
435 
436             // Log crash in battery stats.
437             if (r != null) {
438                 mService.mBatteryStatsService.noteProcessCrash(r.processName, r.uid);
439             }
440 
441             AppErrorDialog.Data data = new AppErrorDialog.Data();
442             data.result = result;
443             data.proc = r;
444 
445             // If we can't identify the process or it's already exceeded its crash quota,
446             // quit right away without showing a crash dialog.
447             if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, data)) {
448                 return;
449             }
450 
451             final Message msg = Message.obtain();
452             msg.what = ActivityManagerService.SHOW_ERROR_UI_MSG;
453 
454             task = data.task;
455             msg.obj = data;
456             mService.mUiHandler.sendMessage(msg);
457         }
458 
459         int res = result.get();
460 
461         Intent appErrorIntent = null;
462         MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res);
463         if (res == AppErrorDialog.TIMEOUT || res == AppErrorDialog.CANCEL) {
464             res = AppErrorDialog.FORCE_QUIT;
465         }
466         synchronized (mService) {
467             if (res == AppErrorDialog.MUTE) {
468                 stopReportingCrashesLocked(r);
469             }
470             if (res == AppErrorDialog.RESTART) {
471                 mService.removeProcessLocked(r, false, true, "crash");
472                 if (task != null) {
473                     try {
474                         mService.startActivityFromRecents(task.taskId,
475                                 ActivityOptions.makeBasic().toBundle());
476                     } catch (IllegalArgumentException e) {
477                         // Hmm, that didn't work, app might have crashed before creating a
478                         // recents entry. Let's see if we have a safe-to-restart intent.
479                         final Set<String> cats = task.intent != null
480                                 ? task.intent.getCategories() : null;
481                         if (cats != null && cats.contains(Intent.CATEGORY_LAUNCHER)) {
482                             mService.getActivityStartController().startActivityInPackage(
483                                     task.mCallingUid, callingPid, callingUid, task.mCallingPackage,
484                                     task.intent, null, null, null, 0, 0,
485                                     new SafeActivityOptions(ActivityOptions.makeBasic()),
486                                     task.userId, null,
487                                     "AppErrors", false /*validateIncomingUser*/);
488                         }
489                     }
490                 }
491             }
492             if (res == AppErrorDialog.FORCE_QUIT) {
493                 long orig = Binder.clearCallingIdentity();
494                 try {
495                     // Kill it with fire!
496                     mService.mStackSupervisor.handleAppCrashLocked(r);
497                     if (!r.persistent) {
498                         mService.removeProcessLocked(r, false, false, "crash");
499                         mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
500                     }
501                 } finally {
502                     Binder.restoreCallingIdentity(orig);
503                 }
504             }
505             if (res == AppErrorDialog.APP_INFO) {
506                 appErrorIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
507                 appErrorIntent.setData(Uri.parse("package:" + r.info.packageName));
508                 appErrorIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
509             }
510             if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
511                 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
512             }
513             if (r != null && !r.isolated && res != AppErrorDialog.RESTART) {
514                 // XXX Can't keep track of crash time for isolated processes,
515                 // since they don't have a persistent identity.
516                 mProcessCrashTimes.put(r.info.processName, r.uid,
517                         SystemClock.uptimeMillis());
518             }
519         }
520 
521         if (appErrorIntent != null) {
522             try {
523                 mContext.startActivityAsUser(appErrorIntent, new UserHandle(r.userId));
524             } catch (ActivityNotFoundException e) {
525                 Slog.w(TAG, "bug report receiver dissappeared", e);
526             }
527         }
528     }
529 
handleAppCrashInActivityController(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo, String shortMsg, String longMsg, String stackTrace, long timeMillis, int callingPid, int callingUid)530     private boolean handleAppCrashInActivityController(ProcessRecord r,
531                                                        ApplicationErrorReport.CrashInfo crashInfo,
532                                                        String shortMsg, String longMsg,
533                                                        String stackTrace, long timeMillis,
534                                                        int callingPid, int callingUid) {
535         if (mService.mController == null) {
536             return false;
537         }
538 
539         try {
540             String name = r != null ? r.processName : null;
541             int pid = r != null ? r.pid : callingPid;
542             int uid = r != null ? r.info.uid : callingUid;
543             if (!mService.mController.appCrashed(name, pid,
544                     shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
545                 if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"))
546                         && "Native crash".equals(crashInfo.exceptionClassName)) {
547                     Slog.w(TAG, "Skip killing native crashed app " + name
548                             + "(" + pid + ") during testing");
549                 } else {
550                     Slog.w(TAG, "Force-killing crashed app " + name
551                             + " at watcher's request");
552                     if (r != null) {
553                         if (!makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, null))
554                         {
555                             r.kill("crash", true);
556                         }
557                     } else {
558                         // Huh.
559                         Process.killProcess(pid);
560                         ActivityManagerService.killProcessGroup(uid, pid);
561                     }
562                 }
563                 return true;
564             }
565         } catch (RemoteException e) {
566             mService.mController = null;
567             Watchdog.getInstance().setActivityController(null);
568         }
569         return false;
570     }
571 
makeAppCrashingLocked(ProcessRecord app, String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data)572     private boolean makeAppCrashingLocked(ProcessRecord app,
573             String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
574         app.crashing = true;
575         app.crashingReport = generateProcessError(app,
576                 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
577         startAppProblemLocked(app);
578         app.stopFreezingAllLocked();
579         return handleAppCrashLocked(app, "force-crash" /*reason*/, shortMsg, longMsg, stackTrace,
580                 data);
581     }
582 
startAppProblemLocked(ProcessRecord app)583     void startAppProblemLocked(ProcessRecord app) {
584         // If this app is not running under the current user, then we
585         // can't give it a report button because that would require
586         // launching the report UI under a different user.
587         app.errorReportReceiver = null;
588 
589         for (int userId : mService.mUserController.getCurrentProfileIds()) {
590             if (app.userId == userId) {
591                 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
592                         mContext, app.info.packageName, app.info.flags);
593             }
594         }
595         mService.skipCurrentReceiverLocked(app);
596     }
597 
598     /**
599      * Generate a process error record, suitable for attachment to a ProcessRecord.
600      *
601      * @param app The ProcessRecord in which the error occurred.
602      * @param condition Crashing, Application Not Responding, etc.  Values are defined in
603      *                      ActivityManager.ProcessErrorStateInfo
604      * @param activity The activity associated with the crash, if known.
605      * @param shortMsg Short message describing the crash.
606      * @param longMsg Long message describing the crash.
607      * @param stackTrace Full crash stack trace, may be null.
608      *
609      * @return Returns a fully-formed ProcessErrorStateInfo record.
610      */
generateProcessError(ProcessRecord app, int condition, String activity, String shortMsg, String longMsg, String stackTrace)611     private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
612             int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
613         ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
614 
615         report.condition = condition;
616         report.processName = app.processName;
617         report.pid = app.pid;
618         report.uid = app.info.uid;
619         report.tag = activity;
620         report.shortMsg = shortMsg;
621         report.longMsg = longMsg;
622         report.stackTrace = stackTrace;
623 
624         return report;
625     }
626 
createAppErrorIntentLocked(ProcessRecord r, long timeMillis, ApplicationErrorReport.CrashInfo crashInfo)627     Intent createAppErrorIntentLocked(ProcessRecord r,
628             long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
629         ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
630         if (report == null) {
631             return null;
632         }
633         Intent result = new Intent(Intent.ACTION_APP_ERROR);
634         result.setComponent(r.errorReportReceiver);
635         result.putExtra(Intent.EXTRA_BUG_REPORT, report);
636         result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
637         return result;
638     }
639 
createAppErrorReportLocked(ProcessRecord r, long timeMillis, ApplicationErrorReport.CrashInfo crashInfo)640     private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
641             long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
642         if (r.errorReportReceiver == null) {
643             return null;
644         }
645 
646         if (!r.crashing && !r.notResponding && !r.forceCrashReport) {
647             return null;
648         }
649 
650         ApplicationErrorReport report = new ApplicationErrorReport();
651         report.packageName = r.info.packageName;
652         report.installerPackageName = r.errorReportReceiver.getPackageName();
653         report.processName = r.processName;
654         report.time = timeMillis;
655         report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
656 
657         if (r.crashing || r.forceCrashReport) {
658             report.type = ApplicationErrorReport.TYPE_CRASH;
659             report.crashInfo = crashInfo;
660         } else if (r.notResponding) {
661             report.type = ApplicationErrorReport.TYPE_ANR;
662             report.anrInfo = new ApplicationErrorReport.AnrInfo();
663 
664             report.anrInfo.activity = r.notRespondingReport.tag;
665             report.anrInfo.cause = r.notRespondingReport.shortMsg;
666             report.anrInfo.info = r.notRespondingReport.longMsg;
667         }
668 
669         return report;
670     }
671 
handleAppCrashLocked(ProcessRecord app, String reason, String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data)672     boolean handleAppCrashLocked(ProcessRecord app, String reason,
673             String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
674         final long now = SystemClock.uptimeMillis();
675         final boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
676                 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
677 
678         final boolean procIsBoundForeground =
679             (app.curProcState == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
680 
681         Long crashTime;
682         Long crashTimePersistent;
683         boolean tryAgain = false;
684 
685         if (!app.isolated) {
686             crashTime = mProcessCrashTimes.get(app.info.processName, app.uid);
687             crashTimePersistent = mProcessCrashTimesPersistent.get(app.info.processName, app.uid);
688         } else {
689             crashTime = crashTimePersistent = null;
690         }
691 
692         // Bump up the crash count of any services currently running in the proc.
693         for (int i = app.services.size() - 1; i >= 0; i--) {
694             // Any services running in the application need to be placed
695             // back in the pending list.
696             ServiceRecord sr = app.services.valueAt(i);
697             // If the service was restarted a while ago, then reset crash count, else increment it.
698             if (now > sr.restartTime + ProcessList.MIN_CRASH_INTERVAL) {
699                 sr.crashCount = 1;
700             } else {
701                 sr.crashCount++;
702             }
703             // Allow restarting for started or bound foreground services that are crashing.
704             // This includes wallpapers.
705             if (sr.crashCount < mService.mConstants.BOUND_SERVICE_MAX_CRASH_RETRY
706                     && (sr.isForeground || procIsBoundForeground)) {
707                 tryAgain = true;
708             }
709         }
710 
711         if (crashTime != null && now < crashTime + ProcessList.MIN_CRASH_INTERVAL) {
712             // The process crashed again very quickly. If it was a bound foreground service, let's
713             // try to restart again in a while, otherwise the process loses!
714             Slog.w(TAG, "Process " + app.info.processName
715                     + " has crashed too many times: killing!");
716             EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
717                     app.userId, app.info.processName, app.uid);
718             mService.mStackSupervisor.handleAppCrashLocked(app);
719             if (!app.persistent) {
720                 // We don't want to start this process again until the user
721                 // explicitly does so...  but for persistent process, we really
722                 // need to keep it running.  If a persistent process is actually
723                 // repeatedly crashing, then badness for everyone.
724                 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.userId, app.uid,
725                         app.info.processName);
726                 if (!app.isolated) {
727                     // XXX We don't have a way to mark isolated processes
728                     // as bad, since they don't have a peristent identity.
729                     mBadProcesses.put(app.info.processName, app.uid,
730                             new BadProcessInfo(now, shortMsg, longMsg, stackTrace));
731                     mProcessCrashTimes.remove(app.info.processName, app.uid);
732                 }
733                 app.bad = true;
734                 app.removed = true;
735                 // Don't let services in this process be restarted and potentially
736                 // annoy the user repeatedly.  Unless it is persistent, since those
737                 // processes run critical code.
738                 mService.removeProcessLocked(app, false, tryAgain, "crash");
739                 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
740                 if (!showBackground) {
741                     return false;
742                 }
743             }
744             mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
745         } else {
746             final TaskRecord affectedTask =
747                     mService.mStackSupervisor.finishTopCrashedActivitiesLocked(app, reason);
748             if (data != null) {
749                 data.task = affectedTask;
750             }
751             if (data != null && crashTimePersistent != null
752                     && now < crashTimePersistent + ProcessList.MIN_CRASH_INTERVAL) {
753                 data.repeating = true;
754             }
755         }
756 
757         if (data != null && tryAgain) {
758             data.isRestartableForService = true;
759         }
760 
761         // If the crashing process is what we consider to be the "home process" and it has been
762         // replaced by a third-party app, clear the package preferred activities from packages
763         // with a home activity running in the process to prevent a repeatedly crashing app
764         // from blocking the user to manually clear the list.
765         final ArrayList<ActivityRecord> activities = app.activities;
766         if (app == mService.mHomeProcess && activities.size() > 0
767                 && (mService.mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
768             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
769                 final ActivityRecord r = activities.get(activityNdx);
770                 if (r.isActivityTypeHome()) {
771                     Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
772                     try {
773                         ActivityThread.getPackageManager()
774                                 .clearPackagePreferredActivities(r.packageName);
775                     } catch (RemoteException c) {
776                         // pm is in same process, this will never happen.
777                     }
778                 }
779             }
780         }
781 
782         if (!app.isolated) {
783             // XXX Can't keep track of crash times for isolated processes,
784             // because they don't have a persistent identity.
785             mProcessCrashTimes.put(app.info.processName, app.uid, now);
786             mProcessCrashTimesPersistent.put(app.info.processName, app.uid, now);
787         }
788 
789         if (app.crashHandler != null) mService.mHandler.post(app.crashHandler);
790         return true;
791     }
792 
handleShowAppErrorUi(Message msg)793     void handleShowAppErrorUi(Message msg) {
794         AppErrorDialog.Data data = (AppErrorDialog.Data) msg.obj;
795         boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
796                 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
797 
798         AppErrorDialog dialogToShow = null;
799         final String packageName;
800         final int userId;
801         synchronized (mService) {
802             final ProcessRecord proc = data.proc;
803             final AppErrorResult res = data.result;
804             if (proc == null) {
805                 Slog.e(TAG, "handleShowAppErrorUi: proc is null");
806                 return;
807             }
808             packageName = proc.info.packageName;
809             userId = proc.userId;
810             if (proc.crashDialog != null) {
811                 Slog.e(TAG, "App already has crash dialog: " + proc);
812                 if (res != null) {
813                     res.set(AppErrorDialog.ALREADY_SHOWING);
814                 }
815                 return;
816             }
817             boolean isBackground = (UserHandle.getAppId(proc.uid)
818                     >= Process.FIRST_APPLICATION_UID
819                     && proc.pid != MY_PID);
820             for (int profileId : mService.mUserController.getCurrentProfileIds()) {
821                 isBackground &= (userId != profileId);
822             }
823             if (isBackground && !showBackground) {
824                 Slog.w(TAG, "Skipping crash dialog of " + proc + ": background");
825                 if (res != null) {
826                     res.set(AppErrorDialog.BACKGROUND_USER);
827                 }
828                 return;
829             }
830             final boolean showFirstCrash = Settings.Global.getInt(
831                     mContext.getContentResolver(),
832                     Settings.Global.SHOW_FIRST_CRASH_DIALOG, 0) != 0;
833             final boolean showFirstCrashDevOption = Settings.Secure.getIntForUser(
834                     mContext.getContentResolver(),
835                     Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION,
836                     0,
837                     mService.mUserController.getCurrentUserId()) != 0;
838             final boolean crashSilenced = mAppsNotReportingCrashes != null &&
839                     mAppsNotReportingCrashes.contains(proc.info.packageName);
840             if ((mService.canShowErrorDialogs() || showBackground) && !crashSilenced
841                     && (showFirstCrash || showFirstCrashDevOption || data.repeating)) {
842                 proc.crashDialog = dialogToShow = new AppErrorDialog(mContext, mService, data);
843             } else {
844                 // The device is asleep, so just pretend that the user
845                 // saw a crash dialog and hit "force quit".
846                 if (res != null) {
847                     res.set(AppErrorDialog.CANT_SHOW);
848                 }
849             }
850         }
851         // If we've created a crash dialog, show it without the lock held
852         if (dialogToShow != null) {
853             Slog.i(TAG, "Showing crash dialog for package " + packageName + " u" + userId);
854             dialogToShow.show();
855         }
856     }
857 
stopReportingCrashesLocked(ProcessRecord proc)858     void stopReportingCrashesLocked(ProcessRecord proc) {
859         if (mAppsNotReportingCrashes == null) {
860             mAppsNotReportingCrashes = new ArraySet<>();
861         }
862         mAppsNotReportingCrashes.add(proc.info.packageName);
863     }
864 
isInterestingForBackgroundTraces(ProcessRecord app)865     static boolean isInterestingForBackgroundTraces(ProcessRecord app) {
866         // The system_server is always considered interesting.
867         if (app.pid == MY_PID) {
868             return true;
869         }
870 
871         // A package is considered interesting if any of the following is true :
872         //
873         // - It's displaying an activity.
874         // - It's the SystemUI.
875         // - It has an overlay or a top UI visible.
876         //
877         // NOTE: The check whether a given ProcessRecord belongs to the systemui
878         // process is a bit of a kludge, but the same pattern seems repeated at
879         // several places in the system server.
880         return app.isInterestingToUserLocked() ||
881             (app.info != null && "com.android.systemui".equals(app.info.packageName)) ||
882             (app.hasTopUi || app.hasOverlayUi);
883     }
884 
appNotResponding(ProcessRecord app, ActivityRecord activity, ActivityRecord parent, boolean aboveSystem, final String annotation)885     final void appNotResponding(ProcessRecord app, ActivityRecord activity,
886             ActivityRecord parent, boolean aboveSystem, final String annotation) {
887         ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
888         SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
889 
890         if (mService.mController != null) {
891             try {
892                 // 0 == continue, -1 = kill process immediately
893                 int res = mService.mController.appEarlyNotResponding(
894                         app.processName, app.pid, annotation);
895                 if (res < 0 && app.pid != MY_PID) {
896                     app.kill("anr", true);
897                 }
898             } catch (RemoteException e) {
899                 mService.mController = null;
900                 Watchdog.getInstance().setActivityController(null);
901             }
902         }
903 
904         long anrTime = SystemClock.uptimeMillis();
905         if (ActivityManagerService.MONITOR_CPU_USAGE) {
906             mService.updateCpuStatsNow();
907         }
908 
909         // Unless configured otherwise, swallow ANRs in background processes & kill the process.
910         boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
911                 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
912 
913         boolean isSilentANR;
914 
915         synchronized (mService) {
916             // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
917             if (mService.mShuttingDown) {
918                 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
919                 return;
920             } else if (app.notResponding) {
921                 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
922                 return;
923             } else if (app.crashing) {
924                 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
925                 return;
926             } else if (app.killedByAm) {
927                 Slog.i(TAG, "App already killed by AM skipping ANR: " + app + " " + annotation);
928                 return;
929             } else if (app.killed) {
930                 Slog.i(TAG, "Skipping died app ANR: " + app + " " + annotation);
931                 return;
932             }
933 
934             // In case we come through here for the same app before completing
935             // this one, mark as anring now so we will bail out.
936             app.notResponding = true;
937 
938             // Log the ANR to the event log.
939             EventLog.writeEvent(EventLogTags.AM_ANR, app.userId, app.pid,
940                     app.processName, app.info.flags, annotation);
941 
942             // Dump thread traces as quickly as we can, starting with "interesting" processes.
943             firstPids.add(app.pid);
944 
945             // Don't dump other PIDs if it's a background ANR
946             isSilentANR = !showBackground && !isInterestingForBackgroundTraces(app);
947             if (!isSilentANR) {
948                 int parentPid = app.pid;
949                 if (parent != null && parent.app != null && parent.app.pid > 0) {
950                     parentPid = parent.app.pid;
951                 }
952                 if (parentPid != app.pid) firstPids.add(parentPid);
953 
954                 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
955 
956                 for (int i = mService.mLruProcesses.size() - 1; i >= 0; i--) {
957                     ProcessRecord r = mService.mLruProcesses.get(i);
958                     if (r != null && r.thread != null) {
959                         int pid = r.pid;
960                         if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
961                             if (r.persistent) {
962                                 firstPids.add(pid);
963                                 if (DEBUG_ANR) Slog.i(TAG, "Adding persistent proc: " + r);
964                             } else if (r.treatLikeActivity) {
965                                 firstPids.add(pid);
966                                 if (DEBUG_ANR) Slog.i(TAG, "Adding likely IME: " + r);
967                             } else {
968                                 lastPids.put(pid, Boolean.TRUE);
969                                 if (DEBUG_ANR) Slog.i(TAG, "Adding ANR proc: " + r);
970                             }
971                         }
972                     }
973                 }
974             }
975         }
976 
977         // Log the ANR to the main log.
978         StringBuilder info = new StringBuilder();
979         info.setLength(0);
980         info.append("ANR in ").append(app.processName);
981         if (activity != null && activity.shortComponentName != null) {
982             info.append(" (").append(activity.shortComponentName).append(")");
983         }
984         info.append("\n");
985         info.append("PID: ").append(app.pid).append("\n");
986         if (annotation != null) {
987             info.append("Reason: ").append(annotation).append("\n");
988         }
989         if (parent != null && parent != activity) {
990             info.append("Parent: ").append(parent.shortComponentName).append("\n");
991         }
992 
993         ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);
994 
995         // don't dump native PIDs for background ANRs unless it is the process of interest
996         String[] nativeProcs = null;
997         if (isSilentANR) {
998             for (int i = 0; i < NATIVE_STACKS_OF_INTEREST.length; i++) {
999                 if (NATIVE_STACKS_OF_INTEREST[i].equals(app.processName)) {
1000                     nativeProcs = new String[] { app.processName };
1001                     break;
1002                 }
1003             }
1004         } else {
1005             nativeProcs = NATIVE_STACKS_OF_INTEREST;
1006         }
1007 
1008         int[] pids = nativeProcs == null ? null : Process.getPidsForCommands(nativeProcs);
1009         ArrayList<Integer> nativePids = null;
1010 
1011         if (pids != null) {
1012             nativePids = new ArrayList<Integer>(pids.length);
1013             for (int i : pids) {
1014                 nativePids.add(i);
1015             }
1016         }
1017 
1018         // For background ANRs, don't pass the ProcessCpuTracker to
1019         // avoid spending 1/2 second collecting stats to rank lastPids.
1020         File tracesFile = ActivityManagerService.dumpStackTraces(
1021                 true, firstPids,
1022                 (isSilentANR) ? null : processCpuTracker,
1023                 (isSilentANR) ? null : lastPids,
1024                 nativePids);
1025 
1026         String cpuInfo = null;
1027         if (ActivityManagerService.MONITOR_CPU_USAGE) {
1028             mService.updateCpuStatsNow();
1029             synchronized (mService.mProcessCpuTracker) {
1030                 cpuInfo = mService.mProcessCpuTracker.printCurrentState(anrTime);
1031             }
1032             info.append(processCpuTracker.printCurrentLoad());
1033             info.append(cpuInfo);
1034         }
1035 
1036         info.append(processCpuTracker.printCurrentState(anrTime));
1037 
1038         Slog.e(TAG, info.toString());
1039         if (tracesFile == null) {
1040             // There is no trace file, so dump (only) the alleged culprit's threads to the log
1041             Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
1042         }
1043 
1044         StatsLog.write(StatsLog.ANR_OCCURRED, app.uid, app.processName,
1045                 activity == null ? "unknown": activity.shortComponentName, annotation,
1046                 (app.info != null) ? (app.info.isInstantApp()
1047                         ? StatsLog.ANROCCURRED__IS_INSTANT_APP__TRUE
1048                         : StatsLog.ANROCCURRED__IS_INSTANT_APP__FALSE)
1049                         : StatsLog.ANROCCURRED__IS_INSTANT_APP__UNAVAILABLE,
1050                 app != null ? (app.isInterestingToUserLocked()
1051                         ? StatsLog.ANROCCURRED__FOREGROUND_STATE__FOREGROUND
1052                         : StatsLog.ANROCCURRED__FOREGROUND_STATE__BACKGROUND)
1053                         : StatsLog.ANROCCURRED__FOREGROUND_STATE__UNKNOWN);
1054         mService.addErrorToDropBox("anr", app, app.processName, activity, parent, annotation,
1055                 cpuInfo, tracesFile, null);
1056 
1057         if (mService.mController != null) {
1058             try {
1059                 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
1060                 int res = mService.mController.appNotResponding(
1061                         app.processName, app.pid, info.toString());
1062                 if (res != 0) {
1063                     if (res < 0 && app.pid != MY_PID) {
1064                         app.kill("anr", true);
1065                     } else {
1066                         synchronized (mService) {
1067                             mService.mServices.scheduleServiceTimeoutLocked(app);
1068                         }
1069                     }
1070                     return;
1071                 }
1072             } catch (RemoteException e) {
1073                 mService.mController = null;
1074                 Watchdog.getInstance().setActivityController(null);
1075             }
1076         }
1077 
1078         synchronized (mService) {
1079             mService.mBatteryStatsService.noteProcessAnr(app.processName, app.uid);
1080 
1081             if (isSilentANR) {
1082                 app.kill("bg anr", true);
1083                 return;
1084             }
1085 
1086             // Set the app's notResponding state, and look up the errorReportReceiver
1087             makeAppNotRespondingLocked(app,
1088                     activity != null ? activity.shortComponentName : null,
1089                     annotation != null ? "ANR " + annotation : "ANR",
1090                     info.toString());
1091 
1092             // Bring up the infamous App Not Responding dialog
1093             Message msg = Message.obtain();
1094             msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG;
1095             msg.obj = new AppNotRespondingDialog.Data(app, activity, aboveSystem);
1096 
1097             mService.mUiHandler.sendMessage(msg);
1098         }
1099     }
1100 
makeAppNotRespondingLocked(ProcessRecord app, String activity, String shortMsg, String longMsg)1101     private void makeAppNotRespondingLocked(ProcessRecord app,
1102             String activity, String shortMsg, String longMsg) {
1103         app.notResponding = true;
1104         app.notRespondingReport = generateProcessError(app,
1105                 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
1106                 activity, shortMsg, longMsg, null);
1107         startAppProblemLocked(app);
1108         app.stopFreezingAllLocked();
1109     }
1110 
handleShowAnrUi(Message msg)1111     void handleShowAnrUi(Message msg) {
1112         Dialog dialogToShow = null;
1113         synchronized (mService) {
1114             AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj;
1115             final ProcessRecord proc = data.proc;
1116             if (proc == null) {
1117                 Slog.e(TAG, "handleShowAnrUi: proc is null");
1118                 return;
1119             }
1120             if (proc.anrDialog != null) {
1121                 Slog.e(TAG, "App already has anr dialog: " + proc);
1122                 MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
1123                         AppNotRespondingDialog.ALREADY_SHOWING);
1124                 return;
1125             }
1126 
1127             Intent intent = new Intent("android.intent.action.ANR");
1128             if (!mService.mProcessesReady) {
1129                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
1130                         | Intent.FLAG_RECEIVER_FOREGROUND);
1131             }
1132             mService.broadcastIntentLocked(null, null, intent,
1133                     null, null, 0, null, null, null, AppOpsManager.OP_NONE,
1134                     null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);
1135 
1136             boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
1137                     Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
1138             if (mService.canShowErrorDialogs() || showBackground) {
1139                 dialogToShow = new AppNotRespondingDialog(mService, mContext, data);
1140                 proc.anrDialog = dialogToShow;
1141             } else {
1142                 MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
1143                         AppNotRespondingDialog.CANT_SHOW);
1144                 // Just kill the app if there is no dialog to be shown.
1145                 mService.killAppAtUsersRequest(proc, null);
1146             }
1147         }
1148         // If we've created a crash dialog, show it without the lock held
1149         if (dialogToShow != null) {
1150             dialogToShow.show();
1151         }
1152     }
1153 
1154     /**
1155      * Information about a process that is currently marked as bad.
1156      */
1157     static final class BadProcessInfo {
BadProcessInfo(long time, String shortMsg, String longMsg, String stack)1158         BadProcessInfo(long time, String shortMsg, String longMsg, String stack) {
1159             this.time = time;
1160             this.shortMsg = shortMsg;
1161             this.longMsg = longMsg;
1162             this.stack = stack;
1163         }
1164 
1165         final long time;
1166         final String shortMsg;
1167         final String longMsg;
1168         final String stack;
1169     }
1170 
1171 }
1172