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