Merge "Fix crash loop when activity controller was set" into nyc-dev

This commit is contained in:
Andrii Kulian
2016-04-29 19:20:15 +00:00
committed by Android (Google) Code Review

View File

@@ -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;
@@ -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;
} }
@@ -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;
} }
@@ -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;
@@ -474,9 +449,6 @@ class AppErrors {
SystemClock.uptimeMillis()); SystemClock.uptimeMillis());
} }
} }
} finally {
Binder.restoreCallingIdentity(ident);
}
if (appErrorIntent != null) { if (appErrorIntent != null) {
try { try {
@@ -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;