1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.server.am; 18 19 import static android.app.ActivityTaskManager.INVALID_TASK_ID; 20 import static android.content.pm.ApplicationInfo.FLAG_SYSTEM; 21 22 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; 23 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; 24 import static com.android.server.am.ActivityManagerService.MY_PID; 25 import static com.android.server.am.ActivityManagerService.SYSTEM_DEBUGGABLE; 26 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE; 27 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE; 28 29 import android.app.ActivityManager; 30 import android.app.ActivityOptions; 31 import android.app.ApplicationErrorReport; 32 import android.app.Dialog; 33 import android.content.ActivityNotFoundException; 34 import android.content.Context; 35 import android.content.Intent; 36 import android.content.pm.ApplicationInfo; 37 import android.content.pm.ModuleInfo; 38 import android.content.pm.PackageManager; 39 import android.content.pm.VersionedPackage; 40 import android.net.Uri; 41 import android.os.Binder; 42 import android.os.Message; 43 import android.os.Process; 44 import android.os.SystemClock; 45 import android.os.SystemProperties; 46 import android.os.UserHandle; 47 import android.provider.Settings; 48 import android.util.ArrayMap; 49 import android.util.ArraySet; 50 import android.util.EventLog; 51 import android.util.Slog; 52 import android.util.SparseArray; 53 import android.util.TimeUtils; 54 import android.util.proto.ProtoOutputStream; 55 56 import com.android.internal.app.ProcessMap; 57 import com.android.internal.logging.MetricsLogger; 58 import com.android.internal.logging.nano.MetricsProto; 59 import com.android.server.PackageWatchdog; 60 import com.android.server.RescueParty; 61 import com.android.server.wm.WindowProcessController; 62 63 import java.io.FileDescriptor; 64 import java.io.PrintWriter; 65 import java.util.Collections; 66 import java.util.List; 67 68 /** 69 * Controls error conditions in applications. 70 */ 71 class AppErrors { 72 73 private static final String TAG = TAG_WITH_CLASS_NAME ? "AppErrors" : TAG_AM; 74 75 private final ActivityManagerService mService; 76 private final Context mContext; 77 private final PackageWatchdog mPackageWatchdog; 78 79 private ArraySet<String> mAppsNotReportingCrashes; 80 81 /** 82 * The last time that various processes have crashed since they were last explicitly started. 83 */ 84 private final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<>(); 85 86 /** 87 * The last time that various processes have crashed (not reset even when explicitly started). 88 */ 89 private final ProcessMap<Long> mProcessCrashTimesPersistent = new ProcessMap<>(); 90 91 /** 92 * Set of applications that we consider to be bad, and will reject 93 * incoming broadcasts from (which the user has no control over). 94 * Processes are added to this set when they have crashed twice within 95 * a minimum amount of time; they are removed from it when they are 96 * later restarted (hopefully due to some user action). The value is the 97 * time it was added to the list. 98 */ 99 private final ProcessMap<BadProcessInfo> mBadProcesses = new ProcessMap<>(); 100 101 AppErrors(Context context, ActivityManagerService service, PackageWatchdog watchdog)102 AppErrors(Context context, ActivityManagerService service, PackageWatchdog watchdog) { 103 context.assertRuntimeOverlayThemable(); 104 mService = service; 105 mContext = context; 106 mPackageWatchdog = watchdog; 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.getProcessNames().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.getProcessNames().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.getProcessNames().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.getProcessNames().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.setCrashing(false); 328 app.crashingReport = null; 329 app.setNotResponding(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 (r != null) { 427 boolean isApexModule = false; 428 try { 429 for (String androidPackage : r.getPackageList()) { 430 ModuleInfo moduleInfo = mContext.getPackageManager().getModuleInfo( 431 androidPackage, /*flags=*/ 0); 432 if (moduleInfo != null) { 433 isApexModule = true; 434 break; 435 } 436 } 437 } catch (IllegalStateException | PackageManager.NameNotFoundException e) { 438 // Call to PackageManager#getModuleInfo() can result in NameNotFoundException or 439 // IllegalStateException. In case they are thrown, there isn't much we can do 440 // other than proceed with app crash handling. 441 } 442 443 if (r.isPersistent() || isApexModule) { 444 // If a persistent app or apex module is stuck in a crash loop, the device isn't 445 // very usable, so we want to consider sending out a rescue party. 446 RescueParty.noteAppCrash(mContext, r.uid); 447 } 448 449 mPackageWatchdog.onPackageFailure(r.getPackageListWithVersionCode()); 450 } 451 452 final int relaunchReason = r != null 453 ? r.getWindowProcessController().computeRelaunchReason() : RELAUNCH_REASON_NONE; 454 455 AppErrorResult result = new AppErrorResult(); 456 int taskId; 457 synchronized (mService) { 458 /** 459 * If crash is handled by instance of {@link android.app.IActivityController}, 460 * finish now and don't show the app error dialog. 461 */ 462 if (handleAppCrashInActivityController(r, crashInfo, shortMsg, longMsg, stackTrace, 463 timeMillis, callingPid, callingUid)) { 464 return; 465 } 466 467 // Suppress crash dialog if the process is being relaunched due to a crash during a free 468 // resize. 469 if (relaunchReason == RELAUNCH_REASON_FREE_RESIZE) { 470 return; 471 } 472 473 /** 474 * If this process was running instrumentation, finish now - it will be handled in 475 * {@link ActivityManagerService#handleAppDiedLocked}. 476 */ 477 if (r != null && r.getActiveInstrumentation() != null) { 478 return; 479 } 480 481 // Log crash in battery stats. 482 if (r != null) { 483 mService.mBatteryStatsService.noteProcessCrash(r.processName, r.uid); 484 } 485 486 AppErrorDialog.Data data = new AppErrorDialog.Data(); 487 data.result = result; 488 data.proc = r; 489 490 // If we can't identify the process or it's already exceeded its crash quota, 491 // quit right away without showing a crash dialog. 492 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, data)) { 493 return; 494 } 495 496 final Message msg = Message.obtain(); 497 msg.what = ActivityManagerService.SHOW_ERROR_UI_MSG; 498 499 taskId = data.taskId; 500 msg.obj = data; 501 mService.mUiHandler.sendMessage(msg); 502 } 503 504 int res = result.get(); 505 506 Intent appErrorIntent = null; 507 MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res); 508 if (res == AppErrorDialog.TIMEOUT || res == AppErrorDialog.CANCEL) { 509 res = AppErrorDialog.FORCE_QUIT; 510 } 511 synchronized (mService) { 512 if (res == AppErrorDialog.MUTE) { 513 stopReportingCrashesLocked(r); 514 } 515 if (res == AppErrorDialog.RESTART) { 516 mService.mProcessList.removeProcessLocked(r, false, true, "crash"); 517 if (taskId != INVALID_TASK_ID) { 518 try { 519 mService.startActivityFromRecents(taskId, 520 ActivityOptions.makeBasic().toBundle()); 521 } catch (IllegalArgumentException e) { 522 // Hmm...that didn't work. Task should either be in recents or associated 523 // with a stack. 524 Slog.e(TAG, "Could not restart taskId=" + taskId, e); 525 } 526 } 527 } 528 if (res == AppErrorDialog.FORCE_QUIT) { 529 long orig = Binder.clearCallingIdentity(); 530 try { 531 // Kill it with fire! 532 mService.mAtmInternal.onHandleAppCrash(r.getWindowProcessController()); 533 if (!r.isPersistent()) { 534 mService.mProcessList.removeProcessLocked(r, false, false, "crash"); 535 mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */); 536 } 537 } finally { 538 Binder.restoreCallingIdentity(orig); 539 } 540 } 541 if (res == AppErrorDialog.APP_INFO) { 542 appErrorIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); 543 appErrorIntent.setData(Uri.parse("package:" + r.info.packageName)); 544 appErrorIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 545 } 546 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) { 547 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo); 548 } 549 if (r != null && !r.isolated && res != AppErrorDialog.RESTART) { 550 // XXX Can't keep track of crash time for isolated processes, 551 // since they don't have a persistent identity. 552 mProcessCrashTimes.put(r.info.processName, r.uid, 553 SystemClock.uptimeMillis()); 554 } 555 } 556 557 if (appErrorIntent != null) { 558 try { 559 mContext.startActivityAsUser(appErrorIntent, new UserHandle(r.userId)); 560 } catch (ActivityNotFoundException e) { 561 Slog.w(TAG, "bug report receiver dissappeared", e); 562 } 563 } 564 } 565 handleAppCrashInActivityController(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo, String shortMsg, String longMsg, String stackTrace, long timeMillis, int callingPid, int callingUid)566 private boolean handleAppCrashInActivityController(ProcessRecord r, 567 ApplicationErrorReport.CrashInfo crashInfo, 568 String shortMsg, String longMsg, 569 String stackTrace, long timeMillis, 570 int callingPid, int callingUid) { 571 String name = r != null ? r.processName : null; 572 int pid = r != null ? r.pid : callingPid; 573 int uid = r != null ? r.info.uid : callingUid; 574 575 return mService.mAtmInternal.handleAppCrashInActivityController( 576 name, pid, shortMsg, longMsg, timeMillis, crashInfo.stackTrace, () -> { 577 if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")) 578 && "Native crash".equals(crashInfo.exceptionClassName)) { 579 Slog.w(TAG, "Skip killing native crashed app " + name 580 + "(" + pid + ") during testing"); 581 } else { 582 Slog.w(TAG, "Force-killing crashed app " + name + " at watcher's request"); 583 if (r != null) { 584 if (!makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, null)) { 585 r.kill("crash", true); 586 } 587 } else { 588 // Huh. 589 Process.killProcess(pid); 590 ProcessList.killProcessGroup(uid, pid); 591 } 592 } 593 }); 594 } 595 596 private boolean makeAppCrashingLocked(ProcessRecord app, 597 String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) { 598 app.setCrashing(true); 599 app.crashingReport = generateProcessError(app, 600 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace); 601 app.startAppProblemLocked(); 602 app.getWindowProcessController().stopFreezingActivities(); 603 return handleAppCrashLocked(app, "force-crash" /*reason*/, shortMsg, longMsg, stackTrace, 604 data); 605 } 606 607 /** 608 * Generate a process error record, suitable for attachment to a ProcessRecord. 609 * 610 * @param app The ProcessRecord in which the error occurred. 611 * @param condition Crashing, Application Not Responding, etc. Values are defined in 612 * ActivityManager.ProcessErrorStateInfo 613 * @param activity The activity associated with the crash, if known. 614 * @param shortMsg Short message describing the crash. 615 * @param longMsg Long message describing the crash. 616 * @param stackTrace Full crash stack trace, may be null. 617 * 618 * @return Returns a fully-formed ProcessErrorStateInfo record. 619 */ 620 ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app, 621 int condition, String activity, String shortMsg, String longMsg, String stackTrace) { 622 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo(); 623 624 report.condition = condition; 625 report.processName = app.processName; 626 report.pid = app.pid; 627 report.uid = app.info.uid; 628 report.tag = activity; 629 report.shortMsg = shortMsg; 630 report.longMsg = longMsg; 631 report.stackTrace = stackTrace; 632 633 return report; 634 } 635 636 Intent createAppErrorIntentLocked(ProcessRecord r, 637 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) { 638 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo); 639 if (report == null) { 640 return null; 641 } 642 Intent result = new Intent(Intent.ACTION_APP_ERROR); 643 result.setComponent(r.errorReportReceiver); 644 result.putExtra(Intent.EXTRA_BUG_REPORT, report); 645 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 646 return result; 647 } 648 649 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r, 650 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) { 651 if (r.errorReportReceiver == null) { 652 return null; 653 } 654 655 if (!r.isCrashing() && !r.isNotResponding() && !r.forceCrashReport) { 656 return null; 657 } 658 659 ApplicationErrorReport report = new ApplicationErrorReport(); 660 report.packageName = r.info.packageName; 661 report.installerPackageName = r.errorReportReceiver.getPackageName(); 662 report.processName = r.processName; 663 report.time = timeMillis; 664 report.systemApp = (r.info.flags & FLAG_SYSTEM) != 0; 665 666 if (r.isCrashing() || r.forceCrashReport) { 667 report.type = ApplicationErrorReport.TYPE_CRASH; 668 report.crashInfo = crashInfo; 669 } else if (r.isNotResponding()) { 670 report.type = ApplicationErrorReport.TYPE_ANR; 671 report.anrInfo = new ApplicationErrorReport.AnrInfo(); 672 673 report.anrInfo.activity = r.notRespondingReport.tag; 674 report.anrInfo.cause = r.notRespondingReport.shortMsg; 675 report.anrInfo.info = r.notRespondingReport.longMsg; 676 } 677 678 return report; 679 } 680 681 boolean handleAppCrashLocked(ProcessRecord app, String reason, 682 String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) { 683 final long now = SystemClock.uptimeMillis(); 684 final boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(), 685 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0; 686 687 final boolean procIsBoundForeground = 688 (app.getCurProcState() == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE); 689 690 Long crashTime; 691 Long crashTimePersistent; 692 boolean tryAgain = false; 693 694 if (!app.isolated) { 695 crashTime = mProcessCrashTimes.get(app.info.processName, app.uid); 696 crashTimePersistent = mProcessCrashTimesPersistent.get(app.info.processName, app.uid); 697 } else { 698 crashTime = crashTimePersistent = null; 699 } 700 701 // Bump up the crash count of any services currently running in the proc. 702 for (int i = app.services.size() - 1; i >= 0; i--) { 703 // Any services running in the application need to be placed 704 // back in the pending list. 705 ServiceRecord sr = app.services.valueAt(i); 706 // If the service was restarted a while ago, then reset crash count, else increment it. 707 if (now > sr.restartTime + ProcessList.MIN_CRASH_INTERVAL) { 708 sr.crashCount = 1; 709 } else { 710 sr.crashCount++; 711 } 712 // Allow restarting for started or bound foreground services that are crashing. 713 // This includes wallpapers. 714 if (sr.crashCount < mService.mConstants.BOUND_SERVICE_MAX_CRASH_RETRY 715 && (sr.isForeground || procIsBoundForeground)) { 716 tryAgain = true; 717 } 718 } 719 720 if (crashTime != null && now < crashTime + ProcessList.MIN_CRASH_INTERVAL) { 721 // The process crashed again very quickly. If it was a bound foreground service, let's 722 // try to restart again in a while, otherwise the process loses! 723 Slog.w(TAG, "Process " + app.info.processName 724 + " has crashed too many times: killing!"); 725 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH, 726 app.userId, app.info.processName, app.uid); 727 mService.mAtmInternal.onHandleAppCrash(app.getWindowProcessController()); 728 if (!app.isPersistent()) { 729 // We don't want to start this process again until the user 730 // explicitly does so... but for persistent process, we really 731 // need to keep it running. If a persistent process is actually 732 // repeatedly crashing, then badness for everyone. 733 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.userId, app.uid, 734 app.info.processName); 735 if (!app.isolated) { 736 // XXX We don't have a way to mark isolated processes 737 // as bad, since they don't have a peristent identity. 738 mBadProcesses.put(app.info.processName, app.uid, 739 new BadProcessInfo(now, shortMsg, longMsg, stackTrace)); 740 mProcessCrashTimes.remove(app.info.processName, app.uid); 741 } 742 app.bad = true; 743 app.removed = true; 744 // Don't let services in this process be restarted and potentially 745 // annoy the user repeatedly. Unless it is persistent, since those 746 // processes run critical code. 747 mService.mProcessList.removeProcessLocked(app, false, tryAgain, "crash"); 748 mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */); 749 if (!showBackground) { 750 return false; 751 } 752 } 753 mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */); 754 } else { 755 final int affectedTaskId = mService.mAtmInternal.finishTopCrashedActivities( 756 app.getWindowProcessController(), reason); 757 if (data != null) { 758 data.taskId = affectedTaskId; 759 } 760 if (data != null && crashTimePersistent != null 761 && now < crashTimePersistent + ProcessList.MIN_CRASH_INTERVAL) { 762 data.repeating = true; 763 } 764 } 765 766 if (data != null && tryAgain) { 767 data.isRestartableForService = true; 768 } 769 770 // If the crashing process is what we consider to be the "home process" and it has been 771 // replaced by a third-party app, clear the package preferred activities from packages 772 // with a home activity running in the process to prevent a repeatedly crashing app 773 // from blocking the user to manually clear the list. 774 final WindowProcessController proc = app.getWindowProcessController(); 775 final WindowProcessController homeProc = mService.mAtmInternal.getHomeProcess(); 776 if (proc == homeProc && proc.hasActivities() 777 && (((ProcessRecord) homeProc.mOwner).info.flags & FLAG_SYSTEM) == 0) { 778 proc.clearPackagePreferredForHomeActivities(); 779 } 780 781 if (!app.isolated) { 782 // XXX Can't keep track of crash times for isolated processes, 783 // because they don't have a persistent identity. 784 mProcessCrashTimes.put(app.info.processName, app.uid, now); 785 mProcessCrashTimesPersistent.put(app.info.processName, app.uid, now); 786 } 787 788 if (app.crashHandler != null) mService.mHandler.post(app.crashHandler); 789 return true; 790 } 791 792 void handleShowAppErrorUi(Message msg) { 793 AppErrorDialog.Data data = (AppErrorDialog.Data) msg.obj; 794 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(), 795 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0; 796 797 AppErrorDialog dialogToShow = null; 798 final String packageName; 799 final int userId; 800 synchronized (mService) { 801 final ProcessRecord proc = data.proc; 802 final AppErrorResult res = data.result; 803 if (proc == null) { 804 Slog.e(TAG, "handleShowAppErrorUi: proc is null"); 805 return; 806 } 807 packageName = proc.info.packageName; 808 userId = proc.userId; 809 if (proc.crashDialog != null) { 810 Slog.e(TAG, "App already has crash dialog: " + proc); 811 if (res != null) { 812 res.set(AppErrorDialog.ALREADY_SHOWING); 813 } 814 return; 815 } 816 boolean isBackground = (UserHandle.getAppId(proc.uid) 817 >= Process.FIRST_APPLICATION_UID 818 && proc.pid != MY_PID); 819 for (int profileId : mService.mUserController.getCurrentProfileIds()) { 820 isBackground &= (userId != profileId); 821 } 822 if (isBackground && !showBackground) { 823 Slog.w(TAG, "Skipping crash dialog of " + proc + ": background"); 824 if (res != null) { 825 res.set(AppErrorDialog.BACKGROUND_USER); 826 } 827 return; 828 } 829 final boolean showFirstCrash = Settings.Global.getInt( 830 mContext.getContentResolver(), 831 Settings.Global.SHOW_FIRST_CRASH_DIALOG, 0) != 0; 832 final boolean showFirstCrashDevOption = Settings.Secure.getIntForUser( 833 mContext.getContentResolver(), 834 Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION, 835 0, 836 mService.mUserController.getCurrentUserId()) != 0; 837 final boolean crashSilenced = mAppsNotReportingCrashes != null && 838 mAppsNotReportingCrashes.contains(proc.info.packageName); 839 if ((mService.mAtmInternal.canShowErrorDialogs() || showBackground) 840 && !crashSilenced 841 && (showFirstCrash || showFirstCrashDevOption || data.repeating)) { 842 proc.crashDialog = dialogToShow = new AppErrorDialog(mContext, mService, data); 843 } else { 844 // The device is asleep, so just pretend that the user 845 // saw a crash dialog and hit "force quit". 846 if (res != null) { 847 res.set(AppErrorDialog.CANT_SHOW); 848 } 849 } 850 } 851 // If we've created a crash dialog, show it without the lock held 852 if (dialogToShow != null) { 853 Slog.i(TAG, "Showing crash dialog for package " + packageName + " u" + userId); 854 dialogToShow.show(); 855 } 856 } 857 858 private void stopReportingCrashesLocked(ProcessRecord proc) { 859 if (mAppsNotReportingCrashes == null) { 860 mAppsNotReportingCrashes = new ArraySet<>(); 861 } 862 mAppsNotReportingCrashes.add(proc.info.packageName); 863 } 864 865 void handleShowAnrUi(Message msg) { 866 Dialog dialogToShow = null; 867 List<VersionedPackage> packageList = null; 868 synchronized (mService) { 869 AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj; 870 final ProcessRecord proc = data.proc; 871 if (proc == null) { 872 Slog.e(TAG, "handleShowAnrUi: proc is null"); 873 return; 874 } 875 if (!proc.isPersistent()) { 876 packageList = proc.getPackageListWithVersionCode(); 877 } 878 if (proc.anrDialog != null) { 879 Slog.e(TAG, "App already has anr dialog: " + proc); 880 MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR, 881 AppNotRespondingDialog.ALREADY_SHOWING); 882 return; 883 } 884 885 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(), 886 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0; 887 if (mService.mAtmInternal.canShowErrorDialogs() || showBackground) { 888 dialogToShow = new AppNotRespondingDialog(mService, mContext, data); 889 proc.anrDialog = dialogToShow; 890 } else { 891 MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR, 892 AppNotRespondingDialog.CANT_SHOW); 893 // Just kill the app if there is no dialog to be shown. 894 mService.killAppAtUsersRequest(proc, null); 895 } 896 } 897 // If we've created a crash dialog, show it without the lock held 898 if (dialogToShow != null) { 899 dialogToShow.show(); 900 } 901 // Notify PackageWatchdog without the lock held 902 if (packageList != null) { 903 mPackageWatchdog.onPackageFailure(packageList); 904 } 905 } 906 907 /** 908 * Information about a process that is currently marked as bad. 909 */ 910 static final class BadProcessInfo { 911 BadProcessInfo(long time, String shortMsg, String longMsg, String stack) { 912 this.time = time; 913 this.shortMsg = shortMsg; 914 this.longMsg = longMsg; 915 this.stack = stack; 916 } 917 918 final long time; 919 final String shortMsg; 920 final String longMsg; 921 final String stack; 922 } 923 924 } 925