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 () -> killAppImmediateLocked(p, "forced", "killed for invalid state"), 387 5000L); 388 } 389 } 390 391 /** 392 * Bring up the "unexpected error" dialog box for a crashing app. 393 * Deal with edge cases (intercepts from instrumented applications, 394 * ActivityController, error intent receivers, that sort of thing). 395 * @param r the application crashing 396 * @param crashInfo describing the failure 397 */ crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo)398 void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) { 399 final int callingPid = Binder.getCallingPid(); 400 final int callingUid = Binder.getCallingUid(); 401 402 final long origId = Binder.clearCallingIdentity(); 403 try { 404 crashApplicationInner(r, crashInfo, callingPid, callingUid); 405 } finally { 406 Binder.restoreCallingIdentity(origId); 407 } 408 } 409 crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo, int callingPid, int callingUid)410 void crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo, 411 int callingPid, int callingUid) { 412 long timeMillis = System.currentTimeMillis(); 413 String shortMsg = crashInfo.exceptionClassName; 414 String longMsg = crashInfo.exceptionMessage; 415 String stackTrace = crashInfo.stackTrace; 416 if (shortMsg != null && longMsg != null) { 417 longMsg = shortMsg + ": " + longMsg; 418 } else if (shortMsg != null) { 419 longMsg = shortMsg; 420 } 421 422 if (r != null) { 423 boolean isApexModule = false; 424 try { 425 for (String androidPackage : r.getPackageList()) { 426 ModuleInfo moduleInfo = mContext.getPackageManager().getModuleInfo( 427 androidPackage, /*flags=*/ 0); 428 if (moduleInfo != null) { 429 isApexModule = true; 430 break; 431 } 432 } 433 } catch (IllegalStateException | PackageManager.NameNotFoundException e) { 434 // Call to PackageManager#getModuleInfo() can result in NameNotFoundException or 435 // IllegalStateException. In case they are thrown, there isn't much we can do 436 // other than proceed with app crash handling. 437 } 438 439 if (r.isPersistent() || isApexModule) { 440 // If a persistent app or apex module is stuck in a crash loop, the device isn't 441 // very usable, so we want to consider sending out a rescue party. 442 RescueParty.noteAppCrash(mContext, r.uid); 443 } 444 445 mPackageWatchdog.onPackageFailure(r.getPackageListWithVersionCode(), 446 PackageWatchdog.FAILURE_REASON_APP_CRASH); 447 } 448 449 final int relaunchReason = r != null 450 ? r.getWindowProcessController().computeRelaunchReason() : RELAUNCH_REASON_NONE; 451 452 AppErrorResult result = new AppErrorResult(); 453 int taskId; 454 synchronized (mService) { 455 /** 456 * If crash is handled by instance of {@link android.app.IActivityController}, 457 * finish now and don't show the app error dialog. 458 */ 459 if (handleAppCrashInActivityController(r, crashInfo, shortMsg, longMsg, stackTrace, 460 timeMillis, callingPid, callingUid)) { 461 return; 462 } 463 464 // Suppress crash dialog if the process is being relaunched due to a crash during a free 465 // resize. 466 if (relaunchReason == RELAUNCH_REASON_FREE_RESIZE) { 467 return; 468 } 469 470 /** 471 * If this process was running instrumentation, finish now - it will be handled in 472 * {@link ActivityManagerService#handleAppDiedLocked}. 473 */ 474 if (r != null && r.getActiveInstrumentation() != null) { 475 return; 476 } 477 478 // Log crash in battery stats. 479 if (r != null) { 480 mService.mBatteryStatsService.noteProcessCrash(r.processName, r.uid); 481 } 482 483 AppErrorDialog.Data data = new AppErrorDialog.Data(); 484 data.result = result; 485 data.proc = r; 486 487 // If we can't identify the process or it's already exceeded its crash quota, 488 // quit right away without showing a crash dialog. 489 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, data)) { 490 return; 491 } 492 493 final Message msg = Message.obtain(); 494 msg.what = ActivityManagerService.SHOW_ERROR_UI_MSG; 495 496 taskId = data.taskId; 497 msg.obj = data; 498 mService.mUiHandler.sendMessage(msg); 499 } 500 501 int res = result.get(); 502 503 Intent appErrorIntent = null; 504 MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res); 505 if (res == AppErrorDialog.TIMEOUT || res == AppErrorDialog.CANCEL) { 506 res = AppErrorDialog.FORCE_QUIT; 507 } 508 synchronized (mService) { 509 if (res == AppErrorDialog.MUTE) { 510 stopReportingCrashesLocked(r); 511 } 512 if (res == AppErrorDialog.RESTART) { 513 mService.mProcessList.removeProcessLocked(r, false, true, "crash"); 514 if (taskId != INVALID_TASK_ID) { 515 try { 516 mService.startActivityFromRecents(taskId, 517 ActivityOptions.makeBasic().toBundle()); 518 } catch (IllegalArgumentException e) { 519 // Hmm...that didn't work. Task should either be in recents or associated 520 // with a stack. 521 Slog.e(TAG, "Could not restart taskId=" + taskId, e); 522 } 523 } 524 } 525 if (res == AppErrorDialog.FORCE_QUIT) { 526 long orig = Binder.clearCallingIdentity(); 527 try { 528 // Kill it with fire! 529 mService.mAtmInternal.onHandleAppCrash(r.getWindowProcessController()); 530 if (!r.isPersistent()) { 531 mService.mProcessList.removeProcessLocked(r, false, false, "crash"); 532 mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */); 533 } 534 } finally { 535 Binder.restoreCallingIdentity(orig); 536 } 537 } 538 if (res == AppErrorDialog.APP_INFO) { 539 appErrorIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); 540 appErrorIntent.setData(Uri.parse("package:" + r.info.packageName)); 541 appErrorIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 542 } 543 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) { 544 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo); 545 } 546 if (r != null && !r.isolated && res != AppErrorDialog.RESTART) { 547 // XXX Can't keep track of crash time for isolated processes, 548 // since they don't have a persistent identity. 549 mProcessCrashTimes.put(r.info.processName, r.uid, 550 SystemClock.uptimeMillis()); 551 } 552 } 553 554 if (appErrorIntent != null) { 555 try { 556 mContext.startActivityAsUser(appErrorIntent, new UserHandle(r.userId)); 557 } catch (ActivityNotFoundException e) { 558 Slog.w(TAG, "bug report receiver dissappeared", e); 559 } 560 } 561 } 562 handleAppCrashInActivityController(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo, String shortMsg, String longMsg, String stackTrace, long timeMillis, int callingPid, int callingUid)563 private boolean handleAppCrashInActivityController(ProcessRecord r, 564 ApplicationErrorReport.CrashInfo crashInfo, 565 String shortMsg, String longMsg, 566 String stackTrace, long timeMillis, 567 int callingPid, int callingUid) { 568 String name = r != null ? r.processName : null; 569 int pid = r != null ? r.pid : callingPid; 570 int uid = r != null ? r.info.uid : callingUid; 571 572 return mService.mAtmInternal.handleAppCrashInActivityController( 573 name, pid, shortMsg, longMsg, timeMillis, crashInfo.stackTrace, () -> { 574 if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")) 575 && "Native crash".equals(crashInfo.exceptionClassName)) { 576 Slog.w(TAG, "Skip killing native crashed app " + name 577 + "(" + pid + ") during testing"); 578 } else { 579 Slog.w(TAG, "Force-killing crashed app " + name + " at watcher's request"); 580 if (r != null) { 581 if (!makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, null)) { 582 r.kill("crash", true); 583 } 584 } else { 585 // Huh. 586 Process.killProcess(pid); 587 ProcessList.killProcessGroup(uid, pid); 588 } 589 } 590 }); 591 } 592 593 private boolean makeAppCrashingLocked(ProcessRecord app, 594 String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) { 595 app.setCrashing(true); 596 app.crashingReport = generateProcessError(app, 597 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace); 598 app.startAppProblemLocked(); 599 app.getWindowProcessController().stopFreezingActivities(); 600 return handleAppCrashLocked(app, "force-crash" /*reason*/, shortMsg, longMsg, stackTrace, 601 data); 602 } 603 604 /** 605 * Generate a process error record, suitable for attachment to a ProcessRecord. 606 * 607 * @param app The ProcessRecord in which the error occurred. 608 * @param condition Crashing, Application Not Responding, etc. Values are defined in 609 * ActivityManager.ProcessErrorStateInfo 610 * @param activity The activity associated with the crash, if known. 611 * @param shortMsg Short message describing the crash. 612 * @param longMsg Long message describing the crash. 613 * @param stackTrace Full crash stack trace, may be null. 614 * 615 * @return Returns a fully-formed ProcessErrorStateInfo record. 616 */ 617 ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app, 618 int condition, String activity, String shortMsg, String longMsg, String stackTrace) { 619 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo(); 620 621 report.condition = condition; 622 report.processName = app.processName; 623 report.pid = app.pid; 624 report.uid = app.info.uid; 625 report.tag = activity; 626 report.shortMsg = shortMsg; 627 report.longMsg = longMsg; 628 report.stackTrace = stackTrace; 629 630 return report; 631 } 632 633 Intent createAppErrorIntentLocked(ProcessRecord r, 634 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) { 635 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo); 636 if (report == null) { 637 return null; 638 } 639 Intent result = new Intent(Intent.ACTION_APP_ERROR); 640 result.setComponent(r.errorReportReceiver); 641 result.putExtra(Intent.EXTRA_BUG_REPORT, report); 642 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 643 return result; 644 } 645 646 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r, 647 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) { 648 if (r.errorReportReceiver == null) { 649 return null; 650 } 651 652 if (!r.isCrashing() && !r.isNotResponding() && !r.forceCrashReport) { 653 return null; 654 } 655 656 ApplicationErrorReport report = new ApplicationErrorReport(); 657 report.packageName = r.info.packageName; 658 report.installerPackageName = r.errorReportReceiver.getPackageName(); 659 report.processName = r.processName; 660 report.time = timeMillis; 661 report.systemApp = (r.info.flags & FLAG_SYSTEM) != 0; 662 663 if (r.isCrashing() || r.forceCrashReport) { 664 report.type = ApplicationErrorReport.TYPE_CRASH; 665 report.crashInfo = crashInfo; 666 } else if (r.isNotResponding()) { 667 report.type = ApplicationErrorReport.TYPE_ANR; 668 report.anrInfo = new ApplicationErrorReport.AnrInfo(); 669 670 report.anrInfo.activity = r.notRespondingReport.tag; 671 report.anrInfo.cause = r.notRespondingReport.shortMsg; 672 report.anrInfo.info = r.notRespondingReport.longMsg; 673 } 674 675 return report; 676 } 677 678 boolean handleAppCrashLocked(ProcessRecord app, String reason, 679 String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) { 680 final long now = SystemClock.uptimeMillis(); 681 final boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(), 682 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0; 683 684 final boolean procIsBoundForeground = 685 (app.getCurProcState() == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE); 686 687 Long crashTime; 688 Long crashTimePersistent; 689 boolean tryAgain = false; 690 691 if (!app.isolated) { 692 crashTime = mProcessCrashTimes.get(app.info.processName, app.uid); 693 crashTimePersistent = mProcessCrashTimesPersistent.get(app.info.processName, app.uid); 694 } else { 695 crashTime = crashTimePersistent = null; 696 } 697 698 // Bump up the crash count of any services currently running in the proc. 699 for (int i = app.services.size() - 1; i >= 0; i--) { 700 // Any services running in the application need to be placed 701 // back in the pending list. 702 ServiceRecord sr = app.services.valueAt(i); 703 // If the service was restarted a while ago, then reset crash count, else increment it. 704 if (now > sr.restartTime + ProcessList.MIN_CRASH_INTERVAL) { 705 sr.crashCount = 1; 706 } else { 707 sr.crashCount++; 708 } 709 // Allow restarting for started or bound foreground services that are crashing. 710 // This includes wallpapers. 711 if (sr.crashCount < mService.mConstants.BOUND_SERVICE_MAX_CRASH_RETRY 712 && (sr.isForeground || procIsBoundForeground)) { 713 tryAgain = true; 714 } 715 } 716 717 if (crashTime != null && now < crashTime + ProcessList.MIN_CRASH_INTERVAL) { 718 // The process crashed again very quickly. If it was a bound foreground service, let's 719 // try to restart again in a while, otherwise the process loses! 720 Slog.w(TAG, "Process " + app.info.processName 721 + " has crashed too many times: killing!"); 722 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH, 723 app.userId, app.info.processName, app.uid); 724 mService.mAtmInternal.onHandleAppCrash(app.getWindowProcessController()); 725 if (!app.isPersistent()) { 726 // We don't want to start this process again until the user 727 // explicitly does so... but for persistent process, we really 728 // need to keep it running. If a persistent process is actually 729 // repeatedly crashing, then badness for everyone. 730 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.userId, app.uid, 731 app.info.processName); 732 if (!app.isolated) { 733 // XXX We don't have a way to mark isolated processes 734 // as bad, since they don't have a peristent identity. 735 mBadProcesses.put(app.info.processName, app.uid, 736 new BadProcessInfo(now, shortMsg, longMsg, stackTrace)); 737 mProcessCrashTimes.remove(app.info.processName, app.uid); 738 } 739 app.bad = true; 740 app.removed = true; 741 // Don't let services in this process be restarted and potentially 742 // annoy the user repeatedly. Unless it is persistent, since those 743 // processes run critical code. 744 mService.mProcessList.removeProcessLocked(app, false, tryAgain, "crash"); 745 mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */); 746 if (!showBackground) { 747 return false; 748 } 749 } 750 mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */); 751 } else { 752 final int affectedTaskId = mService.mAtmInternal.finishTopCrashedActivities( 753 app.getWindowProcessController(), reason); 754 if (data != null) { 755 data.taskId = affectedTaskId; 756 } 757 if (data != null && crashTimePersistent != null 758 && now < crashTimePersistent + ProcessList.MIN_CRASH_INTERVAL) { 759 data.repeating = true; 760 } 761 } 762 763 if (data != null && tryAgain) { 764 data.isRestartableForService = true; 765 } 766 767 // If the crashing process is what we consider to be the "home process" and it has been 768 // replaced by a third-party app, clear the package preferred activities from packages 769 // with a home activity running in the process to prevent a repeatedly crashing app 770 // from blocking the user to manually clear the list. 771 final WindowProcessController proc = app.getWindowProcessController(); 772 final WindowProcessController homeProc = mService.mAtmInternal.getHomeProcess(); 773 if (proc == homeProc && proc.hasActivities() 774 && (((ProcessRecord) homeProc.mOwner).info.flags & FLAG_SYSTEM) == 0) { 775 proc.clearPackagePreferredForHomeActivities(); 776 } 777 778 if (!app.isolated) { 779 // XXX Can't keep track of crash times for isolated processes, 780 // because they don't have a persistent identity. 781 mProcessCrashTimes.put(app.info.processName, app.uid, now); 782 mProcessCrashTimesPersistent.put(app.info.processName, app.uid, now); 783 } 784 785 if (app.crashHandler != null) mService.mHandler.post(app.crashHandler); 786 return true; 787 } 788 789 void handleShowAppErrorUi(Message msg) { 790 AppErrorDialog.Data data = (AppErrorDialog.Data) msg.obj; 791 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(), 792 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0; 793 794 AppErrorDialog dialogToShow = null; 795 final String packageName; 796 final int userId; 797 synchronized (mService) { 798 final ProcessRecord proc = data.proc; 799 final AppErrorResult res = data.result; 800 if (proc == null) { 801 Slog.e(TAG, "handleShowAppErrorUi: proc is null"); 802 return; 803 } 804 packageName = proc.info.packageName; 805 userId = proc.userId; 806 if (proc.crashDialog != null) { 807 Slog.e(TAG, "App already has crash dialog: " + proc); 808 if (res != null) { 809 res.set(AppErrorDialog.ALREADY_SHOWING); 810 } 811 return; 812 } 813 boolean isBackground = (UserHandle.getAppId(proc.uid) 814 >= Process.FIRST_APPLICATION_UID 815 && proc.pid != MY_PID); 816 for (int profileId : mService.mUserController.getCurrentProfileIds()) { 817 isBackground &= (userId != profileId); 818 } 819 if (isBackground && !showBackground) { 820 Slog.w(TAG, "Skipping crash dialog of " + proc + ": background"); 821 if (res != null) { 822 res.set(AppErrorDialog.BACKGROUND_USER); 823 } 824 return; 825 } 826 final boolean showFirstCrash = Settings.Global.getInt( 827 mContext.getContentResolver(), 828 Settings.Global.SHOW_FIRST_CRASH_DIALOG, 0) != 0; 829 final boolean showFirstCrashDevOption = Settings.Secure.getIntForUser( 830 mContext.getContentResolver(), 831 Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION, 832 0, 833 mService.mUserController.getCurrentUserId()) != 0; 834 final boolean crashSilenced = mAppsNotReportingCrashes != null && 835 mAppsNotReportingCrashes.contains(proc.info.packageName); 836 if ((mService.mAtmInternal.canShowErrorDialogs() || showBackground) 837 && !crashSilenced 838 && (showFirstCrash || showFirstCrashDevOption || data.repeating)) { 839 proc.crashDialog = dialogToShow = new AppErrorDialog(mContext, mService, data); 840 } else { 841 // The device is asleep, so just pretend that the user 842 // saw a crash dialog and hit "force quit". 843 if (res != null) { 844 res.set(AppErrorDialog.CANT_SHOW); 845 } 846 } 847 } 848 // If we've created a crash dialog, show it without the lock held 849 if (dialogToShow != null) { 850 Slog.i(TAG, "Showing crash dialog for package " + packageName + " u" + userId); 851 dialogToShow.show(); 852 } 853 } 854 855 private void stopReportingCrashesLocked(ProcessRecord proc) { 856 if (mAppsNotReportingCrashes == null) { 857 mAppsNotReportingCrashes = new ArraySet<>(); 858 } 859 mAppsNotReportingCrashes.add(proc.info.packageName); 860 } 861 862 void handleShowAnrUi(Message msg) { 863 Dialog dialogToShow = null; 864 List<VersionedPackage> packageList = null; 865 synchronized (mService) { 866 AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj; 867 final ProcessRecord proc = data.proc; 868 if (proc == null) { 869 Slog.e(TAG, "handleShowAnrUi: proc is null"); 870 return; 871 } 872 if (!proc.isPersistent()) { 873 packageList = proc.getPackageListWithVersionCode(); 874 } 875 if (proc.anrDialog != null) { 876 Slog.e(TAG, "App already has anr dialog: " + proc); 877 MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR, 878 AppNotRespondingDialog.ALREADY_SHOWING); 879 return; 880 } 881 882 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(), 883 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0; 884 if (mService.mAtmInternal.canShowErrorDialogs() || showBackground) { 885 dialogToShow = new AppNotRespondingDialog(mService, mContext, data); 886 proc.anrDialog = dialogToShow; 887 } else { 888 MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR, 889 AppNotRespondingDialog.CANT_SHOW); 890 // Just kill the app if there is no dialog to be shown. 891 mService.killAppAtUsersRequest(proc, null); 892 } 893 } 894 // If we've created a crash dialog, show it without the lock held 895 if (dialogToShow != null) { 896 dialogToShow.show(); 897 } 898 // Notify PackageWatchdog without the lock held 899 if (packageList != null) { 900 mPackageWatchdog.onPackageFailure(packageList, 901 PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING); 902 } 903 } 904 905 /** 906 * Information about a process that is currently marked as bad. 907 */ 908 static final class BadProcessInfo { 909 BadProcessInfo(long time, String shortMsg, String longMsg, String stack) { 910 this.time = time; 911 this.shortMsg = shortMsg; 912 this.longMsg = longMsg; 913 this.stack = stack; 914 } 915 916 final long time; 917 final String shortMsg; 918 final String longMsg; 919 final String stack; 920 } 921 922 } 923