Loading services/core/java/com/android/server/am/AppErrors.java +130 −117 Original line number Original line Diff line number Diff line Loading @@ -304,6 +304,15 @@ class AppErrors { * @param crashInfo describing the failure * @param crashInfo describing the failure */ */ void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) { void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) { final long origId = Binder.clearCallingIdentity(); try { crashApplicationInner(r, crashInfo); } finally { Binder.restoreCallingIdentity(origId); } } void crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) { long timeMillis = System.currentTimeMillis(); long timeMillis = System.currentTimeMillis(); String shortMsg = crashInfo.exceptionClassName; String shortMsg = crashInfo.exceptionClassName; String longMsg = crashInfo.exceptionMessage; String longMsg = crashInfo.exceptionMessage; Loading @@ -317,49 +326,20 @@ class AppErrors { AppErrorResult result = new AppErrorResult(); AppErrorResult result = new AppErrorResult(); TaskRecord task; TaskRecord task; synchronized (mService) { synchronized (mService) { if (mService.mController != null) { /** try { * If crash is handled by instance of {@link android.app.IActivityController}, String name = r != null ? r.processName : null; * finish now and don't show the app error dialog. int pid = r != null ? r.pid : Binder.getCallingPid(); */ int uid = r != null ? r.info.uid : Binder.getCallingUid(); if (handleAppCrashInActivityController(r, crashInfo, shortMsg, longMsg, stackTrace, if (!mService.mController.appCrashed(name, pid, timeMillis)) { shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) { if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")) && "Native crash".equals(crashInfo.exceptionClassName)) { Slog.w(TAG, "Skip killing native crashed app " + name + "(" + pid + ") during testing"); } else { Slog.w(TAG, "Force-killing crashed app " + name + " at watcher's request"); if (r != null) { r.kill("crash", true); } else { // Huh. Process.killProcess(pid); ActivityManagerService.killProcessGroup(uid, pid); } } return; return; } } } catch (RemoteException e) { mService.mController = null; Watchdog.getInstance().setActivityController(null); } } final long origId = Binder.clearCallingIdentity(); /** * If this process was running instrumentation, finish now - it will be handled in // If this process is running instrumentation, finish it. * {@link ActivityManagerService#handleAppDiedLocked}. */ if (r != null && r.instrumentationClass != null) { if (r != null && r.instrumentationClass != null) { Slog.w(TAG, "Error in app " + r.processName + " running instrumentation " + r.instrumentationClass + ":"); if (shortMsg != null) Slog.w(TAG, " " + shortMsg); if (longMsg != null) Slog.w(TAG, " " + longMsg); Bundle info = new Bundle(); info.putString("shortMsg", shortMsg); info.putString("longMsg", longMsg); mService.finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info); Binder.restoreCallingIdentity(origId); return; return; } } Loading @@ -375,7 +355,6 @@ class AppErrors { // If we can't identify the process or it's already exceeded its crash quota, // If we can't identify the process or it's already exceeded its crash quota, // quit right away without showing a crash dialog. // quit right away without showing a crash dialog. if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, data)) { if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, data)) { Binder.restoreCallingIdentity(origId); return; return; } } Loading @@ -385,15 +364,11 @@ class AppErrors { task = data.task; task = data.task; msg.obj = data; msg.obj = data; mService.mUiHandler.sendMessage(msg); mService.mUiHandler.sendMessage(msg); Binder.restoreCallingIdentity(origId); } } int res = result.get(); int res = result.get(); Intent appErrorIntent = null; Intent appErrorIntent = null; final long ident = Binder.clearCallingIdentity(); try { MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res); MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res); if (res == AppErrorDialog.TIMEOUT) { if (res == AppErrorDialog.TIMEOUT) { res = AppErrorDialog.FORCE_QUIT; res = AppErrorDialog.FORCE_QUIT; Loading Loading @@ -474,9 +449,6 @@ class AppErrors { SystemClock.uptimeMillis()); SystemClock.uptimeMillis()); } } } } } finally { Binder.restoreCallingIdentity(ident); } if (appErrorIntent != null) { if (appErrorIntent != null) { try { try { Loading @@ -487,6 +459,47 @@ class AppErrors { } } } } private boolean handleAppCrashInActivityController(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo, String shortMsg, String longMsg, String stackTrace, long timeMillis) { if (mService.mController == null) { return false; } try { String name = r != null ? r.processName : null; int pid = r != null ? r.pid : Binder.getCallingPid(); int uid = r != null ? r.info.uid : Binder.getCallingUid(); if (!mService.mController.appCrashed(name, pid, shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) { if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")) && "Native crash".equals(crashInfo.exceptionClassName)) { Slog.w(TAG, "Skip killing native crashed app " + name + "(" + pid + ") during testing"); } else { Slog.w(TAG, "Force-killing crashed app " + name + " at watcher's request"); if (r != null) { if (!makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, null)) { r.kill("crash", true); } } else { // Huh. Process.killProcess(pid); ActivityManagerService.killProcessGroup(uid, pid); } } return true; } } catch (RemoteException e) { mService.mController = null; Watchdog.getInstance().setActivityController(null); } return false; } private boolean makeAppCrashingLocked(ProcessRecord app, private boolean makeAppCrashingLocked(ProcessRecord app, String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) { String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) { app.crashing = true; app.crashing = true; Loading Loading
services/core/java/com/android/server/am/AppErrors.java +130 −117 Original line number Original line Diff line number Diff line Loading @@ -304,6 +304,15 @@ class AppErrors { * @param crashInfo describing the failure * @param crashInfo describing the failure */ */ void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) { void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) { final long origId = Binder.clearCallingIdentity(); try { crashApplicationInner(r, crashInfo); } finally { Binder.restoreCallingIdentity(origId); } } void crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) { long timeMillis = System.currentTimeMillis(); long timeMillis = System.currentTimeMillis(); String shortMsg = crashInfo.exceptionClassName; String shortMsg = crashInfo.exceptionClassName; String longMsg = crashInfo.exceptionMessage; String longMsg = crashInfo.exceptionMessage; Loading @@ -317,49 +326,20 @@ class AppErrors { AppErrorResult result = new AppErrorResult(); AppErrorResult result = new AppErrorResult(); TaskRecord task; TaskRecord task; synchronized (mService) { synchronized (mService) { if (mService.mController != null) { /** try { * If crash is handled by instance of {@link android.app.IActivityController}, String name = r != null ? r.processName : null; * finish now and don't show the app error dialog. int pid = r != null ? r.pid : Binder.getCallingPid(); */ int uid = r != null ? r.info.uid : Binder.getCallingUid(); if (handleAppCrashInActivityController(r, crashInfo, shortMsg, longMsg, stackTrace, if (!mService.mController.appCrashed(name, pid, timeMillis)) { shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) { if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")) && "Native crash".equals(crashInfo.exceptionClassName)) { Slog.w(TAG, "Skip killing native crashed app " + name + "(" + pid + ") during testing"); } else { Slog.w(TAG, "Force-killing crashed app " + name + " at watcher's request"); if (r != null) { r.kill("crash", true); } else { // Huh. Process.killProcess(pid); ActivityManagerService.killProcessGroup(uid, pid); } } return; return; } } } catch (RemoteException e) { mService.mController = null; Watchdog.getInstance().setActivityController(null); } } final long origId = Binder.clearCallingIdentity(); /** * If this process was running instrumentation, finish now - it will be handled in // If this process is running instrumentation, finish it. * {@link ActivityManagerService#handleAppDiedLocked}. */ if (r != null && r.instrumentationClass != null) { if (r != null && r.instrumentationClass != null) { Slog.w(TAG, "Error in app " + r.processName + " running instrumentation " + r.instrumentationClass + ":"); if (shortMsg != null) Slog.w(TAG, " " + shortMsg); if (longMsg != null) Slog.w(TAG, " " + longMsg); Bundle info = new Bundle(); info.putString("shortMsg", shortMsg); info.putString("longMsg", longMsg); mService.finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info); Binder.restoreCallingIdentity(origId); return; return; } } Loading @@ -375,7 +355,6 @@ class AppErrors { // If we can't identify the process or it's already exceeded its crash quota, // If we can't identify the process or it's already exceeded its crash quota, // quit right away without showing a crash dialog. // quit right away without showing a crash dialog. if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, data)) { if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, data)) { Binder.restoreCallingIdentity(origId); return; return; } } Loading @@ -385,15 +364,11 @@ class AppErrors { task = data.task; task = data.task; msg.obj = data; msg.obj = data; mService.mUiHandler.sendMessage(msg); mService.mUiHandler.sendMessage(msg); Binder.restoreCallingIdentity(origId); } } int res = result.get(); int res = result.get(); Intent appErrorIntent = null; Intent appErrorIntent = null; final long ident = Binder.clearCallingIdentity(); try { MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res); MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res); if (res == AppErrorDialog.TIMEOUT) { if (res == AppErrorDialog.TIMEOUT) { res = AppErrorDialog.FORCE_QUIT; res = AppErrorDialog.FORCE_QUIT; Loading Loading @@ -474,9 +449,6 @@ class AppErrors { SystemClock.uptimeMillis()); SystemClock.uptimeMillis()); } } } } } finally { Binder.restoreCallingIdentity(ident); } if (appErrorIntent != null) { if (appErrorIntent != null) { try { try { Loading @@ -487,6 +459,47 @@ class AppErrors { } } } } private boolean handleAppCrashInActivityController(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo, String shortMsg, String longMsg, String stackTrace, long timeMillis) { if (mService.mController == null) { return false; } try { String name = r != null ? r.processName : null; int pid = r != null ? r.pid : Binder.getCallingPid(); int uid = r != null ? r.info.uid : Binder.getCallingUid(); if (!mService.mController.appCrashed(name, pid, shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) { if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")) && "Native crash".equals(crashInfo.exceptionClassName)) { Slog.w(TAG, "Skip killing native crashed app " + name + "(" + pid + ") during testing"); } else { Slog.w(TAG, "Force-killing crashed app " + name + " at watcher's request"); if (r != null) { if (!makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, null)) { r.kill("crash", true); } } else { // Huh. Process.killProcess(pid); ActivityManagerService.killProcessGroup(uid, pid); } } return true; } } catch (RemoteException e) { mService.mController = null; Watchdog.getInstance().setActivityController(null); } return false; } private boolean makeAppCrashingLocked(ProcessRecord app, private boolean makeAppCrashingLocked(ProcessRecord app, String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) { String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) { app.crashing = true; app.crashing = true; Loading