AppErrors.java revision 5719028766f51512beffa623db7ee682851570a0
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 17package com.android.server.am; 18 19import com.android.internal.app.ProcessMap; 20import com.android.internal.logging.MetricsLogger; 21import com.android.internal.logging.MetricsProto; 22import com.android.internal.os.ProcessCpuTracker; 23import com.android.server.Watchdog; 24 25import android.app.Activity; 26import android.app.ActivityManager; 27import android.app.ActivityOptions; 28import android.app.ActivityThread; 29import android.app.AppOpsManager; 30import android.app.ApplicationErrorReport; 31import android.app.Dialog; 32import android.content.ActivityNotFoundException; 33import android.content.Context; 34import android.content.Intent; 35import android.content.pm.ApplicationInfo; 36import android.content.pm.IPackageDataObserver; 37import android.content.pm.PackageManager; 38import android.os.Binder; 39import android.os.Bundle; 40import android.os.Message; 41import android.os.Process; 42import android.os.RemoteException; 43import android.os.SystemClock; 44import android.os.SystemProperties; 45import android.os.UserHandle; 46import android.provider.Settings; 47import android.util.ArrayMap; 48import android.util.ArraySet; 49import android.util.EventLog; 50import android.util.Log; 51import android.util.Slog; 52import android.util.SparseArray; 53import android.util.TimeUtils; 54 55import java.io.File; 56import java.io.FileDescriptor; 57import java.io.PrintWriter; 58import java.util.ArrayList; 59import java.util.Collections; 60import java.util.HashMap; 61import java.util.concurrent.Semaphore; 62 63import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST; 64import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR; 65import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; 66import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; 67import static com.android.server.am.ActivityManagerService.MY_PID; 68import static com.android.server.am.ActivityManagerService.SYSTEM_DEBUGGABLE; 69 70/** 71 * Controls error conditions in applications. 72 */ 73class 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 103 AppErrors(Context context, ActivityManagerService service) { 104 mService = service; 105 mContext = context; 106 } 107 108 boolean dumpLocked(FileDescriptor fd, PrintWriter pw, boolean needSep, 109 String dumpPackage) { 110 if (!mProcessCrashTimes.getMap().isEmpty()) { 111 boolean printed = false; 112 final long now = SystemClock.uptimeMillis(); 113 final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap(); 114 final int processCount = pmap.size(); 115 for (int ip = 0; ip < processCount; ip++) { 116 final String pname = pmap.keyAt(ip); 117 final SparseArray<Long> uids = pmap.valueAt(ip); 118 final int uidCount = uids.size(); 119 for (int i = 0; i < uidCount; i++) { 120 final int puid = uids.keyAt(i); 121 final ProcessRecord r = mService.mProcessNames.get(pname, puid); 122 if (dumpPackage != null && (r == null 123 || !r.pkgList.containsKey(dumpPackage))) { 124 continue; 125 } 126 if (!printed) { 127 if (needSep) pw.println(); 128 needSep = true; 129 pw.println(" Time since processes crashed:"); 130 printed = true; 131 } 132 pw.print(" Process "); pw.print(pname); 133 pw.print(" uid "); pw.print(puid); 134 pw.print(": last crashed "); 135 TimeUtils.formatDuration(now-uids.valueAt(i), pw); 136 pw.println(" ago"); 137 } 138 } 139 } 140 141 if (!mBadProcesses.getMap().isEmpty()) { 142 boolean printed = false; 143 final ArrayMap<String, SparseArray<BadProcessInfo>> pmap = mBadProcesses.getMap(); 144 final int processCount = pmap.size(); 145 for (int ip = 0; ip < processCount; ip++) { 146 final String pname = pmap.keyAt(ip); 147 final SparseArray<BadProcessInfo> uids = pmap.valueAt(ip); 148 final int uidCount = uids.size(); 149 for (int i = 0; i < uidCount; i++) { 150 final int puid = uids.keyAt(i); 151 final ProcessRecord r = mService.mProcessNames.get(pname, puid); 152 if (dumpPackage != null && (r == null 153 || !r.pkgList.containsKey(dumpPackage))) { 154 continue; 155 } 156 if (!printed) { 157 if (needSep) pw.println(); 158 needSep = true; 159 pw.println(" Bad processes:"); 160 printed = true; 161 } 162 final BadProcessInfo info = uids.valueAt(i); 163 pw.print(" Bad process "); pw.print(pname); 164 pw.print(" uid "); pw.print(puid); 165 pw.print(": crashed at time "); pw.println(info.time); 166 if (info.shortMsg != null) { 167 pw.print(" Short msg: "); pw.println(info.shortMsg); 168 } 169 if (info.longMsg != null) { 170 pw.print(" Long msg: "); pw.println(info.longMsg); 171 } 172 if (info.stack != null) { 173 pw.println(" Stack:"); 174 int lastPos = 0; 175 for (int pos = 0; pos < info.stack.length(); pos++) { 176 if (info.stack.charAt(pos) == '\n') { 177 pw.print(" "); 178 pw.write(info.stack, lastPos, pos-lastPos); 179 pw.println(); 180 lastPos = pos+1; 181 } 182 } 183 if (lastPos < info.stack.length()) { 184 pw.print(" "); 185 pw.write(info.stack, lastPos, info.stack.length()-lastPos); 186 pw.println(); 187 } 188 } 189 } 190 } 191 } 192 return needSep; 193 } 194 195 boolean isBadProcessLocked(ApplicationInfo info) { 196 return mBadProcesses.get(info.processName, info.uid) != null; 197 } 198 199 void clearBadProcessLocked(ApplicationInfo info) { 200 mBadProcesses.remove(info.processName, info.uid); 201 } 202 203 void resetProcessCrashTimeLocked(ApplicationInfo info) { 204 mProcessCrashTimes.remove(info.processName, info.uid); 205 } 206 207 void resetProcessCrashTimeLocked(boolean resetEntireUser, int appId, int userId) { 208 final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap(); 209 for (int ip = pmap.size() - 1; ip >= 0; ip--) { 210 SparseArray<Long> ba = pmap.valueAt(ip); 211 for (int i = ba.size() - 1; i >= 0; i--) { 212 boolean remove = false; 213 final int entUid = ba.keyAt(i); 214 if (!resetEntireUser) { 215 if (userId == UserHandle.USER_ALL) { 216 if (UserHandle.getAppId(entUid) == appId) { 217 remove = true; 218 } 219 } else { 220 if (entUid == UserHandle.getUid(userId, appId)) { 221 remove = true; 222 } 223 } 224 } else if (UserHandle.getUserId(entUid) == userId) { 225 remove = true; 226 } 227 if (remove) { 228 ba.removeAt(i); 229 } 230 } 231 if (ba.size() == 0) { 232 pmap.removeAt(ip); 233 } 234 } 235 } 236 237 void loadAppsNotReportingCrashesFromConfigLocked(String appsNotReportingCrashesConfig) { 238 if (appsNotReportingCrashesConfig != null) { 239 final String[] split = appsNotReportingCrashesConfig.split(","); 240 if (split.length > 0) { 241 mAppsNotReportingCrashes = new ArraySet<>(); 242 Collections.addAll(mAppsNotReportingCrashes, split); 243 } 244 } 245 } 246 247 void killAppAtUserRequestLocked(ProcessRecord app, Dialog fromDialog) { 248 app.crashing = false; 249 app.crashingReport = null; 250 app.notResponding = false; 251 app.notRespondingReport = null; 252 if (app.anrDialog == fromDialog) { 253 app.anrDialog = null; 254 } 255 if (app.waitDialog == fromDialog) { 256 app.waitDialog = null; 257 } 258 if (app.pid > 0 && app.pid != MY_PID) { 259 handleAppCrashLocked(app, "user-terminated" /*reason*/, 260 null /*shortMsg*/, null /*longMsg*/, null /*stackTrace*/, null /*data*/); 261 app.kill("user request after error", true); 262 } 263 } 264 265 void scheduleAppCrashLocked(int uid, int initialPid, String packageName, 266 String message) { 267 ProcessRecord proc = null; 268 269 // Figure out which process to kill. We don't trust that initialPid 270 // still has any relation to current pids, so must scan through the 271 // list. 272 273 synchronized (mService.mPidsSelfLocked) { 274 for (int i=0; i<mService.mPidsSelfLocked.size(); i++) { 275 ProcessRecord p = mService.mPidsSelfLocked.valueAt(i); 276 if (p.uid != uid) { 277 continue; 278 } 279 if (p.pid == initialPid) { 280 proc = p; 281 break; 282 } 283 if (p.pkgList.containsKey(packageName)) { 284 proc = p; 285 } 286 } 287 } 288 289 if (proc == null) { 290 Slog.w(TAG, "crashApplication: nothing for uid=" + uid 291 + " initialPid=" + initialPid 292 + " packageName=" + packageName); 293 return; 294 } 295 296 proc.scheduleCrash(message); 297 } 298 299 /** 300 * Bring up the "unexpected error" dialog box for a crashing app. 301 * Deal with edge cases (intercepts from instrumented applications, 302 * ActivityController, error intent receivers, that sort of thing). 303 * @param r the application crashing 304 * @param crashInfo describing the failure 305 */ 306 void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) { 307 long timeMillis = System.currentTimeMillis(); 308 String shortMsg = crashInfo.exceptionClassName; 309 String longMsg = crashInfo.exceptionMessage; 310 String stackTrace = crashInfo.stackTrace; 311 if (shortMsg != null && longMsg != null) { 312 longMsg = shortMsg + ": " + longMsg; 313 } else if (shortMsg != null) { 314 longMsg = shortMsg; 315 } 316 317 AppErrorResult result = new AppErrorResult(); 318 TaskRecord task; 319 synchronized (mService) { 320 if (mService.mController != null) { 321 try { 322 String name = r != null ? r.processName : null; 323 int pid = r != null ? r.pid : Binder.getCallingPid(); 324 int uid = r != null ? r.info.uid : Binder.getCallingUid(); 325 if (!mService.mController.appCrashed(name, pid, 326 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) { 327 if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")) 328 && "Native crash".equals(crashInfo.exceptionClassName)) { 329 Slog.w(TAG, "Skip killing native crashed app " + name 330 + "(" + pid + ") during testing"); 331 } else { 332 Slog.w(TAG, "Force-killing crashed app " + name 333 + " at watcher's request"); 334 if (r != null) { 335 r.kill("crash", true); 336 } else { 337 // Huh. 338 Process.killProcess(pid); 339 ActivityManagerService.killProcessGroup(uid, pid); 340 } 341 } 342 return; 343 } 344 } catch (RemoteException e) { 345 mService.mController = null; 346 Watchdog.getInstance().setActivityController(null); 347 } 348 } 349 350 final long origId = Binder.clearCallingIdentity(); 351 352 // If this process is running instrumentation, finish it. 353 if (r != null && r.instrumentationClass != null) { 354 Slog.w(TAG, "Error in app " + r.processName 355 + " running instrumentation " + r.instrumentationClass + ":"); 356 if (shortMsg != null) Slog.w(TAG, " " + shortMsg); 357 if (longMsg != null) Slog.w(TAG, " " + longMsg); 358 Bundle info = new Bundle(); 359 info.putString("shortMsg", shortMsg); 360 info.putString("longMsg", longMsg); 361 mService.finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info); 362 Binder.restoreCallingIdentity(origId); 363 return; 364 } 365 366 // Log crash in battery stats. 367 if (r != null) { 368 mService.mBatteryStatsService.noteProcessCrash(r.processName, r.uid); 369 } 370 371 AppErrorDialog.Data data = new AppErrorDialog.Data(); 372 data.result = result; 373 data.proc = r; 374 375 // If we can't identify the process or it's already exceeded its crash quota, 376 // quit right away without showing a crash dialog. 377 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, data)) { 378 Binder.restoreCallingIdentity(origId); 379 return; 380 } 381 382 Message msg = Message.obtain(); 383 msg.what = ActivityManagerService.SHOW_ERROR_UI_MSG; 384 385 task = data.task; 386 msg.obj = data; 387 mService.mUiHandler.sendMessage(msg); 388 389 Binder.restoreCallingIdentity(origId); 390 } 391 392 int res = result.get(); 393 394 Intent appErrorIntent = null; 395 final long ident = Binder.clearCallingIdentity(); 396 try { 397 MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res); 398 if (res == AppErrorDialog.TIMEOUT) { 399 res = AppErrorDialog.FORCE_QUIT; 400 } 401 if (res == AppErrorDialog.RESET) { 402 String[] packageList = r.getPackageList(); 403 if (packageList != null) { 404 PackageManager pm = mContext.getPackageManager(); 405 final Semaphore s = new Semaphore(0); 406 for (int i = 0; i < packageList.length; i++) { 407 if (i < packageList.length - 1) { 408 pm.deleteApplicationCacheFiles(packageList[i], null); 409 } else { 410 pm.deleteApplicationCacheFiles(packageList[i], 411 new IPackageDataObserver.Stub() { 412 @Override 413 public void onRemoveCompleted(String packageName, 414 boolean succeeded) { 415 s.release(); 416 } 417 }); 418 419 // Wait until cache has been cleared before we restart. 420 try { 421 s.acquire(); 422 } catch (InterruptedException e) { 423 } 424 } 425 } 426 } 427 // If there was nothing to reset, just restart; 428 res = AppErrorDialog.RESTART; 429 } 430 synchronized (mService) { 431 if (res == AppErrorDialog.MUTE) { 432 stopReportingCrashesLocked(r); 433 } 434 if (res == AppErrorDialog.RESTART) { 435 mService.removeProcessLocked(r, false, true, "crash"); 436 if (task != null) { 437 try { 438 mService.startActivityFromRecents(task.taskId, 439 ActivityOptions.makeBasic().toBundle()); 440 } catch (IllegalArgumentException e) { 441 // Hmm, that didn't work, app might have crashed before creating a 442 // recents entry. Let's see if we have a safe-to-restart intent. 443 if (task.intent.getCategories().contains( 444 Intent.CATEGORY_LAUNCHER)) { 445 mService.startActivityInPackage(task.mCallingUid, 446 task.mCallingPackage, task.intent, 447 null, null, null, 0, 0, 448 ActivityOptions.makeBasic().toBundle(), 449 task.userId, null, null); 450 } 451 } 452 } 453 } 454 if (res == AppErrorDialog.FORCE_QUIT) { 455 long orig = Binder.clearCallingIdentity(); 456 try { 457 // Kill it with fire! 458 mService.mStackSupervisor.handleAppCrashLocked(r); 459 if (!r.persistent) { 460 mService.removeProcessLocked(r, false, false, "crash"); 461 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked(); 462 } 463 } finally { 464 Binder.restoreCallingIdentity(orig); 465 } 466 } 467 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) { 468 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo); 469 } 470 if (r != null && !r.isolated && res != AppErrorDialog.RESTART) { 471 // XXX Can't keep track of crash time for isolated processes, 472 // since they don't have a persistent identity. 473 mProcessCrashTimes.put(r.info.processName, r.uid, 474 SystemClock.uptimeMillis()); 475 } 476 } 477 } finally { 478 Binder.restoreCallingIdentity(ident); 479 } 480 481 if (appErrorIntent != null) { 482 try { 483 mContext.startActivityAsUser(appErrorIntent, new UserHandle(r.userId)); 484 } catch (ActivityNotFoundException e) { 485 Slog.w(TAG, "bug report receiver dissappeared", e); 486 } 487 } 488 } 489 490 private boolean makeAppCrashingLocked(ProcessRecord app, 491 String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) { 492 app.crashing = true; 493 app.crashingReport = generateProcessError(app, 494 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace); 495 startAppProblemLocked(app); 496 app.stopFreezingAllLocked(); 497 return handleAppCrashLocked(app, "force-crash" /*reason*/, shortMsg, longMsg, stackTrace, 498 data); 499 } 500 501 void startAppProblemLocked(ProcessRecord app) { 502 // If this app is not running under the current user, then we 503 // can't give it a report button because that would require 504 // launching the report UI under a different user. 505 app.errorReportReceiver = null; 506 507 for (int userId : mService.mUserController.getCurrentProfileIdsLocked()) { 508 if (app.userId == userId) { 509 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver( 510 mContext, app.info.packageName, app.info.flags); 511 } 512 } 513 mService.skipCurrentReceiverLocked(app); 514 } 515 516 /** 517 * Generate a process error record, suitable for attachment to a ProcessRecord. 518 * 519 * @param app The ProcessRecord in which the error occurred. 520 * @param condition Crashing, Application Not Responding, etc. Values are defined in 521 * ActivityManager.AppErrorStateInfo 522 * @param activity The activity associated with the crash, if known. 523 * @param shortMsg Short message describing the crash. 524 * @param longMsg Long message describing the crash. 525 * @param stackTrace Full crash stack trace, may be null. 526 * 527 * @return Returns a fully-formed AppErrorStateInfo record. 528 */ 529 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app, 530 int condition, String activity, String shortMsg, String longMsg, String stackTrace) { 531 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo(); 532 533 report.condition = condition; 534 report.processName = app.processName; 535 report.pid = app.pid; 536 report.uid = app.info.uid; 537 report.tag = activity; 538 report.shortMsg = shortMsg; 539 report.longMsg = longMsg; 540 report.stackTrace = stackTrace; 541 542 return report; 543 } 544 545 Intent createAppErrorIntentLocked(ProcessRecord r, 546 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) { 547 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo); 548 if (report == null) { 549 return null; 550 } 551 Intent result = new Intent(Intent.ACTION_APP_ERROR); 552 result.setComponent(r.errorReportReceiver); 553 result.putExtra(Intent.EXTRA_BUG_REPORT, report); 554 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 555 return result; 556 } 557 558 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r, 559 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) { 560 if (r.errorReportReceiver == null) { 561 return null; 562 } 563 564 if (!r.crashing && !r.notResponding && !r.forceCrashReport) { 565 return null; 566 } 567 568 ApplicationErrorReport report = new ApplicationErrorReport(); 569 report.packageName = r.info.packageName; 570 report.installerPackageName = r.errorReportReceiver.getPackageName(); 571 report.processName = r.processName; 572 report.time = timeMillis; 573 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0; 574 575 if (r.crashing || r.forceCrashReport) { 576 report.type = ApplicationErrorReport.TYPE_CRASH; 577 report.crashInfo = crashInfo; 578 } else if (r.notResponding) { 579 report.type = ApplicationErrorReport.TYPE_ANR; 580 report.anrInfo = new ApplicationErrorReport.AnrInfo(); 581 582 report.anrInfo.activity = r.notRespondingReport.tag; 583 report.anrInfo.cause = r.notRespondingReport.shortMsg; 584 report.anrInfo.info = r.notRespondingReport.longMsg; 585 } 586 587 return report; 588 } 589 590 boolean handleAppCrashLocked(ProcessRecord app, String reason, 591 String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) { 592 long now = SystemClock.uptimeMillis(); 593 594 Long crashTime; 595 Long crashTimePersistent; 596 if (!app.isolated) { 597 crashTime = mProcessCrashTimes.get(app.info.processName, app.uid); 598 crashTimePersistent = mProcessCrashTimesPersistent.get(app.info.processName, app.uid); 599 } else { 600 crashTime = crashTimePersistent = null; 601 } 602 if (crashTime != null && now < crashTime+ProcessList.MIN_CRASH_INTERVAL) { 603 // This process loses! 604 Slog.w(TAG, "Process " + app.info.processName 605 + " has crashed too many times: killing!"); 606 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH, 607 app.userId, app.info.processName, app.uid); 608 mService.mStackSupervisor.handleAppCrashLocked(app); 609 if (!app.persistent) { 610 // We don't want to start this process again until the user 611 // explicitly does so... but for persistent process, we really 612 // need to keep it running. If a persistent process is actually 613 // repeatedly crashing, then badness for everyone. 614 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.userId, app.uid, 615 app.info.processName); 616 if (!app.isolated) { 617 // XXX We don't have a way to mark isolated processes 618 // as bad, since they don't have a peristent identity. 619 mBadProcesses.put(app.info.processName, app.uid, 620 new BadProcessInfo(now, shortMsg, longMsg, stackTrace)); 621 mProcessCrashTimes.remove(app.info.processName, app.uid); 622 } 623 app.bad = true; 624 app.removed = true; 625 // Don't let services in this process be restarted and potentially 626 // annoy the user repeatedly. Unless it is persistent, since those 627 // processes run critical code. 628 mService.removeProcessLocked(app, false, false, "crash"); 629 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked(); 630 return false; 631 } 632 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked(); 633 } else { 634 TaskRecord affectedTask = 635 mService.mStackSupervisor.finishTopRunningActivityLocked(app, reason); 636 if (data != null) { 637 data.task = affectedTask; 638 } 639 if (data != null && crashTimePersistent != null 640 && now < crashTimePersistent + ProcessList.MIN_CRASH_INTERVAL) { 641 data.repeating = true; 642 } 643 } 644 645 // Bump up the crash count of any services currently running in the proc. 646 for (int i=app.services.size()-1; i>=0; i--) { 647 // Any services running in the application need to be placed 648 // back in the pending list. 649 ServiceRecord sr = app.services.valueAt(i); 650 sr.crashCount++; 651 } 652 653 // If the crashing process is what we consider to be the "home process" and it has been 654 // replaced by a third-party app, clear the package preferred activities from packages 655 // with a home activity running in the process to prevent a repeatedly crashing app 656 // from blocking the user to manually clear the list. 657 final ArrayList<ActivityRecord> activities = app.activities; 658 if (app == mService.mHomeProcess && activities.size() > 0 659 && (mService.mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { 660 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 661 final ActivityRecord r = activities.get(activityNdx); 662 if (r.isHomeActivity()) { 663 Log.i(TAG, "Clearing package preferred activities from " + r.packageName); 664 try { 665 ActivityThread.getPackageManager() 666 .clearPackagePreferredActivities(r.packageName); 667 } catch (RemoteException c) { 668 // pm is in same process, this will never happen. 669 } 670 } 671 } 672 } 673 674 if (!app.isolated) { 675 // XXX Can't keep track of crash times for isolated processes, 676 // because they don't have a perisistent identity. 677 mProcessCrashTimes.put(app.info.processName, app.uid, now); 678 mProcessCrashTimesPersistent.put(app.info.processName, app.uid, now); 679 } 680 681 if (app.crashHandler != null) mService.mHandler.post(app.crashHandler); 682 return true; 683 } 684 685 void handleShowAppErrorUi(Message msg) { 686 AppErrorDialog.Data data = (AppErrorDialog.Data) msg.obj; 687 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(), 688 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0; 689 synchronized (mService) { 690 ProcessRecord proc = data.proc; 691 AppErrorResult res = data.result; 692 if (proc != null && proc.crashDialog != null) { 693 Slog.e(TAG, "App already has crash dialog: " + proc); 694 if (res != null) { 695 res.set(AppErrorDialog.ALREADY_SHOWING); 696 } 697 return; 698 } 699 boolean isBackground = (UserHandle.getAppId(proc.uid) 700 >= Process.FIRST_APPLICATION_UID 701 && proc.pid != MY_PID); 702 for (int userId : mService.mUserController.getCurrentProfileIdsLocked()) { 703 isBackground &= (proc.userId != userId); 704 } 705 if (isBackground && !showBackground) { 706 Slog.w(TAG, "Skipping crash dialog of " + proc + ": background"); 707 if (res != null) { 708 res.set(AppErrorDialog.BACKGROUND_USER); 709 } 710 return; 711 } 712 final boolean crashSilenced = mAppsNotReportingCrashes != null && 713 mAppsNotReportingCrashes.contains(proc.info.packageName); 714 if (mService.canShowErrorDialogs() && !crashSilenced) { 715 proc.crashDialog = new AppErrorDialog(mContext, mService, data); 716 } else { 717 // The device is asleep, so just pretend that the user 718 // saw a crash dialog and hit "force quit". 719 if (res != null) { 720 res.set(AppErrorDialog.CANT_SHOW); 721 } 722 } 723 } 724 // If we've created a crash dialog, show it without the lock held 725 if(data.proc.crashDialog != null) { 726 data.proc.crashDialog.show(); 727 } 728 } 729 730 void stopReportingCrashesLocked(ProcessRecord proc) { 731 if (mAppsNotReportingCrashes == null) { 732 mAppsNotReportingCrashes = new ArraySet<>(); 733 } 734 mAppsNotReportingCrashes.add(proc.info.packageName); 735 } 736 737 final void appNotResponding(ProcessRecord app, ActivityRecord activity, 738 ActivityRecord parent, boolean aboveSystem, final String annotation) { 739 ArrayList<Integer> firstPids = new ArrayList<Integer>(5); 740 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20); 741 742 if (mService.mController != null) { 743 try { 744 // 0 == continue, -1 = kill process immediately 745 int res = mService.mController.appEarlyNotResponding( 746 app.processName, app.pid, annotation); 747 if (res < 0 && app.pid != MY_PID) { 748 app.kill("anr", true); 749 } 750 } catch (RemoteException e) { 751 mService.mController = null; 752 Watchdog.getInstance().setActivityController(null); 753 } 754 } 755 756 long anrTime = SystemClock.uptimeMillis(); 757 if (ActivityManagerService.MONITOR_CPU_USAGE) { 758 mService.updateCpuStatsNow(); 759 } 760 761 synchronized (mService) { 762 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down. 763 if (mService.mShuttingDown) { 764 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation); 765 return; 766 } else if (app.notResponding) { 767 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation); 768 return; 769 } else if (app.crashing) { 770 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation); 771 return; 772 } 773 774 // In case we come through here for the same app before completing 775 // this one, mark as anring now so we will bail out. 776 app.notResponding = true; 777 778 // Log the ANR to the event log. 779 EventLog.writeEvent(EventLogTags.AM_ANR, app.userId, app.pid, 780 app.processName, app.info.flags, annotation); 781 782 // Dump thread traces as quickly as we can, starting with "interesting" processes. 783 firstPids.add(app.pid); 784 785 int parentPid = app.pid; 786 if (parent != null && parent.app != null && parent.app.pid > 0) { 787 parentPid = parent.app.pid; 788 } 789 if (parentPid != app.pid) firstPids.add(parentPid); 790 791 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID); 792 793 for (int i = mService.mLruProcesses.size() - 1; i >= 0; i--) { 794 ProcessRecord r = mService.mLruProcesses.get(i); 795 if (r != null && r.thread != null) { 796 int pid = r.pid; 797 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) { 798 if (r.persistent) { 799 firstPids.add(pid); 800 if (DEBUG_ANR) Slog.i(TAG, "Adding persistent proc: " + r); 801 } else { 802 lastPids.put(pid, Boolean.TRUE); 803 if (DEBUG_ANR) Slog.i(TAG, "Adding ANR proc: " + r); 804 } 805 } 806 } 807 } 808 } 809 810 // Log the ANR to the main log. 811 StringBuilder info = new StringBuilder(); 812 info.setLength(0); 813 info.append("ANR in ").append(app.processName); 814 if (activity != null && activity.shortComponentName != null) { 815 info.append(" (").append(activity.shortComponentName).append(")"); 816 } 817 info.append("\n"); 818 info.append("PID: ").append(app.pid).append("\n"); 819 if (annotation != null) { 820 info.append("Reason: ").append(annotation).append("\n"); 821 } 822 if (parent != null && parent != activity) { 823 info.append("Parent: ").append(parent.shortComponentName).append("\n"); 824 } 825 826 final ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true); 827 828 File tracesFile = mService.dumpStackTraces(true, firstPids, processCpuTracker, lastPids, 829 NATIVE_STACKS_OF_INTEREST); 830 831 String cpuInfo = null; 832 if (ActivityManagerService.MONITOR_CPU_USAGE) { 833 mService.updateCpuStatsNow(); 834 synchronized (mService.mProcessCpuTracker) { 835 cpuInfo = mService.mProcessCpuTracker.printCurrentState(anrTime); 836 } 837 info.append(processCpuTracker.printCurrentLoad()); 838 info.append(cpuInfo); 839 } 840 841 info.append(processCpuTracker.printCurrentState(anrTime)); 842 843 Slog.e(TAG, info.toString()); 844 if (tracesFile == null) { 845 // There is no trace file, so dump (only) the alleged culprit's threads to the log 846 Process.sendSignal(app.pid, Process.SIGNAL_QUIT); 847 } 848 849 mService.addErrorToDropBox("anr", app, app.processName, activity, parent, annotation, 850 cpuInfo, tracesFile, null); 851 852 if (mService.mController != null) { 853 try { 854 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately 855 int res = mService.mController.appNotResponding( 856 app.processName, app.pid, info.toString()); 857 if (res != 0) { 858 if (res < 0 && app.pid != MY_PID) { 859 app.kill("anr", true); 860 } else { 861 synchronized (mService) { 862 mService.mServices.scheduleServiceTimeoutLocked(app); 863 } 864 } 865 return; 866 } 867 } catch (RemoteException e) { 868 mService.mController = null; 869 Watchdog.getInstance().setActivityController(null); 870 } 871 } 872 873 // Unless configured otherwise, swallow ANRs in background processes & kill the process. 874 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(), 875 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0; 876 877 synchronized (mService) { 878 mService.mBatteryStatsService.noteProcessAnr(app.processName, app.uid); 879 880 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) { 881 app.kill("bg anr", true); 882 return; 883 } 884 885 // Set the app's notResponding state, and look up the errorReportReceiver 886 makeAppNotRespondingLocked(app, 887 activity != null ? activity.shortComponentName : null, 888 annotation != null ? "ANR " + annotation : "ANR", 889 info.toString()); 890 891 // Bring up the infamous App Not Responding dialog 892 Message msg = Message.obtain(); 893 HashMap<String, Object> map = new HashMap<String, Object>(); 894 msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG; 895 msg.obj = map; 896 msg.arg1 = aboveSystem ? 1 : 0; 897 map.put("app", app); 898 if (activity != null) { 899 map.put("activity", activity); 900 } 901 902 mService.mUiHandler.sendMessage(msg); 903 } 904 } 905 906 private void makeAppNotRespondingLocked(ProcessRecord app, 907 String activity, String shortMsg, String longMsg) { 908 app.notResponding = true; 909 app.notRespondingReport = generateProcessError(app, 910 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING, 911 activity, shortMsg, longMsg, null); 912 startAppProblemLocked(app); 913 app.stopFreezingAllLocked(); 914 } 915 916 void handleShowAnrUi(Message msg) { 917 Dialog d = null; 918 synchronized (mService) { 919 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj; 920 ProcessRecord proc = (ProcessRecord)data.get("app"); 921 if (proc != null && proc.anrDialog != null) { 922 Slog.e(TAG, "App already has anr dialog: " + proc); 923 MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR, 924 AppNotRespondingDialog.ALREADY_SHOWING); 925 return; 926 } 927 928 Intent intent = new Intent("android.intent.action.ANR"); 929 if (!mService.mProcessesReady) { 930 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY 931 | Intent.FLAG_RECEIVER_FOREGROUND); 932 } 933 mService.broadcastIntentLocked(null, null, intent, 934 null, null, 0, null, null, null, AppOpsManager.OP_NONE, 935 null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */); 936 937 if (mService.canShowErrorDialogs()) { 938 d = new AppNotRespondingDialog(mService, 939 mContext, proc, (ActivityRecord)data.get("activity"), 940 msg.arg1 != 0); 941 proc.anrDialog = d; 942 } else { 943 MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR, 944 AppNotRespondingDialog.CANT_SHOW); 945 // Just kill the app if there is no dialog to be shown. 946 mService.killAppAtUsersRequest(proc, null); 947 } 948 } 949 // If we've created a crash dialog, show it without the lock held 950 if (d != null) { 951 d.show(); 952 } 953 } 954 955 /** 956 * Information about a process that is currently marked as bad. 957 */ 958 static final class BadProcessInfo { 959 BadProcessInfo(long time, String shortMsg, String longMsg, String stack) { 960 this.time = time; 961 this.shortMsg = shortMsg; 962 this.longMsg = longMsg; 963 this.stack = stack; 964 } 965 966 final long time; 967 final String shortMsg; 968 final String longMsg; 969 final String stack; 970 } 971 972} 973