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