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