• 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 static android.app.ActivityTaskManager.INVALID_TASK_ID;
20 import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
21 
22 import static com.android.server.am.ActivityManagerConstants.PROCESS_CRASH_COUNT_LIMIT;
23 import static com.android.server.am.ActivityManagerConstants.PROCESS_CRASH_COUNT_RESET_INTERVAL;
24 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
25 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
26 import static com.android.server.am.ActivityManagerService.MY_PID;
27 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
28 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
29 
30 import android.annotation.Nullable;
31 import android.app.ActivityManager;
32 import android.app.ActivityOptions;
33 import android.app.AnrController;
34 import android.app.ApplicationErrorReport;
35 import android.app.ApplicationExitInfo;
36 import android.app.RemoteServiceException.CrashedByAdbException;
37 import android.app.usage.UsageStatsManager;
38 import android.content.ActivityNotFoundException;
39 import android.content.Context;
40 import android.content.Intent;
41 import android.content.pm.VersionedPackage;
42 import android.net.Uri;
43 import android.os.Binder;
44 import android.os.Build;
45 import android.os.Bundle;
46 import android.os.Message;
47 import android.os.Process;
48 import android.os.SystemClock;
49 import android.os.UserHandle;
50 import android.os.UserManager;
51 import android.provider.Settings;
52 import android.util.ArrayMap;
53 import android.util.ArraySet;
54 import android.util.EventLog;
55 import android.util.Pair;
56 import android.util.Slog;
57 import android.util.SparseArray;
58 import android.util.TimeUtils;
59 import android.util.proto.ProtoOutputStream;
60 
61 import com.android.internal.annotations.GuardedBy;
62 import com.android.internal.app.ProcessMap;
63 import com.android.internal.logging.MetricsLogger;
64 import com.android.internal.logging.nano.MetricsProto;
65 import com.android.server.LocalServices;
66 import com.android.server.PackageWatchdog;
67 import com.android.server.pm.UserManagerInternal;
68 import com.android.server.usage.AppStandbyInternal;
69 import com.android.server.wm.WindowProcessController;
70 
71 import java.io.FileDescriptor;
72 import java.io.PrintWriter;
73 import java.util.Collections;
74 import java.util.List;
75 
76 /**
77  * Controls error conditions in applications.
78  */
79 class AppErrors {
80 
81     private static final String TAG = TAG_WITH_CLASS_NAME ? "AppErrors" : TAG_AM;
82 
83     private final ActivityManagerService mService;
84     private final ActivityManagerGlobalLock mProcLock;
85     private final Context mContext;
86     private final PackageWatchdog mPackageWatchdog;
87 
88     @GuardedBy("mBadProcessLock")
89     private ArraySet<String> mAppsNotReportingCrashes;
90 
91     /**
92      * The last time that various processes have crashed since they were last explicitly started.
93      */
94     @GuardedBy("mBadProcessLock")
95     private final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<>();
96 
97     /**
98      * The last time that various processes have crashed (not reset even when explicitly started).
99      */
100     @GuardedBy("mBadProcessLock")
101     private final ProcessMap<Long> mProcessCrashTimesPersistent = new ProcessMap<>();
102 
103     /**
104      * The last time that various processes have crashed and shown an error dialog.
105      */
106     @GuardedBy("mBadProcessLock")
107     private final ProcessMap<Long> mProcessCrashShowDialogTimes = new ProcessMap<>();
108 
109     /**
110      * A pairing between how many times various processes have crashed since a given time.
111      * Entry and exit conditions for this map are similar to mProcessCrashTimes.
112      */
113     @GuardedBy("mBadProcessLock")
114     private final ProcessMap<Pair<Long, Integer>> mProcessCrashCounts = new ProcessMap<>();
115 
116     /**
117      * Set of applications that we consider to be bad, and will reject
118      * incoming broadcasts from (which the user has no control over).
119      * Processes are added to this set when they have crashed twice within
120      * a minimum amount of time; they are removed from it when they are
121      * later restarted (hopefully due to some user action).  The value is the
122      * time it was added to the list.
123      *
124      * Read access is UNLOCKED, and must either be based on a single lookup
125      * call on the current mBadProcesses instance, or a local copy of that
126      * reference must be made and the local copy treated as the source of
127      * truth.  Mutations are performed by synchronizing on mBadProcessLock,
128      * cloning the existing mBadProcesses instance, performing the mutation,
129      * then changing the volatile "live" mBadProcesses reference to point to the
130      * mutated version.  These operations are very rare compared to lookups:
131      * we intentionally trade additional cost for mutations for eliminating
132      * lock operations from the simple lookup cases.
133      */
134     private volatile ProcessMap<BadProcessInfo> mBadProcesses = new ProcessMap<>();
135 
136     /**
137      * Dedicated lock for {@link #mAppsNotReportingCrashes}, {@link #mProcessCrashTimes},
138      * {@link #mProcessCrashTimesPersistent}, {@link #mProcessCrashShowDialogTimes},
139      * {@link #mProcessCrashCounts} and {@link #mBadProcesses}.
140      *
141      * <p>The naming convention of the function with this lock should be "-LBp"</b>
142      *
143      * @See mBadProcesses
144      */
145     private final Object mBadProcessLock = new Object();
146 
AppErrors(Context context, ActivityManagerService service, PackageWatchdog watchdog)147     AppErrors(Context context, ActivityManagerService service, PackageWatchdog watchdog) {
148         context.assertRuntimeOverlayThemable();
149         mService = service;
150         mProcLock = service.mProcLock;
151         mContext = context;
152         mPackageWatchdog = watchdog;
153     }
154 
155     /** Resets the current state but leaves the constructor-provided fields unchanged. */
resetState()156     public void resetState() {
157         Slog.i(TAG, "Resetting AppErrors");
158         synchronized (mBadProcessLock) {
159             mAppsNotReportingCrashes.clear();
160             mProcessCrashTimes.clear();
161             mProcessCrashTimesPersistent.clear();
162             mProcessCrashShowDialogTimes.clear();
163             mProcessCrashCounts.clear();
164             mBadProcesses = new ProcessMap<>();
165         }
166     }
167 
168     @GuardedBy("mProcLock")
dumpDebugLPr(ProtoOutputStream proto, long fieldId, String dumpPackage)169     void dumpDebugLPr(ProtoOutputStream proto, long fieldId, String dumpPackage) {
170         final ProcessMap<BadProcessInfo> badProcesses = mBadProcesses;
171         if (mProcessCrashTimes.getMap().isEmpty() && badProcesses.getMap().isEmpty()) {
172             return;
173         }
174 
175         final long token = proto.start(fieldId);
176         final long now = SystemClock.uptimeMillis();
177         proto.write(AppErrorsProto.NOW_UPTIME_MS, now);
178 
179         if (!badProcesses.getMap().isEmpty()) {
180             final ArrayMap<String, SparseArray<BadProcessInfo>> pmap = badProcesses.getMap();
181             final int processCount = pmap.size();
182             for (int ip = 0; ip < processCount; ip++) {
183                 final long btoken = proto.start(AppErrorsProto.BAD_PROCESSES);
184                 final String pname = pmap.keyAt(ip);
185                 final SparseArray<BadProcessInfo> uids = pmap.valueAt(ip);
186                 final int uidCount = uids.size();
187 
188                 proto.write(AppErrorsProto.BadProcess.PROCESS_NAME, pname);
189                 for (int i = 0; i < uidCount; i++) {
190                     final int puid = uids.keyAt(i);
191                     final ProcessRecord r = mService.getProcessNamesLOSP().get(pname, puid);
192                     if (dumpPackage != null && (r == null
193                             || !r.getPkgList().containsKey(dumpPackage))) {
194                         continue;
195                     }
196                     final BadProcessInfo info = uids.valueAt(i);
197                     final long etoken = proto.start(AppErrorsProto.BadProcess.ENTRIES);
198                     proto.write(AppErrorsProto.BadProcess.Entry.UID, puid);
199                     proto.write(AppErrorsProto.BadProcess.Entry.CRASHED_AT_MS, info.time);
200                     proto.write(AppErrorsProto.BadProcess.Entry.SHORT_MSG, info.shortMsg);
201                     proto.write(AppErrorsProto.BadProcess.Entry.LONG_MSG, info.longMsg);
202                     proto.write(AppErrorsProto.BadProcess.Entry.STACK, info.stack);
203                     proto.end(etoken);
204                 }
205                 proto.end(btoken);
206             }
207         }
208 
209         synchronized (mBadProcessLock) {
210             if (!mProcessCrashTimes.getMap().isEmpty()) {
211                 final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap();
212                 final int procCount = pmap.size();
213                 for (int ip = 0; ip < procCount; ip++) {
214                     final long ctoken = proto.start(AppErrorsProto.PROCESS_CRASH_TIMES);
215                     final String pname = pmap.keyAt(ip);
216                     final SparseArray<Long> uids = pmap.valueAt(ip);
217                     final int uidCount = uids.size();
218 
219                     proto.write(AppErrorsProto.ProcessCrashTime.PROCESS_NAME, pname);
220                     for (int i = 0; i < uidCount; i++) {
221                         final int puid = uids.keyAt(i);
222                         final ProcessRecord r = mService.getProcessNamesLOSP().get(pname, puid);
223                         if (dumpPackage != null
224                                 && (r == null || !r.getPkgList().containsKey(dumpPackage))) {
225                             continue;
226                         }
227                         final long etoken = proto.start(AppErrorsProto.ProcessCrashTime.ENTRIES);
228                         proto.write(AppErrorsProto.ProcessCrashTime.Entry.UID, puid);
229                         proto.write(AppErrorsProto.ProcessCrashTime.Entry.LAST_CRASHED_AT_MS,
230                                 uids.valueAt(i));
231                         proto.end(etoken);
232                     }
233                     proto.end(ctoken);
234                 }
235             }
236         }
237 
238         proto.end(token);
239     }
240 
241     @GuardedBy("mProcLock")
dumpLPr(FileDescriptor fd, PrintWriter pw, boolean needSep, String dumpPackage)242     boolean dumpLPr(FileDescriptor fd, PrintWriter pw, boolean needSep, String dumpPackage) {
243         final long now = SystemClock.uptimeMillis();
244         synchronized (mBadProcessLock) {
245             if (!mProcessCrashTimes.getMap().isEmpty()) {
246                 boolean printed = false;
247                 final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap();
248                 final int processCount = pmap.size();
249                 for (int ip = 0; ip < processCount; ip++) {
250                     final String pname = pmap.keyAt(ip);
251                     final SparseArray<Long> uids = pmap.valueAt(ip);
252                     final int uidCount = uids.size();
253                     for (int i = 0; i < uidCount; i++) {
254                         final int puid = uids.keyAt(i);
255                         final ProcessRecord r = mService.getProcessNamesLOSP().get(pname, puid);
256                         if (dumpPackage != null
257                                 && (r == null || !r.getPkgList().containsKey(dumpPackage))) {
258                             continue;
259                         }
260                         if (!printed) {
261                             if (needSep) pw.println();
262                             needSep = true;
263                             pw.println("  Time since processes crashed:");
264                             printed = true;
265                         }
266                         pw.print("    Process "); pw.print(pname);
267                         pw.print(" uid "); pw.print(puid);
268                         pw.print(": last crashed ");
269                         TimeUtils.formatDuration(now - uids.valueAt(i), pw);
270                         pw.println(" ago");
271                     }
272                 }
273             }
274 
275             if (!mProcessCrashCounts.getMap().isEmpty()) {
276                 boolean printed = false;
277                 final ArrayMap<String, SparseArray<Pair<Long, Integer>>> pmap =
278                         mProcessCrashCounts.getMap();
279                 final int processCount = pmap.size();
280                 for (int ip = 0; ip < processCount; ip++) {
281                     final String pname = pmap.keyAt(ip);
282                     final SparseArray<Pair<Long, Integer>> uids = pmap.valueAt(ip);
283                     final int uidCount = uids.size();
284                     for (int i = 0; i < uidCount; i++) {
285                         final int puid = uids.keyAt(i);
286                         final ProcessRecord r = mService.getProcessNamesLOSP().get(pname, puid);
287                         if (dumpPackage != null
288                                 && (r == null || !r.getPkgList().containsKey(dumpPackage))) {
289                             continue;
290                         }
291                         if (!printed) {
292                             if (needSep) pw.println();
293                             needSep = true;
294                             pw.println("  First time processes crashed and counts:");
295                             printed = true;
296                         }
297                         pw.print("    Process "); pw.print(pname);
298                         pw.print(" uid "); pw.print(puid);
299                         pw.print(": first crashed ");
300                         TimeUtils.formatDuration(now - uids.valueAt(i).first, pw);
301                         pw.print(" ago; crashes since then: "); pw.println(uids.valueAt(i).second);
302                     }
303                 }
304             }
305         }
306 
307         final ProcessMap<BadProcessInfo> badProcesses = mBadProcesses;
308         if (!badProcesses.getMap().isEmpty()) {
309             boolean printed = false;
310             final ArrayMap<String, SparseArray<BadProcessInfo>> pmap = badProcesses.getMap();
311             final int processCount = pmap.size();
312             for (int ip = 0; ip < processCount; ip++) {
313                 final String pname = pmap.keyAt(ip);
314                 final SparseArray<BadProcessInfo> uids = pmap.valueAt(ip);
315                 final int uidCount = uids.size();
316                 for (int i = 0; i < uidCount; i++) {
317                     final int puid = uids.keyAt(i);
318                     final ProcessRecord r = mService.getProcessNamesLOSP().get(pname, puid);
319                     if (dumpPackage != null && (r == null
320                             || !r.getPkgList().containsKey(dumpPackage))) {
321                         continue;
322                     }
323                     if (!printed) {
324                         if (needSep) pw.println();
325                         needSep = true;
326                         pw.println("  Bad processes:");
327                         printed = true;
328                     }
329                     final BadProcessInfo info = uids.valueAt(i);
330                     pw.print("    Bad process "); pw.print(pname);
331                     pw.print(" uid "); pw.print(puid);
332                     pw.print(": crashed at time "); pw.println(info.time);
333                     if (info.shortMsg != null) {
334                         pw.print("      Short msg: "); pw.println(info.shortMsg);
335                     }
336                     if (info.longMsg != null) {
337                         pw.print("      Long msg: "); pw.println(info.longMsg);
338                     }
339                     if (info.stack != null) {
340                         pw.println("      Stack:");
341                         int lastPos = 0;
342                         for (int pos = 0; pos < info.stack.length(); pos++) {
343                             if (info.stack.charAt(pos) == '\n') {
344                                 pw.print("        ");
345                                 pw.write(info.stack, lastPos, pos - lastPos);
346                                 pw.println();
347                                 lastPos = pos + 1;
348                             }
349                         }
350                         if (lastPos < info.stack.length()) {
351                             pw.print("        ");
352                             pw.write(info.stack, lastPos, info.stack.length() - lastPos);
353                             pw.println();
354                         }
355                     }
356                 }
357             }
358         }
359         return needSep;
360     }
361 
isBadProcess(final String processName, final int uid)362     boolean isBadProcess(final String processName, final int uid) {
363         // NO LOCKING for the simple lookup
364         return mBadProcesses.get(processName, uid) != null;
365     }
366 
clearBadProcess(final String processName, final int uid)367     void clearBadProcess(final String processName, final int uid) {
368         synchronized (mBadProcessLock) {
369             final ProcessMap<BadProcessInfo> badProcesses = new ProcessMap<>();
370             badProcesses.putAll(mBadProcesses);
371             badProcesses.remove(processName, uid);
372             mBadProcesses = badProcesses;
373         }
374     }
375 
clearBadProcessForUser(final String processName, final int userId)376     void clearBadProcessForUser(final String processName, final int userId) {
377         synchronized (mBadProcessLock) {
378             final ProcessMap<BadProcessInfo> badProcesses = new ProcessMap<>();
379             badProcesses.putAll(mBadProcesses);
380             final SparseArray<BadProcessInfo> uids = badProcesses.get(processName);
381             if (uids == null) {
382                 return;
383             }
384             for (int i = uids.size() - 1; i >= 0; --i) {
385                 final int uid = uids.keyAt(i);
386                 if (userId == UserHandle.USER_ALL || userId == UserHandle.getUserId(uid)) {
387                     badProcesses.remove(processName, uid);
388                 }
389             }
390             mBadProcesses = badProcesses;
391         }
392     }
393 
markBadProcess(final String processName, final int uid, BadProcessInfo info)394     void markBadProcess(final String processName, final int uid, BadProcessInfo info) {
395         synchronized (mBadProcessLock) {
396             final ProcessMap<BadProcessInfo> badProcesses = new ProcessMap<>();
397             badProcesses.putAll(mBadProcesses);
398             badProcesses.put(processName, uid, info);
399             mBadProcesses = badProcesses;
400         }
401     }
402 
resetProcessCrashTime(final String processName, final int uid)403     void resetProcessCrashTime(final String processName, final int uid) {
404         synchronized (mBadProcessLock) {
405             mProcessCrashTimes.remove(processName, uid);
406             mProcessCrashCounts.remove(processName, uid);
407         }
408     }
409 
resetProcessCrashTime(boolean resetEntireUser, int appId, int userId)410     void resetProcessCrashTime(boolean resetEntireUser, int appId, int userId) {
411         synchronized (mBadProcessLock) {
412             final ArrayMap<String, SparseArray<Long>> pTimeMap = mProcessCrashTimes.getMap();
413             for (int ip = pTimeMap.size() - 1; ip >= 0; ip--) {
414                 SparseArray<Long> ba = pTimeMap.valueAt(ip);
415                 resetProcessCrashMapLBp(ba, resetEntireUser, appId, userId);
416                 if (ba.size() == 0) {
417                     pTimeMap.removeAt(ip);
418                 }
419             }
420 
421             final ArrayMap<String, SparseArray<Pair<Long, Integer>>> pCountMap =
422                     mProcessCrashCounts.getMap();
423             for (int ip = pCountMap.size() - 1; ip >= 0; ip--) {
424                 SparseArray<Pair<Long, Integer>> ba = pCountMap.valueAt(ip);
425                 resetProcessCrashMapLBp(ba, resetEntireUser, appId, userId);
426                 if (ba.size() == 0) {
427                     pCountMap.removeAt(ip);
428                 }
429             }
430         }
431     }
432 
433     @GuardedBy("mBadProcessLock")
resetProcessCrashMapLBp(SparseArray<?> ba, boolean resetEntireUser, int appId, int userId)434     private void resetProcessCrashMapLBp(SparseArray<?> ba, boolean resetEntireUser,
435             int appId, int userId) {
436         for (int i = ba.size() - 1; i >= 0; i--) {
437             boolean remove = false;
438             final int entUid = ba.keyAt(i);
439             if (!resetEntireUser) {
440                 if (userId == UserHandle.USER_ALL) {
441                     if (UserHandle.getAppId(entUid) == appId) {
442                         remove = true;
443                     }
444                 } else {
445                     if (entUid == UserHandle.getUid(userId, appId)) {
446                         remove = true;
447                     }
448                 }
449             } else if (UserHandle.getUserId(entUid) == userId) {
450                 remove = true;
451             }
452             if (remove) {
453                 ba.removeAt(i);
454             }
455         }
456     }
457 
loadAppsNotReportingCrashesFromConfig(String appsNotReportingCrashesConfig)458     void loadAppsNotReportingCrashesFromConfig(String appsNotReportingCrashesConfig) {
459         if (appsNotReportingCrashesConfig != null) {
460             final String[] split = appsNotReportingCrashesConfig.split(",");
461             if (split.length > 0) {
462                 synchronized (mBadProcessLock) {
463                     mAppsNotReportingCrashes = new ArraySet<>();
464                     Collections.addAll(mAppsNotReportingCrashes, split);
465                 }
466             }
467         }
468     }
469 
470     @GuardedBy("mService")
killAppAtUserRequestLocked(ProcessRecord app)471     void killAppAtUserRequestLocked(ProcessRecord app) {
472         ErrorDialogController controller = app.mErrorState.getDialogController();
473 
474         int reasonCode = ApplicationExitInfo.REASON_ANR;
475         int subReason = ApplicationExitInfo.SUBREASON_UNKNOWN;
476         synchronized (mProcLock) {
477             if (controller.hasDebugWaitingDialog()) {
478                 reasonCode = ApplicationExitInfo.REASON_OTHER;
479                 subReason = ApplicationExitInfo.SUBREASON_WAIT_FOR_DEBUGGER;
480             }
481             controller.clearAllErrorDialogs();
482             killAppImmediateLSP(app, reasonCode, subReason,
483                     "user-terminated", "user request after error");
484         }
485     }
486 
487     @GuardedBy({"mService", "mProcLock"})
killAppImmediateLSP(ProcessRecord app, int reasonCode, int subReason, String reason, String killReason)488     private void killAppImmediateLSP(ProcessRecord app, int reasonCode, int subReason,
489             String reason, String killReason) {
490         final ProcessErrorStateRecord errState = app.mErrorState;
491         errState.setCrashing(false);
492         errState.setCrashingReport(null);
493         errState.setNotResponding(false);
494         errState.setNotRespondingReport(null);
495         final int pid = errState.mApp.getPid();
496         if (pid > 0 && pid != MY_PID) {
497             synchronized (mBadProcessLock) {
498                 handleAppCrashLSPB(app, reason,
499                         null /*shortMsg*/, null /*longMsg*/, null /*stackTrace*/, null /*data*/);
500             }
501             app.killLocked(killReason, reasonCode, subReason, true);
502         }
503     }
504 
505     /**
506      * Induce a crash in the given app.
507      *
508      * @param uid if nonnegative, the required matching uid of the target to crash
509      * @param initialPid fast-path match for the target to crash
510      * @param packageName fallback match if the stated pid is not found or doesn't match uid
511      * @param userId If nonnegative, required to identify a match by package name
512      * @param message
513      */
scheduleAppCrashLocked(int uid, int initialPid, String packageName, int userId, String message, boolean force, int exceptionTypeId, @Nullable Bundle extras)514     void scheduleAppCrashLocked(int uid, int initialPid, String packageName, int userId,
515             String message, boolean force, int exceptionTypeId, @Nullable Bundle extras) {
516         ProcessRecord proc = null;
517 
518         // Figure out which process to kill.  We don't trust that initialPid
519         // still has any relation to current pids, so must scan through the
520         // list.
521 
522         synchronized (mService.mPidsSelfLocked) {
523             for (int i=0; i<mService.mPidsSelfLocked.size(); i++) {
524                 ProcessRecord p = mService.mPidsSelfLocked.valueAt(i);
525                 if (uid >= 0 && p.uid != uid) {
526                     continue;
527                 }
528                 if (p.getPid() == initialPid) {
529                     proc = p;
530                     break;
531                 }
532                 if (p.getPkgList().containsKey(packageName)
533                         && (userId < 0 || p.userId == userId)) {
534                     proc = p;
535                 }
536             }
537         }
538 
539         if (proc == null) {
540             Slog.w(TAG, "crashApplication: nothing for uid=" + uid
541                     + " initialPid=" + initialPid
542                     + " packageName=" + packageName
543                     + " userId=" + userId);
544             return;
545         }
546 
547         if (exceptionTypeId == CrashedByAdbException.TYPE_ID) {
548             String[] packages = proc.getPackageList();
549             for (int i = 0; i < packages.length; i++) {
550                 if (mService.mPackageManagerInt.isPackageStateProtected(packages[i], proc.userId)) {
551                     Slog.w(TAG, "crashApplication: Can not crash protected package " + packages[i]);
552                     return;
553                 }
554             }
555         }
556 
557         mService.mOomAdjuster.mCachedAppOptimizer.unfreezeProcess(initialPid,
558                 CachedAppOptimizer.UNFREEZE_REASON_PROCESS_END);
559         proc.scheduleCrashLocked(message, exceptionTypeId, extras);
560         if (force) {
561             // If the app is responsive, the scheduled crash will happen as expected
562             // and then the delayed summary kill will be a no-op.
563             final ProcessRecord p = proc;
564             mService.mHandler.postDelayed(
565                     () -> {
566                         synchronized (mService) {
567                             synchronized (mProcLock) {
568                                 killAppImmediateLSP(p, ApplicationExitInfo.REASON_OTHER,
569                                         ApplicationExitInfo.SUBREASON_INVALID_STATE,
570                                         "forced", "killed for invalid state");
571                             }
572                         }
573                     },
574                     5000L);
575         }
576     }
577 
sendRecoverableCrashToAppExitInfo( ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo)578     void sendRecoverableCrashToAppExitInfo(
579             ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
580         if (r == null || crashInfo == null
581                 || !"Native crash".equals(crashInfo.exceptionClassName)) return;
582         synchronized (mService) {
583             mService.mProcessList.noteAppRecoverableCrash(r);
584         }
585     }
586 
587     /**
588      * Bring up the "unexpected error" dialog box for a crashing app.
589      * Deal with edge cases (intercepts from instrumented applications,
590      * ActivityController, error intent receivers, that sort of thing).
591      * @param r the application crashing
592      * @param crashInfo describing the failure
593      */
crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo)594     void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
595         final int callingPid = Binder.getCallingPid();
596         final int callingUid = Binder.getCallingUid();
597 
598         final long origId = Binder.clearCallingIdentity();
599         try {
600             crashApplicationInner(r, crashInfo, callingPid, callingUid);
601         } finally {
602             Binder.restoreCallingIdentity(origId);
603         }
604     }
605 
crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo, int callingPid, int callingUid)606     private void crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo,
607             int callingPid, int callingUid) {
608         long timeMillis = System.currentTimeMillis();
609         String shortMsg = crashInfo.exceptionClassName;
610         String longMsg = crashInfo.exceptionMessage;
611         String stackTrace = crashInfo.stackTrace;
612         if (shortMsg != null && longMsg != null) {
613             longMsg = shortMsg + ": " + longMsg;
614         } else if (shortMsg != null) {
615             longMsg = shortMsg;
616         }
617 
618         if (r != null) {
619             mPackageWatchdog.notifyPackageFailure(r.getPackageListWithVersionCode(),
620                     PackageWatchdog.FAILURE_REASON_APP_CRASH);
621 
622             synchronized (mService) {
623                 mService.mProcessList.noteAppKill(r, (crashInfo != null
624                           && "Native crash".equals(crashInfo.exceptionClassName))
625                           ? ApplicationExitInfo.REASON_CRASH_NATIVE
626                           : ApplicationExitInfo.REASON_CRASH,
627                           ApplicationExitInfo.SUBREASON_UNKNOWN,
628                         "crash");
629             }
630         }
631 
632         final int relaunchReason = r != null
633                 ? r.getWindowProcessController().computeRelaunchReason() : RELAUNCH_REASON_NONE;
634 
635         AppErrorResult result = new AppErrorResult();
636         int taskId;
637         synchronized (mService) {
638             /**
639              * If crash is handled by instance of {@link android.app.IActivityController},
640              * finish now and don't show the app error dialog.
641              */
642             if (handleAppCrashInActivityController(r, crashInfo, shortMsg, longMsg, stackTrace,
643                     timeMillis, callingPid, callingUid)) {
644                 return;
645             }
646 
647             // Suppress crash dialog if the process is being relaunched due to a crash during a free
648             // resize.
649             if (relaunchReason == RELAUNCH_REASON_FREE_RESIZE) {
650                 return;
651             }
652 
653             /**
654              * If this process was running instrumentation, finish now - it will be handled in
655              * {@link ActivityManagerService#handleAppDiedLocked}.
656              */
657             if (r != null && r.getActiveInstrumentation() != null) {
658                 return;
659             }
660 
661             // Log crash in battery stats.
662             if (r != null) {
663                 mService.mBatteryStatsService.noteProcessCrash(r.processName, r.uid);
664             }
665 
666             AppErrorDialog.Data data = new AppErrorDialog.Data();
667             data.result = result;
668             data.proc = r;
669 
670             // If we can't identify the process or it's already exceeded its crash quota,
671             // quit right away without showing a crash dialog.
672             if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, data)) {
673                 return;
674             }
675 
676             final Message msg = Message.obtain();
677             msg.what = ActivityManagerService.SHOW_ERROR_UI_MSG;
678 
679             taskId = data.taskId;
680             msg.obj = data;
681             mService.mUiHandler.sendMessage(msg);
682         }
683 
684         int res = result.get();
685 
686         Intent appErrorIntent = null;
687         MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res);
688         if (res == AppErrorDialog.TIMEOUT || res == AppErrorDialog.CANCEL) {
689             res = AppErrorDialog.FORCE_QUIT;
690         }
691         switch (res) {
692             case AppErrorDialog.MUTE:
693                 synchronized (mBadProcessLock) {
694                     stopReportingCrashesLBp(r);
695                 }
696                 break;
697             case AppErrorDialog.RESTART:
698                 synchronized (mService) {
699                     mService.mProcessList.removeProcessLocked(r, false, true,
700                             ApplicationExitInfo.REASON_CRASH, "crash");
701                 }
702                 if (taskId != INVALID_TASK_ID) {
703                     try {
704                         mService.startActivityFromRecents(taskId,
705                                 ActivityOptions.makeBasic().toBundle());
706                     } catch (IllegalArgumentException e) {
707                         // Hmm...that didn't work. Task should either be in recents or associated
708                         // with a stack.
709                         Slog.e(TAG, "Could not restart taskId=" + taskId, e);
710                     }
711                 }
712                 break;
713             case AppErrorDialog.FORCE_QUIT:
714                 final long orig = Binder.clearCallingIdentity();
715                 try {
716                     // Kill it with fire!
717                     mService.mAtmInternal.onHandleAppCrash(r.getWindowProcessController());
718                     if (!r.isPersistent()) {
719                         synchronized (mService) {
720                             mService.mProcessList.removeProcessLocked(r, false, false,
721                                     ApplicationExitInfo.REASON_CRASH, "crash");
722                         }
723                         mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
724                     }
725                 } finally {
726                     Binder.restoreCallingIdentity(orig);
727                 }
728                 break;
729             case AppErrorDialog.APP_INFO:
730                 appErrorIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
731                 appErrorIntent.setData(Uri.parse("package:" + r.info.packageName));
732                 appErrorIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
733                 break;
734             case AppErrorDialog.FORCE_QUIT_AND_REPORT:
735                 synchronized (mProcLock) {
736                     appErrorIntent = createAppErrorIntentLOSP(r, timeMillis, crashInfo);
737                 }
738                 break;
739         }
740 
741         if (appErrorIntent != null) {
742             try {
743                 mContext.startActivityAsUser(appErrorIntent, new UserHandle(r.userId));
744             } catch (ActivityNotFoundException e) {
745                 Slog.w(TAG, "bug report receiver dissappeared", e);
746             }
747         }
748     }
749 
750     @GuardedBy("mService")
handleAppCrashInActivityController(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo, String shortMsg, String longMsg, String stackTrace, long timeMillis, int callingPid, int callingUid)751     private boolean handleAppCrashInActivityController(ProcessRecord r,
752                                                        ApplicationErrorReport.CrashInfo crashInfo,
753                                                        String shortMsg, String longMsg,
754                                                        String stackTrace, long timeMillis,
755                                                        int callingPid, int callingUid) {
756         String name = r != null ? r.processName : null;
757         int pid = r != null ? r.getPid() : callingPid;
758         int uid = r != null ? r.info.uid : callingUid;
759 
760         return mService.mAtmInternal.handleAppCrashInActivityController(
761                 name, pid, shortMsg, longMsg, timeMillis, crashInfo.stackTrace, () -> {
762                 if (Build.IS_DEBUGGABLE
763                         && "Native crash".equals(crashInfo.exceptionClassName)) {
764                     Slog.w(TAG, "Skip killing native crashed app " + name
765                             + "(" + pid + ") during testing");
766                 } else {
767                     Slog.w(TAG, "Force-killing crashed app " + name + " at watcher's request");
768                     if (r != null) {
769                         if (!makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, null)) {
770                             r.killLocked("crash", ApplicationExitInfo.REASON_CRASH, true);
771                         }
772                     } else {
773                         // Huh.
774                         Process.killProcess(pid);
775                         ProcessList.killProcessGroup(uid, pid);
776                         mService.mProcessList.noteAppKill(pid, uid,
777                                 ApplicationExitInfo.REASON_CRASH,
778                                 ApplicationExitInfo.SUBREASON_UNKNOWN,
779                                 "crash");
780                     }
781                 }
782         });
783     }
784 
785     @GuardedBy("mService")
786     private boolean makeAppCrashingLocked(ProcessRecord app,
787             String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
788         synchronized (mProcLock) {
789             final ProcessErrorStateRecord errState = app.mErrorState;
790             errState.setCrashing(true);
791             errState.setCrashingReport(generateProcessError(app,
792                     ActivityManager.ProcessErrorStateInfo.CRASHED,
793                     null, shortMsg, longMsg, stackTrace));
794             errState.startAppProblemLSP();
795             app.getWindowProcessController().stopFreezingActivities();
796             synchronized (mBadProcessLock) {
797                 return handleAppCrashLSPB(app, "force-crash" /*reason*/, shortMsg, longMsg,
798                         stackTrace, data);
799             }
800         }
801     }
802 
803     /**
804      * Generate a process error record, suitable for attachment to a ProcessRecord.
805      *
806      * @param app The ProcessRecord in which the error occurred.
807      * @param condition Crashing, Application Not Responding, etc.  Values are defined in
808      *                      ActivityManager.ProcessErrorStateInfo
809      * @param activity The activity associated with the crash, if known.
810      * @param shortMsg Short message describing the crash.
811      * @param longMsg Long message describing the crash.
812      * @param stackTrace Full crash stack trace, may be null.
813      *
814      * @return Returns a fully-formed ProcessErrorStateInfo record.
815      */
816     ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
817             int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
818         ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
819 
820         report.condition = condition;
821         report.processName = app.processName;
822         report.pid = app.getPid();
823         report.uid = app.info.uid;
824         report.tag = activity;
825         report.shortMsg = shortMsg;
826         report.longMsg = longMsg;
827         report.stackTrace = stackTrace;
828 
829         return report;
830     }
831 
832     @GuardedBy(anyOf = {"mService", "mProcLock"})
833     Intent createAppErrorIntentLOSP(ProcessRecord r,
834             long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
835         ApplicationErrorReport report = createAppErrorReportLOSP(r, timeMillis, crashInfo);
836         if (report == null) {
837             return null;
838         }
839         Intent result = new Intent(Intent.ACTION_APP_ERROR);
840         result.setComponent(r.mErrorState.getErrorReportReceiver());
841         result.putExtra(Intent.EXTRA_BUG_REPORT, report);
842         result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
843         return result;
844     }
845 
846     @GuardedBy(anyOf = {"mService", "mProcLock"})
847     private ApplicationErrorReport createAppErrorReportLOSP(ProcessRecord r,
848             long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
849         final ProcessErrorStateRecord errState = r.mErrorState;
850         if (errState.getErrorReportReceiver() == null) {
851             return null;
852         }
853 
854         if (!errState.isCrashing() && !errState.isNotResponding()
855                 && !errState.isForceCrashReport()) {
856             return null;
857         }
858 
859         ApplicationErrorReport report = new ApplicationErrorReport();
860         report.packageName = r.info.packageName;
861         report.installerPackageName = errState.getErrorReportReceiver().getPackageName();
862         report.processName = r.processName;
863         report.time = timeMillis;
864         report.systemApp = (r.info.flags & FLAG_SYSTEM) != 0;
865 
866         if (errState.isCrashing() || errState.isForceCrashReport()) {
867             report.type = ApplicationErrorReport.TYPE_CRASH;
868             report.crashInfo = crashInfo;
869         } else if (errState.isNotResponding()) {
870             final ActivityManager.ProcessErrorStateInfo anrReport =
871                     errState.getNotRespondingReport();
872             if (anrReport == null) {
873                 // The ANR dump is still ongoing, ignore it for now.
874                 return null;
875             }
876             report.type = ApplicationErrorReport.TYPE_ANR;
877             report.anrInfo = new ApplicationErrorReport.AnrInfo();
878 
879             report.anrInfo.activity = anrReport.tag;
880             report.anrInfo.cause = anrReport.shortMsg;
881             report.anrInfo.info = anrReport.longMsg;
882         }
883 
884         return report;
885     }
886 
887     @GuardedBy({"mService", "mProcLock", "mBadProcessLock"})
888     private boolean handleAppCrashLSPB(ProcessRecord app, String reason,
889             String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
890         final long now = SystemClock.uptimeMillis();
891 
892         Long crashTime;
893         Long crashTimePersistent;
894         final String processName = app.processName;
895         final int uid = app.uid;
896         final int userId = app.userId;
897         final boolean isolated = app.isolated;
898         final boolean persistent = app.isPersistent();
899         final WindowProcessController proc = app.getWindowProcessController();
900         final ProcessErrorStateRecord errState = app.mErrorState;
901         final boolean showBackground = Settings.Secure.getIntForUser(mContext.getContentResolver(),
902                 Settings.Secure.ANR_SHOW_BACKGROUND, 0, getVisibleUserId(userId)) != 0;
903 
904         if (!app.isolated) {
905             crashTime = mProcessCrashTimes.get(processName, uid);
906             crashTimePersistent = mProcessCrashTimesPersistent.get(processName, uid);
907         } else {
908             crashTime = crashTimePersistent = null;
909         }
910 
911         // Bump up the crash count of any services currently running in the proc.
912         boolean tryAgain = app.mServices.incServiceCrashCountLocked(now);
913 
914         final boolean quickCrash = crashTime != null
915                 && now < crashTime + ActivityManagerConstants.MIN_CRASH_INTERVAL;
916         if (quickCrash || isProcOverCrashLimitLBp(app, now)) {
917             // The process either crashed again very quickly or has been crashing periodically in
918             // the last few hours. If it was a bound foreground service, let's try to restart again
919             // in a while, otherwise the process loses!
920             Slog.w(TAG, "Process " + processName + " has crashed too many times, killing!"
921                     + " Reason: " + (quickCrash ? "crashed quickly" : "over process crash limit"));
922             EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
923                     userId, processName, uid);
924             mService.mAtmInternal.onHandleAppCrash(proc);
925             if (!persistent) {
926                 // We don't want to start this process again until the user
927                 // explicitly does so...  but for persistent process, we really
928                 // need to keep it running.  If a persistent process is actually
929                 // repeatedly crashing, then badness for everyone.
930                 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, userId, uid,
931                         processName);
932                 if (!isolated) {
933                     // XXX We don't have a way to mark isolated processes
934                     // as bad, since they don't have a persistent identity.
935                     markBadProcess(processName, app.uid,
936                             new BadProcessInfo(now, shortMsg, longMsg, stackTrace));
937                     mProcessCrashTimes.remove(processName, app.uid);
938                     mProcessCrashCounts.remove(processName, app.uid);
939                 }
940                 errState.setBad(true);
941                 app.setRemoved(true);
942                 final AppStandbyInternal appStandbyInternal =
943                         LocalServices.getService(AppStandbyInternal.class);
944                 if (appStandbyInternal != null) {
945                     appStandbyInternal.restrictApp(
946                             // Sometimes the processName is the same as the package name, so use
947                             // that if we don't have the ApplicationInfo object.
948                             // AppStandbyController will just return if it can't find the app.
949                             app.info != null ? app.info.packageName : processName,
950                             userId, UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY);
951                 }
952                 // Don't let services in this process be restarted and potentially
953                 // annoy the user repeatedly.  Unless it is persistent, since those
954                 // processes run critical code.
955                 mService.mProcessList.removeProcessLocked(app, false, tryAgain,
956                         ApplicationExitInfo.REASON_CRASH, "crash");
957                 mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
958                 if (!showBackground) {
959                     return false;
960                 }
961             }
962             mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
963         } else {
964             final int affectedTaskId = mService.mAtmInternal.finishTopCrashedActivities(
965                             proc, reason);
966             if (data != null) {
967                 data.taskId = affectedTaskId;
968             }
969             if (data != null && crashTimePersistent != null
970                     && now < crashTimePersistent + ActivityManagerConstants.MIN_CRASH_INTERVAL) {
971                 data.repeating = true;
972             }
973         }
974 
975         if (data != null && tryAgain) {
976             data.isRestartableForService = true;
977         }
978 
979         // If the crashing process is what we consider to be the "home process" and it has been
980         // replaced by a third-party app, clear the package preferred activities from packages
981         // with a home activity running in the process to prevent a repeatedly crashing app
982         // from blocking the user to manually clear the list.
983         if (proc.isHomeProcess() && proc.hasActivities() && (app.info.flags & FLAG_SYSTEM) == 0) {
984             proc.clearPackagePreferredForHomeActivities();
985         }
986 
987         if (!isolated) {
988             // XXX Can't keep track of crash times for isolated processes,
989             // because they don't have a persistent identity.
990             mProcessCrashTimes.put(processName, uid, now);
991             mProcessCrashTimesPersistent.put(processName, uid, now);
992             updateProcessCrashCountLBp(processName, uid, now);
993         }
994 
995         if (errState.getCrashHandler() != null) {
996             mService.mHandler.post(errState.getCrashHandler());
997         }
998         return true;
999     }
1000 
1001     @GuardedBy("mBadProcessLock")
1002     private void updateProcessCrashCountLBp(String processName, int uid, long now) {
1003         Pair<Long, Integer> count = mProcessCrashCounts.get(processName, uid);
1004         if (count == null || (count.first + PROCESS_CRASH_COUNT_RESET_INTERVAL) < now) {
1005             count = new Pair<>(now, 1);
1006         } else {
1007             count = new Pair<>(count.first, count.second + 1);
1008         }
1009         mProcessCrashCounts.put(processName, uid, count);
1010     }
1011 
1012     @GuardedBy("mBadProcessLock")
1013     private boolean isProcOverCrashLimitLBp(ProcessRecord app, long now) {
1014         final Pair<Long, Integer> crashCount = mProcessCrashCounts.get(app.processName, app.uid);
1015         return !app.isolated && crashCount != null
1016                 && now < (crashCount.first + PROCESS_CRASH_COUNT_RESET_INTERVAL)
1017                 && crashCount.second >= PROCESS_CRASH_COUNT_LIMIT;
1018     }
1019 
1020     void handleShowAppErrorUi(Message msg) {
1021         AppErrorDialog.Data data = (AppErrorDialog.Data) msg.obj;
1022 
1023         final int userId;
1024         synchronized (mProcLock) {
1025             final ProcessRecord proc = data.proc;
1026             final AppErrorResult res = data.result;
1027             if (proc == null) {
1028                 Slog.e(TAG, "handleShowAppErrorUi: proc is null");
1029                 return;
1030             }
1031             final ProcessErrorStateRecord errState = proc.mErrorState;
1032             userId = proc.userId;
1033             if (errState.getDialogController().hasCrashDialogs()) {
1034                 Slog.e(TAG, "App already has crash dialog: " + proc);
1035                 if (res != null) {
1036                     res.set(AppErrorDialog.ALREADY_SHOWING);
1037                 }
1038                 return;
1039             }
1040             boolean isBackground = (UserHandle.getAppId(proc.uid)
1041                     >= Process.FIRST_APPLICATION_UID
1042                     && proc.getPid() != MY_PID);
1043             for (int profileId : mService.mUserController.getCurrentProfileIds()) {
1044                 isBackground &= (userId != profileId);
1045             }
1046             int visibleUserId = getVisibleUserId(userId);
1047             boolean isVisibleUser = LocalServices.getService(UserManagerInternal.class)
1048                     .isVisibleBackgroundFullUser(visibleUserId);
1049             boolean showBackground = Settings.Secure.getIntForUser(mContext.getContentResolver(),
1050                     Settings.Secure.ANR_SHOW_BACKGROUND, 0, visibleUserId) != 0;
1051             if (isBackground && !showBackground && !isVisibleUser) {
1052                 Slog.w(TAG, "Skipping crash dialog of " + proc + ": background");
1053                 if (res != null) {
1054                     res.set(AppErrorDialog.BACKGROUND_USER);
1055                 }
1056                 return;
1057             }
1058             Long crashShowErrorTime = null;
1059             synchronized (mBadProcessLock) {
1060                 if (!proc.isolated) {
1061                     crashShowErrorTime = mProcessCrashShowDialogTimes.get(proc.processName,
1062                             proc.uid);
1063                 }
1064                 final boolean showFirstCrash = Settings.Global.getInt(
1065                         mContext.getContentResolver(),
1066                         Settings.Global.SHOW_FIRST_CRASH_DIALOG, 0) != 0;
1067                 final boolean showFirstCrashDevOption = Settings.Secure.getIntForUser(
1068                         mContext.getContentResolver(),
1069                         Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION,
1070                         0,
1071                         visibleUserId) != 0;
1072                 final String packageName = proc.info.packageName;
1073                 final boolean crashSilenced = mAppsNotReportingCrashes != null
1074                         && mAppsNotReportingCrashes.contains(proc.info.packageName);
1075                 final long now = SystemClock.uptimeMillis();
1076                 final boolean shouldThottle = crashShowErrorTime != null
1077                         && now < crashShowErrorTime + ActivityManagerConstants.MIN_CRASH_INTERVAL;
1078                 if ((mService.mAtmInternal.canShowErrorDialogs(visibleUserId) || showBackground)
1079                         && !crashSilenced && !shouldThottle
1080                         && (showFirstCrash || showFirstCrashDevOption || data.repeating)) {
1081                     Slog.i(TAG, "Showing crash dialog for package " + packageName + " u" + userId);
1082                     errState.getDialogController().showCrashDialogs(data);
1083                     if (!proc.isolated) {
1084                         mProcessCrashShowDialogTimes.put(proc.processName, proc.uid, now);
1085                     }
1086                 } else {
1087                     // The device is asleep, so just pretend that the user
1088                     // saw a crash dialog and hit "force quit".
1089                     if (res != null) {
1090                         res.set(AppErrorDialog.CANT_SHOW);
1091                     }
1092                 }
1093             }
1094         }
1095     }
1096 
1097     @GuardedBy("mBadProcessLock")
1098     private void stopReportingCrashesLBp(ProcessRecord proc) {
1099         if (mAppsNotReportingCrashes == null) {
1100             mAppsNotReportingCrashes = new ArraySet<>();
1101         }
1102         mAppsNotReportingCrashes.add(proc.info.packageName);
1103     }
1104 
1105     void handleShowAnrUi(Message msg) {
1106         List<VersionedPackage> packageList = null;
1107         boolean doKill = false;
1108         AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj;
1109         final ProcessRecord proc = data.proc;
1110         if (proc == null) {
1111             Slog.e(TAG, "handleShowAnrUi: proc is null");
1112             return;
1113         }
1114         synchronized (mProcLock) {
1115             final ProcessErrorStateRecord errState = proc.mErrorState;
1116             errState.setAnrData(data);
1117             if (!proc.isPersistent()) {
1118                 packageList = proc.getPackageListWithVersionCode();
1119             }
1120             if (errState.getDialogController().hasAnrDialogs()) {
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             int visibleUserId = getVisibleUserId(proc.userId);
1128             boolean showBackground = Settings.Secure.getIntForUser(mContext.getContentResolver(),
1129                     Settings.Secure.ANR_SHOW_BACKGROUND, 0, visibleUserId) != 0;
1130             if (mService.mAtmInternal.canShowErrorDialogs(visibleUserId) || showBackground) {
1131                 AnrController anrController = errState.getDialogController().getAnrController();
1132                 if (anrController == null) {
1133                     errState.getDialogController().showAnrDialogs(data);
1134                 } else {
1135                     String packageName = proc.info.packageName;
1136                     int uid = proc.info.uid;
1137                     boolean showDialog = anrController.onAnrDelayCompleted(packageName, uid);
1138 
1139                     if (showDialog) {
1140                         Slog.d(TAG, "ANR delay completed. Showing ANR dialog for package: "
1141                                 + packageName);
1142                         errState.getDialogController().showAnrDialogs(data);
1143                     } else {
1144                         Slog.d(TAG, "ANR delay completed. Cancelling ANR dialog for package: "
1145                                 + packageName);
1146                         errState.setNotResponding(false);
1147                         errState.setNotRespondingReport(null);
1148                         errState.getDialogController().clearAnrDialogs();
1149                     }
1150                 }
1151             } else {
1152                 MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
1153                         AppNotRespondingDialog.CANT_SHOW);
1154                 // Just kill the app if there is no dialog to be shown.
1155                 doKill = true;
1156             }
1157         }
1158         if (doKill) {
1159             mService.killAppAtUsersRequest(proc);
1160         }
1161         // Notify PackageWatchdog without the lock held
1162         if (packageList != null) {
1163             mPackageWatchdog.notifyPackageFailure(packageList,
1164                     PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING);
1165         }
1166     }
1167 
1168     void handleDismissAnrDialogs(ProcessRecord proc) {
1169         synchronized (mProcLock) {
1170             final ProcessErrorStateRecord errState = proc.mErrorState;
1171 
1172             // Cancel any rescheduled ANR dialogs
1173             mService.mUiHandler.removeMessages(
1174                     ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG, errState.getAnrData());
1175 
1176             // Dismiss any ANR dialogs currently visible
1177             if (errState.getDialogController().hasAnrDialogs()) {
1178                 errState.setNotResponding(false);
1179                 errState.setNotRespondingReport(null);
1180                 errState.getDialogController().clearAnrDialogs();
1181             }
1182             proc.mErrorState.setAnrData(null);
1183         }
1184     }
1185 
1186     /**
1187      * Returns the user ID of the visible user associated with the error occurrence.
1188      *
1189      * <p>For most cases it will return the current foreground user ID, but on devices that
1190      * {@link UserManager#isVisibleBackgroundUsersEnabled() support visible background users},
1191      * it will return the given app user ID passed as parameter.
1192      *
1193      * @param appUserId The user ID of the app where the error occurred.
1194      * @return The ID of the visible user associated with the error.
1195      */
1196     private int getVisibleUserId(int appUserId) {
1197         if (!UserManager.isVisibleBackgroundUsersEnabled()) {
1198             return mService.mUserController.getCurrentUserId();
1199         }
1200         return appUserId;
1201     }
1202 
1203     /**
1204      * Information about a process that is currently marked as bad.
1205      */
1206     static final class BadProcessInfo {
1207         BadProcessInfo(long time, String shortMsg, String longMsg, String stack) {
1208             this.time = time;
1209             this.shortMsg = shortMsg;
1210             this.longMsg = longMsg;
1211             this.stack = stack;
1212         }
1213 
1214         final long time;
1215         final String shortMsg;
1216         final String longMsg;
1217         final String stack;
1218     }
1219 
1220 }
1221