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