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