Merge "Fix crash loop when activity controller was set" into nyc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
099347936b
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user