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 com.android.internal.app.ProcessMap; 20 import com.android.internal.logging.MetricsLogger; 21 import com.android.internal.logging.nano.MetricsProto; 22 import com.android.internal.os.ProcessCpuTracker; 23 import com.android.server.RescueParty; 24 import com.android.server.Watchdog; 25 26 import android.app.ActivityManager; 27 import android.app.ActivityOptions; 28 import android.app.ActivityThread; 29 import android.app.AppOpsManager; 30 import android.app.ApplicationErrorReport; 31 import android.app.Dialog; 32 import android.content.ActivityNotFoundException; 33 import android.content.Context; 34 import android.content.Intent; 35 import android.content.pm.ApplicationInfo; 36 import android.net.Uri; 37 import android.os.Binder; 38 import android.os.Message; 39 import android.os.Process; 40 import android.os.RemoteException; 41 import android.os.SystemClock; 42 import android.os.SystemProperties; 43 import android.os.UserHandle; 44 import android.provider.Settings; 45 import android.util.ArrayMap; 46 import android.util.ArraySet; 47 import android.util.EventLog; 48 import android.util.Log; 49 import android.util.Slog; 50 import android.util.StatsLog; 51 import android.util.SparseArray; 52 import android.util.TimeUtils; 53 import android.util.proto.ProtoOutputStream; 54 55 import java.io.File; 56 import java.io.FileDescriptor; 57 import java.io.PrintWriter; 58 import java.util.ArrayList; 59 import java.util.Collections; 60 import java.util.HashMap; 61 import java.util.Set; 62 63 import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST; 64 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR; 65 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; 66 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; 67 import static com.android.server.am.ActivityManagerService.MY_PID; 68 import static com.android.server.am.ActivityManagerService.SYSTEM_DEBUGGABLE; 69 70 /** 71 * Controls error conditions in applications. 72 */ 73 class AppErrors { 74 75 private static final String TAG = TAG_WITH_CLASS_NAME ? "AppErrors" : TAG_AM; 76 77 private final ActivityManagerService mService; 78 private final Context mContext; 79 80 private ArraySet<String> mAppsNotReportingCrashes; 81 82 /** 83 * The last time that various processes have crashed since they were last explicitly started. 84 */ 85 private final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<>(); 86 87 /** 88 * The last time that various processes have crashed (not reset even when explicitly started). 89 */ 90 private final ProcessMap<Long> mProcessCrashTimesPersistent = new ProcessMap<>(); 91 92 /** 93 * Set of applications that we consider to be bad, and will reject 94 * incoming broadcasts from (which the user has no control over). 95 * Processes are added to this set when they have crashed twice within 96 * a minimum amount of time; they are removed from it when they are 97 * later restarted (hopefully due to some user action). The value is the 98 * time it was added to the list. 99 */ 100 private final ProcessMap<BadProcessInfo> mBadProcesses = new ProcessMap<>(); 101 102 AppErrors(Context context, ActivityManagerService service)103 AppErrors(Context context, ActivityManagerService service) { 104 context.assertRuntimeOverlayThemable(); 105 mService = service; 106 mContext = context; 107 } 108 writeToProto(ProtoOutputStream proto, long fieldId, String dumpPackage)109 void writeToProto(ProtoOutputStream proto, long fieldId, String dumpPackage) { 110 if (mProcessCrashTimes.getMap().isEmpty() && mBadProcesses.getMap().isEmpty()) { 111 return; 112 } 113 114 final long token = proto.start(fieldId); 115 final long now = SystemClock.uptimeMillis(); 116 proto.write(AppErrorsProto.NOW_UPTIME_MS, now); 117 118 if (!mProcessCrashTimes.getMap().isEmpty()) { 119 final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap(); 120 final int procCount = pmap.size(); 121 for (int ip = 0; ip < procCount; ip++) { 122 final long ctoken = proto.start(AppErrorsProto.PROCESS_CRASH_TIMES); 123 final String pname = pmap.keyAt(ip); 124 final SparseArray<Long> uids = pmap.valueAt(ip); 125 final int uidCount = uids.size(); 126 127 proto.write(AppErrorsProto.ProcessCrashTime.PROCESS_NAME, pname); 128 for (int i = 0; i < uidCount; i++) { 129 final int puid = uids.keyAt(i); 130 final ProcessRecord r = mService.mProcessNames.get(pname, puid); 131 if (dumpPackage != null && (r == null || !r.pkgList.containsKey(dumpPackage))) { 132 continue; 133 } 134 final long etoken = proto.start(AppErrorsProto.ProcessCrashTime.ENTRIES); 135 proto.write(AppErrorsProto.ProcessCrashTime.Entry.UID, puid); 136 proto.write(AppErrorsProto.ProcessCrashTime.Entry.LAST_CRASHED_AT_MS, 137 uids.valueAt(i)); 138 proto.end(etoken); 139 } 140 proto.end(ctoken); 141 } 142 143 } 144 145 if (!mBadProcesses.getMap().isEmpty()) { 146 final ArrayMap<String, SparseArray<BadProcessInfo>> pmap = mBadProcesses.getMap(); 147 final int processCount = pmap.size(); 148 for (int ip = 0; ip < processCount; ip++) { 149 final long btoken = proto.start(AppErrorsProto.BAD_PROCESSES); 150 final String pname = pmap.keyAt(ip); 151 final SparseArray<BadProcessInfo> uids = pmap.valueAt(ip); 152 final int uidCount = uids.size(); 153 154 proto.write(AppErrorsProto.BadProcess.PROCESS_NAME, pname); 155 for (int i = 0; i < uidCount; i++) { 156 final int puid = uids.keyAt(i); 157 final ProcessRecord r = mService.mProcessNames.get(pname, puid); 158 if (dumpPackage != null && (r == null 159 || !r.pkgList.containsKey(dumpPackage))) { 160 continue; 161 } 162 final BadProcessInfo info = uids.valueAt(i); 163 final long etoken = proto.start(AppErrorsProto.BadProcess.ENTRIES); 164 proto.write(AppErrorsProto.BadProcess.Entry.UID, puid); 165 proto.write(AppErrorsProto.BadProcess.Entry.CRASHED_AT_MS, info.time); 166 proto.write(AppErrorsProto.BadProcess.Entry.SHORT_MSG, info.shortMsg); 167 proto.write(AppErrorsProto.BadProcess.Entry.LONG_MSG, info.longMsg); 168 proto.write(AppErrorsProto.BadProcess.Entry.STACK, info.stack); 169 proto.end(etoken); 170 } 171 proto.end(btoken); 172 } 173 } 174 175 proto.end(token); 176 } 177 dumpLocked(FileDescriptor fd, PrintWriter pw, boolean needSep, String dumpPackage)178 boolean dumpLocked(FileDescriptor fd, PrintWriter pw, boolean needSep, String dumpPackage) { 179 if (!mProcessCrashTimes.getMap().isEmpty()) { 180 boolean printed = false; 181 final long now = SystemClock.uptimeMillis(); 182 final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap(); 183 final int processCount = pmap.size(); 184 for (int ip = 0; ip < processCount; ip++) { 185 final String pname = pmap.keyAt(ip); 186 final SparseArray<Long> uids = pmap.valueAt(ip); 187 final int uidCount = uids.size(); 188 for (int i = 0; i < uidCount; i++) { 189 final int puid = uids.keyAt(i); 190 final ProcessRecord r = mService.mProcessNames.get(pname, puid); 191 if (dumpPackage != null && (r == null 192 || !r.pkgList.containsKey(dumpPackage))) { 193 continue; 194 } 195 if (!printed) { 196 if (needSep) pw.println(); 197 needSep = true; 198 pw.println(" Time since processes crashed:"); 199 printed = true; 200 } 201 pw.print(" Process "); pw.print(pname); 202 pw.print(" uid "); pw.print(puid); 203 pw.print(": last crashed "); 204 TimeUtils.formatDuration(now-uids.valueAt(i), pw); 205 pw.println(" ago"); 206 } 207 } 208 } 209 210 if (!mBadProcesses.getMap().isEmpty()) { 211 boolean printed = false; 212 final ArrayMap<String, SparseArray<BadProcessInfo>> pmap = mBadProcesses.getMap(); 213 final int processCount = pmap.size(); 214 for (int ip = 0; ip < processCount; ip++) { 215 final String pname = pmap.keyAt(ip); 216 final SparseArray<BadProcessInfo> uids = pmap.valueAt(ip); 217 final int uidCount = uids.size(); 218 for (int i = 0; i < uidCount; i++) { 219 final int puid = uids.keyAt(i); 220 final ProcessRecord r = mService.mProcessNames.get(pname, puid); 221 if (dumpPackage != null && (r == null 222 || !r.pkgList.containsKey(dumpPackage))) { 223 continue; 224 } 225 if (!printed) { 226 if (needSep) pw.println(); 227 needSep = true; 228 pw.println(" Bad processes:"); 229 printed = true; 230 } 231 final BadProcessInfo info = uids.valueAt(i); 232 pw.print(" Bad process "); pw.print(pname); 233 pw.print(" uid "); pw.print(puid); 234 pw.print(": crashed at time "); pw.println(info.time); 235 if (info.shortMsg != null) { 236 pw.print(" Short msg: "); pw.println(info.shortMsg); 237 } 238 if (info.longMsg != null) { 239 pw.print(" Long msg: "); pw.println(info.longMsg); 240 } 241 if (info.stack != null) { 242 pw.println(" Stack:"); 243 int lastPos = 0; 244 for (int pos = 0; pos < info.stack.length(); pos++) { 245 if (info.stack.charAt(pos) == '\n') { 246 pw.print(" "); 247 pw.write(info.stack, lastPos, pos-lastPos); 248 pw.println(); 249 lastPos = pos+1; 250 } 251 } 252 if (lastPos < info.stack.length()) { 253 pw.print(" "); 254 pw.write(info.stack, lastPos, info.stack.length()-lastPos); 255 pw.println(); 256 } 257 } 258 } 259 } 260 } 261 return needSep; 262 } 263 isBadProcessLocked(ApplicationInfo info)264 boolean isBadProcessLocked(ApplicationInfo info) { 265 return mBadProcesses.get(info.processName, info.uid) != null; 266 } 267 clearBadProcessLocked(ApplicationInfo info)268 void clearBadProcessLocked(ApplicationInfo info) { 269 mBadProcesses.remove(info.processName, info.uid); 270 } 271 resetProcessCrashTimeLocked(ApplicationInfo info)272 void resetProcessCrashTimeLocked(ApplicationInfo info) { 273 mProcessCrashTimes.remove(info.processName, info.uid); 274 } 275 resetProcessCrashTimeLocked(boolean resetEntireUser, int appId, int userId)276 void resetProcessCrashTimeLocked(boolean resetEntireUser, int appId, int userId) { 277 final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap(); 278 for (int ip = pmap.size() - 1; ip >= 0; ip--) { 279 SparseArray<Long> ba = pmap.valueAt(ip); 280 for (int i = ba.size() - 1; i >= 0; i--) { 281 boolean remove = false; 282 final int entUid = ba.keyAt(i); 283 if (!resetEntireUser) { 284 if (userId == UserHandle.USER_ALL) { 285 if (UserHandle.getAppId(entUid) == appId) { 286 remove = true; 287 } 288 } else { 289 if (entUid == UserHandle.getUid(userId, appId)) { 290 remove = true; 291 } 292 } 293 } else if (UserHandle.getUserId(entUid) == userId) { 294 remove = true; 295 } 296 if (remove) { 297 ba.removeAt(i); 298 } 299 } 300 if (ba.size() == 0) { 301 pmap.removeAt(ip); 302 } 303 } 304 } 305 loadAppsNotReportingCrashesFromConfigLocked(String appsNotReportingCrashesConfig)306 void loadAppsNotReportingCrashesFromConfigLocked(String appsNotReportingCrashesConfig) { 307 if (appsNotReportingCrashesConfig != null) { 308 final String[] split = appsNotReportingCrashesConfig.split(","); 309 if (split.length > 0) { 310 mAppsNotReportingCrashes = new ArraySet<>(); 311 Collections.addAll(mAppsNotReportingCrashes, split); 312 } 313 } 314 } 315 killAppAtUserRequestLocked(ProcessRecord app, Dialog fromDialog)316 void killAppAtUserRequestLocked(ProcessRecord app, Dialog fromDialog) { 317 if (app.anrDialog == fromDialog) { 318 app.anrDialog = null; 319 } 320 if (app.waitDialog == fromDialog) { 321 app.waitDialog = null; 322 } 323 killAppImmediateLocked(app, "user-terminated", "user request after error"); 324 } 325 killAppImmediateLocked(ProcessRecord app, String reason, String killReason)326 private void killAppImmediateLocked(ProcessRecord app, String reason, String killReason) { 327 app.crashing = false; 328 app.crashingReport = null; 329 app.notResponding = false; 330 app.notRespondingReport = null; 331 if (app.pid > 0 && app.pid != MY_PID) { 332 handleAppCrashLocked(app, reason, 333 null /*shortMsg*/, null /*longMsg*/, null /*stackTrace*/, null /*data*/); 334 app.kill(killReason, true); 335 } 336 } 337 338 /** 339 * Induce a crash in the given app. 340 * 341 * @param uid if nonnegative, the required matching uid of the target to crash 342 * @param initialPid fast-path match for the target to crash 343 * @param packageName fallback match if the stated pid is not found or doesn't match uid 344 * @param userId If nonnegative, required to identify a match by package name 345 * @param message 346 */ scheduleAppCrashLocked(int uid, int initialPid, String packageName, int userId, String message, boolean force)347 void scheduleAppCrashLocked(int uid, int initialPid, String packageName, int userId, 348 String message, boolean force) { 349 ProcessRecord proc = null; 350 351 // Figure out which process to kill. We don't trust that initialPid 352 // still has any relation to current pids, so must scan through the 353 // list. 354 355 synchronized (mService.mPidsSelfLocked) { 356 for (int i=0; i<mService.mPidsSelfLocked.size(); i++) { 357 ProcessRecord p = mService.mPidsSelfLocked.valueAt(i); 358 if (uid >= 0 && p.uid != uid) { 359 continue; 360 } 361 if (p.pid == initialPid) { 362 proc = p; 363 break; 364 } 365 if (p.pkgList.containsKey(packageName) 366 && (userId < 0 || p.userId == userId)) { 367 proc = p; 368 } 369 } 370 } 371 372 if (proc == null) { 373 Slog.w(TAG, "crashApplication: nothing for uid=" + uid 374 + " initialPid=" + initialPid 375 + " packageName=" + packageName 376 + " userId=" + userId); 377 return; 378 } 379 380 proc.scheduleCrash(message); 381 if (force) { 382 // If the app is responsive, the scheduled crash will happen as expected 383 // and then the delayed summary kill will be a no-op. 384 final ProcessRecord p = proc; 385 mService.mHandler.postDelayed( 386 () -> { 387 synchronized (mService) { 388 killAppImmediateLocked(p, "forced", "killed for invalid state"); 389 } 390 }, 391 5000L); 392 } 393 } 394 395 /** 396 * Bring up the "unexpected error" dialog box for a crashing app. 397 * Deal with edge cases (intercepts from instrumented applications, 398 * ActivityController, error intent receivers, that sort of thing). 399 * @param r the application crashing 400 * @param crashInfo describing the failure 401 */ crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo)402 void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) { 403 final int callingPid = Binder.getCallingPid(); 404 final int callingUid = Binder.getCallingUid(); 405 406 final long origId = Binder.clearCallingIdentity(); 407 try { 408 crashApplicationInner(r, crashInfo, callingPid, callingUid); 409 } finally { 410 Binder.restoreCallingIdentity(origId); 411 } 412 } 413 crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo, int callingPid, int callingUid)414 void crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo, 415 int callingPid, int callingUid) { 416 long timeMillis = System.currentTimeMillis(); 417 String shortMsg = crashInfo.exceptionClassName; 418 String longMsg = crashInfo.exceptionMessage; 419 String stackTrace = crashInfo.stackTrace; 420 if (shortMsg != null && longMsg != null) { 421 longMsg = shortMsg + ": " + longMsg; 422 } else if (shortMsg != null) { 423 longMsg = shortMsg; 424 } 425 426 // If a persistent app is stuck in a crash loop, the device isn't very 427 // usable, so we want to consider sending out a rescue party. 428 if (r != null && r.persistent) { 429 RescueParty.notePersistentAppCrash(mContext, r.uid); 430 } 431 432 AppErrorResult result = new AppErrorResult(); 433 TaskRecord task; 434 synchronized (mService) { 435 /** 436 * If crash is handled by instance of {@link android.app.IActivityController}, 437 * finish now and don't show the app error dialog. 438 */ 439 if (handleAppCrashInActivityController(r, crashInfo, shortMsg, longMsg, stackTrace, 440 timeMillis, callingPid, callingUid)) { 441 return; 442 } 443 444 /** 445 * If this process was running instrumentation, finish now - it will be handled in 446 * {@link ActivityManagerService#handleAppDiedLocked}. 447 */ 448 if (r != null && r.instr != null) { 449 return; 450 } 451 452 // Log crash in battery stats. 453 if (r != null) { 454 mService.mBatteryStatsService.noteProcessCrash(r.processName, r.uid); 455 } 456 457 AppErrorDialog.Data data = new AppErrorDialog.Data(); 458 data.result = result; 459 data.proc = r; 460 461 // If we can't identify the process or it's already exceeded its crash quota, 462 // quit right away without showing a crash dialog. 463 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, data)) { 464 return; 465 } 466 467 final Message msg = Message.obtain(); 468 msg.what = ActivityManagerService.SHOW_ERROR_UI_MSG; 469 470 task = data.task; 471 msg.obj = data; 472 mService.mUiHandler.sendMessage(msg); 473 } 474 475 int res = result.get(); 476 477 Intent appErrorIntent = null; 478 MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res); 479 if (res == AppErrorDialog.TIMEOUT || res == AppErrorDialog.CANCEL) { 480 res = AppErrorDialog.FORCE_QUIT; 481 } 482 synchronized (mService) { 483 if (res == AppErrorDialog.MUTE) { 484 stopReportingCrashesLocked(r); 485 } 486 if (res == AppErrorDialog.RESTART) { 487 mService.removeProcessLocked(r, false, true, "crash"); 488 if (task != null) { 489 try { 490 mService.startActivityFromRecents(task.taskId, 491 ActivityOptions.makeBasic().toBundle()); 492 } catch (IllegalArgumentException e) { 493 // Hmm, that didn't work, app might have crashed before creating a 494 // recents entry. Let's see if we have a safe-to-restart intent. 495 final Set<String> cats = task.intent != null 496 ? task.intent.getCategories() : null; 497 if (cats != null && cats.contains(Intent.CATEGORY_LAUNCHER)) { 498 mService.getActivityStartController().startActivityInPackage( 499 task.mCallingUid, callingPid, callingUid, task.mCallingPackage, 500 task.intent, null, null, null, 0, 0, 501 new SafeActivityOptions(ActivityOptions.makeBasic()), 502 task.userId, null, 503 "AppErrors", false /*validateIncomingUser*/); 504 } 505 } 506 } 507 } 508 if (res == AppErrorDialog.FORCE_QUIT) { 509 long orig = Binder.clearCallingIdentity(); 510 try { 511 // Kill it with fire! 512 mService.mStackSupervisor.handleAppCrashLocked(r); 513 if (!r.persistent) { 514 mService.removeProcessLocked(r, false, false, "crash"); 515 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked(); 516 } 517 } finally { 518 Binder.restoreCallingIdentity(orig); 519 } 520 } 521 if (res == AppErrorDialog.APP_INFO) { 522 appErrorIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); 523 appErrorIntent.setData(Uri.parse("package:" + r.info.packageName)); 524 appErrorIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 525 } 526 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) { 527 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo); 528 } 529 if (r != null && !r.isolated && res != AppErrorDialog.RESTART) { 530 // XXX Can't keep track of crash time for isolated processes, 531 // since they don't have a persistent identity. 532 mProcessCrashTimes.put(r.info.processName, r.uid, 533 SystemClock.uptimeMillis()); 534 } 535 } 536 537 if (appErrorIntent != null) { 538 try { 539 mContext.startActivityAsUser(appErrorIntent, new UserHandle(r.userId)); 540 } catch (ActivityNotFoundException e) { 541 Slog.w(TAG, "bug report receiver dissappeared", e); 542 } 543 } 544 } 545 handleAppCrashInActivityController(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo, String shortMsg, String longMsg, String stackTrace, long timeMillis, int callingPid, int callingUid)546 private boolean handleAppCrashInActivityController(ProcessRecord r, 547 ApplicationErrorReport.CrashInfo crashInfo, 548 String shortMsg, String longMsg, 549 String stackTrace, long timeMillis, 550 int callingPid, int callingUid) { 551 if (mService.mController == null) { 552 return false; 553 } 554 555 try { 556 String name = r != null ? r.processName : null; 557 int pid = r != null ? r.pid : callingPid; 558 int uid = r != null ? r.info.uid : callingUid; 559 if (!mService.mController.appCrashed(name, pid, 560 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) { 561 if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")) 562 && "Native crash".equals(crashInfo.exceptionClassName)) { 563 Slog.w(TAG, "Skip killing native crashed app " + name 564 + "(" + pid + ") during testing"); 565 } else { 566 Slog.w(TAG, "Force-killing crashed app " + name 567 + " at watcher's request"); 568 if (r != null) { 569 if (!makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, null)) 570 { 571 r.kill("crash", true); 572 } 573 } else { 574 // Huh. 575 Process.killProcess(pid); 576 ActivityManagerService.killProcessGroup(uid, pid); 577 } 578 } 579 return true; 580 } 581 } catch (RemoteException e) { 582 mService.mController = null; 583 Watchdog.getInstance().setActivityController(null); 584 } 585 return false; 586 } 587 makeAppCrashingLocked(ProcessRecord app, String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data)588 private boolean makeAppCrashingLocked(ProcessRecord app, 589 String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) { 590 app.crashing = true; 591 app.crashingReport = generateProcessError(app, 592 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace); 593 startAppProblemLocked(app); 594 app.stopFreezingAllLocked(); 595 return handleAppCrashLocked(app, "force-crash" /*reason*/, shortMsg, longMsg, stackTrace, 596 data); 597 } 598 startAppProblemLocked(ProcessRecord app)599 void startAppProblemLocked(ProcessRecord app) { 600 // If this app is not running under the current user, then we 601 // can't give it a report button because that would require 602 // launching the report UI under a different user. 603 app.errorReportReceiver = null; 604 605 for (int userId : mService.mUserController.getCurrentProfileIds()) { 606 if (app.userId == userId) { 607 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver( 608 mContext, app.info.packageName, app.info.flags); 609 } 610 } 611 mService.skipCurrentReceiverLocked(app); 612 } 613 614 /** 615 * Generate a process error record, suitable for attachment to a ProcessRecord. 616 * 617 * @param app The ProcessRecord in which the error occurred. 618 * @param condition Crashing, Application Not Responding, etc. Values are defined in 619 * ActivityManager.ProcessErrorStateInfo 620 * @param activity The activity associated with the crash, if known. 621 * @param shortMsg Short message describing the crash. 622 * @param longMsg Long message describing the crash. 623 * @param stackTrace Full crash stack trace, may be null. 624 * 625 * @return Returns a fully-formed ProcessErrorStateInfo record. 626 */ generateProcessError(ProcessRecord app, int condition, String activity, String shortMsg, String longMsg, String stackTrace)627 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app, 628 int condition, String activity, String shortMsg, String longMsg, String stackTrace) { 629 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo(); 630 631 report.condition = condition; 632 report.processName = app.processName; 633 report.pid = app.pid; 634 report.uid = app.info.uid; 635 report.tag = activity; 636 report.shortMsg = shortMsg; 637 report.longMsg = longMsg; 638 report.stackTrace = stackTrace; 639 640 return report; 641 } 642 createAppErrorIntentLocked(ProcessRecord r, long timeMillis, ApplicationErrorReport.CrashInfo crashInfo)643 Intent createAppErrorIntentLocked(ProcessRecord r, 644 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) { 645 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo); 646 if (report == null) { 647 return null; 648 } 649 Intent result = new Intent(Intent.ACTION_APP_ERROR); 650 result.setComponent(r.errorReportReceiver); 651 result.putExtra(Intent.EXTRA_BUG_REPORT, report); 652 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 653 return result; 654 } 655 createAppErrorReportLocked(ProcessRecord r, long timeMillis, ApplicationErrorReport.CrashInfo crashInfo)656 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r, 657 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) { 658 if (r.errorReportReceiver == null) { 659 return null; 660 } 661 662 if (!r.crashing && !r.notResponding && !r.forceCrashReport) { 663 return null; 664 } 665 666 ApplicationErrorReport report = new ApplicationErrorReport(); 667 report.packageName = r.info.packageName; 668 report.installerPackageName = r.errorReportReceiver.getPackageName(); 669 report.processName = r.processName; 670 report.time = timeMillis; 671 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0; 672 673 if (r.crashing || r.forceCrashReport) { 674 report.type = ApplicationErrorReport.TYPE_CRASH; 675 report.crashInfo = crashInfo; 676 } else if (r.notResponding) { 677 report.type = ApplicationErrorReport.TYPE_ANR; 678 report.anrInfo = new ApplicationErrorReport.AnrInfo(); 679 680 report.anrInfo.activity = r.notRespondingReport.tag; 681 report.anrInfo.cause = r.notRespondingReport.shortMsg; 682 report.anrInfo.info = r.notRespondingReport.longMsg; 683 } 684 685 return report; 686 } 687 handleAppCrashLocked(ProcessRecord app, String reason, String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data)688 boolean handleAppCrashLocked(ProcessRecord app, String reason, 689 String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) { 690 final long now = SystemClock.uptimeMillis(); 691 final boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(), 692 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0; 693 694 final boolean procIsBoundForeground = 695 (app.curProcState == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE); 696 697 Long crashTime; 698 Long crashTimePersistent; 699 boolean tryAgain = false; 700 701 if (!app.isolated) { 702 crashTime = mProcessCrashTimes.get(app.info.processName, app.uid); 703 crashTimePersistent = mProcessCrashTimesPersistent.get(app.info.processName, app.uid); 704 } else { 705 crashTime = crashTimePersistent = null; 706 } 707 708 // Bump up the crash count of any services currently running in the proc. 709 for (int i = app.services.size() - 1; i >= 0; i--) { 710 // Any services running in the application need to be placed 711 // back in the pending list. 712 ServiceRecord sr = app.services.valueAt(i); 713 // If the service was restarted a while ago, then reset crash count, else increment it. 714 if (now > sr.restartTime + ProcessList.MIN_CRASH_INTERVAL) { 715 sr.crashCount = 1; 716 } else { 717 sr.crashCount++; 718 } 719 // Allow restarting for started or bound foreground services that are crashing. 720 // This includes wallpapers. 721 if (sr.crashCount < mService.mConstants.BOUND_SERVICE_MAX_CRASH_RETRY 722 && (sr.isForeground || procIsBoundForeground)) { 723 tryAgain = true; 724 } 725 } 726 727 if (crashTime != null && now < crashTime + ProcessList.MIN_CRASH_INTERVAL) { 728 // The process crashed again very quickly. If it was a bound foreground service, let's 729 // try to restart again in a while, otherwise the process loses! 730 Slog.w(TAG, "Process " + app.info.processName 731 + " has crashed too many times: killing!"); 732 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH, 733 app.userId, app.info.processName, app.uid); 734 mService.mStackSupervisor.handleAppCrashLocked(app); 735 if (!app.persistent) { 736 // We don't want to start this process again until the user 737 // explicitly does so... but for persistent process, we really 738 // need to keep it running. If a persistent process is actually 739 // repeatedly crashing, then badness for everyone. 740 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.userId, app.uid, 741 app.info.processName); 742 if (!app.isolated) { 743 // XXX We don't have a way to mark isolated processes 744 // as bad, since they don't have a peristent identity. 745 mBadProcesses.put(app.info.processName, app.uid, 746 new BadProcessInfo(now, shortMsg, longMsg, stackTrace)); 747 mProcessCrashTimes.remove(app.info.processName, app.uid); 748 } 749 app.bad = true; 750 app.removed = true; 751 // Don't let services in this process be restarted and potentially 752 // annoy the user repeatedly. Unless it is persistent, since those 753 // processes run critical code. 754 mService.removeProcessLocked(app, false, tryAgain, "crash"); 755 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked(); 756 if (!showBackground) { 757 return false; 758 } 759 } 760 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked(); 761 } else { 762 final TaskRecord affectedTask = 763 mService.mStackSupervisor.finishTopCrashedActivitiesLocked(app, reason); 764 if (data != null) { 765 data.task = affectedTask; 766 } 767 if (data != null && crashTimePersistent != null 768 && now < crashTimePersistent + ProcessList.MIN_CRASH_INTERVAL) { 769 data.repeating = true; 770 } 771 } 772 773 if (data != null && tryAgain) { 774 data.isRestartableForService = true; 775 } 776 777 // If the crashing process is what we consider to be the "home process" and it has been 778 // replaced by a third-party app, clear the package preferred activities from packages 779 // with a home activity running in the process to prevent a repeatedly crashing app 780 // from blocking the user to manually clear the list. 781 final ArrayList<ActivityRecord> activities = app.activities; 782 if (app == mService.mHomeProcess && activities.size() > 0 783 && (mService.mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { 784 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 785 final ActivityRecord r = activities.get(activityNdx); 786 if (r.isActivityTypeHome()) { 787 Log.i(TAG, "Clearing package preferred activities from " + r.packageName); 788 try { 789 ActivityThread.getPackageManager() 790 .clearPackagePreferredActivities(r.packageName); 791 } catch (RemoteException c) { 792 // pm is in same process, this will never happen. 793 } 794 } 795 } 796 } 797 798 if (!app.isolated) { 799 // XXX Can't keep track of crash times for isolated processes, 800 // because they don't have a persistent identity. 801 mProcessCrashTimes.put(app.info.processName, app.uid, now); 802 mProcessCrashTimesPersistent.put(app.info.processName, app.uid, now); 803 } 804 805 if (app.crashHandler != null) mService.mHandler.post(app.crashHandler); 806 return true; 807 } 808 handleShowAppErrorUi(Message msg)809 void handleShowAppErrorUi(Message msg) { 810 AppErrorDialog.Data data = (AppErrorDialog.Data) msg.obj; 811 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(), 812 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0; 813 814 AppErrorDialog dialogToShow = null; 815 final String packageName; 816 final int userId; 817 synchronized (mService) { 818 final ProcessRecord proc = data.proc; 819 final AppErrorResult res = data.result; 820 if (proc == null) { 821 Slog.e(TAG, "handleShowAppErrorUi: proc is null"); 822 return; 823 } 824 packageName = proc.info.packageName; 825 userId = proc.userId; 826 if (proc.crashDialog != null) { 827 Slog.e(TAG, "App already has crash dialog: " + proc); 828 if (res != null) { 829 res.set(AppErrorDialog.ALREADY_SHOWING); 830 } 831 return; 832 } 833 boolean isBackground = (UserHandle.getAppId(proc.uid) 834 >= Process.FIRST_APPLICATION_UID 835 && proc.pid != MY_PID); 836 for (int profileId : mService.mUserController.getCurrentProfileIds()) { 837 isBackground &= (userId != profileId); 838 } 839 if (isBackground && !showBackground) { 840 Slog.w(TAG, "Skipping crash dialog of " + proc + ": background"); 841 if (res != null) { 842 res.set(AppErrorDialog.BACKGROUND_USER); 843 } 844 return; 845 } 846 final boolean showFirstCrash = Settings.Global.getInt( 847 mContext.getContentResolver(), 848 Settings.Global.SHOW_FIRST_CRASH_DIALOG, 0) != 0; 849 final boolean showFirstCrashDevOption = Settings.Secure.getIntForUser( 850 mContext.getContentResolver(), 851 Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION, 852 0, 853 mService.mUserController.getCurrentUserId()) != 0; 854 final boolean crashSilenced = mAppsNotReportingCrashes != null && 855 mAppsNotReportingCrashes.contains(proc.info.packageName); 856 if ((mService.canShowErrorDialogs() || showBackground) && !crashSilenced 857 && (showFirstCrash || showFirstCrashDevOption || data.repeating)) { 858 proc.crashDialog = dialogToShow = new AppErrorDialog(mContext, mService, data); 859 } else { 860 // The device is asleep, so just pretend that the user 861 // saw a crash dialog and hit "force quit". 862 if (res != null) { 863 res.set(AppErrorDialog.CANT_SHOW); 864 } 865 } 866 } 867 // If we've created a crash dialog, show it without the lock held 868 if (dialogToShow != null) { 869 Slog.i(TAG, "Showing crash dialog for package " + packageName + " u" + userId); 870 dialogToShow.show(); 871 } 872 } 873 stopReportingCrashesLocked(ProcessRecord proc)874 void stopReportingCrashesLocked(ProcessRecord proc) { 875 if (mAppsNotReportingCrashes == null) { 876 mAppsNotReportingCrashes = new ArraySet<>(); 877 } 878 mAppsNotReportingCrashes.add(proc.info.packageName); 879 } 880 isInterestingForBackgroundTraces(ProcessRecord app)881 static boolean isInterestingForBackgroundTraces(ProcessRecord app) { 882 // The system_server is always considered interesting. 883 if (app.pid == MY_PID) { 884 return true; 885 } 886 887 // A package is considered interesting if any of the following is true : 888 // 889 // - It's displaying an activity. 890 // - It's the SystemUI. 891 // - It has an overlay or a top UI visible. 892 // 893 // NOTE: The check whether a given ProcessRecord belongs to the systemui 894 // process is a bit of a kludge, but the same pattern seems repeated at 895 // several places in the system server. 896 return app.isInterestingToUserLocked() || 897 (app.info != null && "com.android.systemui".equals(app.info.packageName)) || 898 (app.hasTopUi || app.hasOverlayUi); 899 } 900 appNotResponding(ProcessRecord app, ActivityRecord activity, ActivityRecord parent, boolean aboveSystem, final String annotation)901 final void appNotResponding(ProcessRecord app, ActivityRecord activity, 902 ActivityRecord parent, boolean aboveSystem, final String annotation) { 903 ArrayList<Integer> firstPids = new ArrayList<Integer>(5); 904 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20); 905 906 if (mService.mController != null) { 907 try { 908 // 0 == continue, -1 = kill process immediately 909 int res = mService.mController.appEarlyNotResponding( 910 app.processName, app.pid, annotation); 911 if (res < 0 && app.pid != MY_PID) { 912 app.kill("anr", true); 913 } 914 } catch (RemoteException e) { 915 mService.mController = null; 916 Watchdog.getInstance().setActivityController(null); 917 } 918 } 919 920 long anrTime = SystemClock.uptimeMillis(); 921 if (ActivityManagerService.MONITOR_CPU_USAGE) { 922 mService.updateCpuStatsNow(); 923 } 924 925 // Unless configured otherwise, swallow ANRs in background processes & kill the process. 926 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(), 927 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0; 928 929 boolean isSilentANR; 930 931 synchronized (mService) { 932 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down. 933 if (mService.mShuttingDown) { 934 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation); 935 return; 936 } else if (app.notResponding) { 937 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation); 938 return; 939 } else if (app.crashing) { 940 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation); 941 return; 942 } else if (app.killedByAm) { 943 Slog.i(TAG, "App already killed by AM skipping ANR: " + app + " " + annotation); 944 return; 945 } else if (app.killed) { 946 Slog.i(TAG, "Skipping died app ANR: " + app + " " + annotation); 947 return; 948 } 949 950 // In case we come through here for the same app before completing 951 // this one, mark as anring now so we will bail out. 952 app.notResponding = true; 953 954 // Log the ANR to the event log. 955 EventLog.writeEvent(EventLogTags.AM_ANR, app.userId, app.pid, 956 app.processName, app.info.flags, annotation); 957 958 // Dump thread traces as quickly as we can, starting with "interesting" processes. 959 firstPids.add(app.pid); 960 961 // Don't dump other PIDs if it's a background ANR 962 isSilentANR = !showBackground && !isInterestingForBackgroundTraces(app); 963 if (!isSilentANR) { 964 int parentPid = app.pid; 965 if (parent != null && parent.app != null && parent.app.pid > 0) { 966 parentPid = parent.app.pid; 967 } 968 if (parentPid != app.pid) firstPids.add(parentPid); 969 970 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID); 971 972 for (int i = mService.mLruProcesses.size() - 1; i >= 0; i--) { 973 ProcessRecord r = mService.mLruProcesses.get(i); 974 if (r != null && r.thread != null) { 975 int pid = r.pid; 976 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) { 977 if (r.persistent) { 978 firstPids.add(pid); 979 if (DEBUG_ANR) Slog.i(TAG, "Adding persistent proc: " + r); 980 } else if (r.treatLikeActivity) { 981 firstPids.add(pid); 982 if (DEBUG_ANR) Slog.i(TAG, "Adding likely IME: " + r); 983 } else { 984 lastPids.put(pid, Boolean.TRUE); 985 if (DEBUG_ANR) Slog.i(TAG, "Adding ANR proc: " + r); 986 } 987 } 988 } 989 } 990 } 991 } 992 993 // Log the ANR to the main log. 994 StringBuilder info = new StringBuilder(); 995 info.setLength(0); 996 info.append("ANR in ").append(app.processName); 997 if (activity != null && activity.shortComponentName != null) { 998 info.append(" (").append(activity.shortComponentName).append(")"); 999 } 1000 info.append("\n"); 1001 info.append("PID: ").append(app.pid).append("\n"); 1002 if (annotation != null) { 1003 info.append("Reason: ").append(annotation).append("\n"); 1004 } 1005 if (parent != null && parent != activity) { 1006 info.append("Parent: ").append(parent.shortComponentName).append("\n"); 1007 } 1008 1009 ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true); 1010 1011 // don't dump native PIDs for background ANRs unless it is the process of interest 1012 String[] nativeProcs = null; 1013 if (isSilentANR) { 1014 for (int i = 0; i < NATIVE_STACKS_OF_INTEREST.length; i++) { 1015 if (NATIVE_STACKS_OF_INTEREST[i].equals(app.processName)) { 1016 nativeProcs = new String[] { app.processName }; 1017 break; 1018 } 1019 } 1020 } else { 1021 nativeProcs = NATIVE_STACKS_OF_INTEREST; 1022 } 1023 1024 int[] pids = nativeProcs == null ? null : Process.getPidsForCommands(nativeProcs); 1025 ArrayList<Integer> nativePids = null; 1026 1027 if (pids != null) { 1028 nativePids = new ArrayList<Integer>(pids.length); 1029 for (int i : pids) { 1030 nativePids.add(i); 1031 } 1032 } 1033 1034 // For background ANRs, don't pass the ProcessCpuTracker to 1035 // avoid spending 1/2 second collecting stats to rank lastPids. 1036 File tracesFile = ActivityManagerService.dumpStackTraces( 1037 true, firstPids, 1038 (isSilentANR) ? null : processCpuTracker, 1039 (isSilentANR) ? null : lastPids, 1040 nativePids); 1041 1042 String cpuInfo = null; 1043 if (ActivityManagerService.MONITOR_CPU_USAGE) { 1044 mService.updateCpuStatsNow(); 1045 synchronized (mService.mProcessCpuTracker) { 1046 cpuInfo = mService.mProcessCpuTracker.printCurrentState(anrTime); 1047 } 1048 info.append(processCpuTracker.printCurrentLoad()); 1049 info.append(cpuInfo); 1050 } 1051 1052 info.append(processCpuTracker.printCurrentState(anrTime)); 1053 1054 Slog.e(TAG, info.toString()); 1055 if (tracesFile == null) { 1056 // There is no trace file, so dump (only) the alleged culprit's threads to the log 1057 Process.sendSignal(app.pid, Process.SIGNAL_QUIT); 1058 } 1059 1060 StatsLog.write(StatsLog.ANR_OCCURRED, app.uid, app.processName, 1061 activity == null ? "unknown": activity.shortComponentName, annotation, 1062 (app.info != null) ? (app.info.isInstantApp() 1063 ? StatsLog.ANROCCURRED__IS_INSTANT_APP__TRUE 1064 : StatsLog.ANROCCURRED__IS_INSTANT_APP__FALSE) 1065 : StatsLog.ANROCCURRED__IS_INSTANT_APP__UNAVAILABLE, 1066 app != null ? (app.isInterestingToUserLocked() 1067 ? StatsLog.ANROCCURRED__FOREGROUND_STATE__FOREGROUND 1068 : StatsLog.ANROCCURRED__FOREGROUND_STATE__BACKGROUND) 1069 : StatsLog.ANROCCURRED__FOREGROUND_STATE__UNKNOWN); 1070 mService.addErrorToDropBox("anr", app, app.processName, activity, parent, annotation, 1071 cpuInfo, tracesFile, null); 1072 1073 if (mService.mController != null) { 1074 try { 1075 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately 1076 int res = mService.mController.appNotResponding( 1077 app.processName, app.pid, info.toString()); 1078 if (res != 0) { 1079 if (res < 0 && app.pid != MY_PID) { 1080 app.kill("anr", true); 1081 } else { 1082 synchronized (mService) { 1083 mService.mServices.scheduleServiceTimeoutLocked(app); 1084 } 1085 } 1086 return; 1087 } 1088 } catch (RemoteException e) { 1089 mService.mController = null; 1090 Watchdog.getInstance().setActivityController(null); 1091 } 1092 } 1093 1094 synchronized (mService) { 1095 mService.mBatteryStatsService.noteProcessAnr(app.processName, app.uid); 1096 1097 if (isSilentANR) { 1098 app.kill("bg anr", true); 1099 return; 1100 } 1101 1102 // Set the app's notResponding state, and look up the errorReportReceiver 1103 makeAppNotRespondingLocked(app, 1104 activity != null ? activity.shortComponentName : null, 1105 annotation != null ? "ANR " + annotation : "ANR", 1106 info.toString()); 1107 1108 // Bring up the infamous App Not Responding dialog 1109 Message msg = Message.obtain(); 1110 msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG; 1111 msg.obj = new AppNotRespondingDialog.Data(app, activity, aboveSystem); 1112 1113 mService.mUiHandler.sendMessage(msg); 1114 } 1115 } 1116 makeAppNotRespondingLocked(ProcessRecord app, String activity, String shortMsg, String longMsg)1117 private void makeAppNotRespondingLocked(ProcessRecord app, 1118 String activity, String shortMsg, String longMsg) { 1119 app.notResponding = true; 1120 app.notRespondingReport = generateProcessError(app, 1121 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING, 1122 activity, shortMsg, longMsg, null); 1123 startAppProblemLocked(app); 1124 app.stopFreezingAllLocked(); 1125 } 1126 handleShowAnrUi(Message msg)1127 void handleShowAnrUi(Message msg) { 1128 Dialog dialogToShow = null; 1129 synchronized (mService) { 1130 AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj; 1131 final ProcessRecord proc = data.proc; 1132 if (proc == null) { 1133 Slog.e(TAG, "handleShowAnrUi: proc is null"); 1134 return; 1135 } 1136 if (proc.anrDialog != null) { 1137 Slog.e(TAG, "App already has anr dialog: " + proc); 1138 MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR, 1139 AppNotRespondingDialog.ALREADY_SHOWING); 1140 return; 1141 } 1142 1143 Intent intent = new Intent("android.intent.action.ANR"); 1144 if (!mService.mProcessesReady) { 1145 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY 1146 | Intent.FLAG_RECEIVER_FOREGROUND); 1147 } 1148 mService.broadcastIntentLocked(null, null, intent, 1149 null, null, 0, null, null, null, AppOpsManager.OP_NONE, 1150 null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */); 1151 1152 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(), 1153 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0; 1154 if (mService.canShowErrorDialogs() || showBackground) { 1155 dialogToShow = new AppNotRespondingDialog(mService, mContext, data); 1156 proc.anrDialog = dialogToShow; 1157 } else { 1158 MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR, 1159 AppNotRespondingDialog.CANT_SHOW); 1160 // Just kill the app if there is no dialog to be shown. 1161 mService.killAppAtUsersRequest(proc, null); 1162 } 1163 } 1164 // If we've created a crash dialog, show it without the lock held 1165 if (dialogToShow != null) { 1166 dialogToShow.show(); 1167 } 1168 } 1169 1170 /** 1171 * Information about a process that is currently marked as bad. 1172 */ 1173 static final class BadProcessInfo { BadProcessInfo(long time, String shortMsg, String longMsg, String stack)1174 BadProcessInfo(long time, String shortMsg, String longMsg, String stack) { 1175 this.time = time; 1176 this.shortMsg = shortMsg; 1177 this.longMsg = longMsg; 1178 this.stack = stack; 1179 } 1180 1181 final long time; 1182 final String shortMsg; 1183 final String longMsg; 1184 final String stack; 1185 } 1186 1187 } 1188