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