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