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