[ActivityManager] Move UI operation to UI handler
Because ANR will dump cpu usage, stack traces in ActivityManager
thread, if system is busy or in low-end device, it may spend more
than 5s to dump. So when there is UI operation (e.g. pop dialog)
in ActivityManager thread, it may meet key dispatch timeout.
Change-Id: Ie550e31a7cff65bdcfc9af2c32989e9deb5fb2cf
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index a5cd1db..914d883 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1287,10 +1287,11 @@
final ServiceThread mHandlerThread;
final MainHandler mHandler;
+ final UiHandler mUiHandler;
- final class MainHandler extends Handler {
- public MainHandler(Looper looper) {
- super(looper, null, true);
+ final class UiHandler extends Handler {
+ public UiHandler() {
+ super(com.android.server.UiThread.get().getLooper(), null, true);
}
@Override
@@ -1403,15 +1404,6 @@
d.show();
ensureBootCompleted();
} break;
- case UPDATE_CONFIGURATION_MSG: {
- final ContentResolver resolver = mContext.getContentResolver();
- Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
- } break;
- case GC_BACKGROUND_PROCESSES_MSG: {
- synchronized (ActivityManagerService.this) {
- performAppGcsIfAppropriateLocked();
- }
- } break;
case WAIT_FOR_DEBUGGER_MSG: {
synchronized (ActivityManagerService.this) {
ProcessRecord app = (ProcessRecord)msg.obj;
@@ -1432,6 +1424,88 @@
}
}
} break;
+ case SHOW_UID_ERROR_MSG: {
+ if (mShowDialogs) {
+ AlertDialog d = new BaseErrorDialog(mContext);
+ d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
+ d.setCancelable(false);
+ d.setTitle(mContext.getText(R.string.android_system_label));
+ d.setMessage(mContext.getText(R.string.system_error_wipe_data));
+ d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok),
+ obtainMessage(DISMISS_DIALOG_MSG, d));
+ d.show();
+ }
+ } break;
+ case SHOW_FINGERPRINT_ERROR_MSG: {
+ if (mShowDialogs) {
+ AlertDialog d = new BaseErrorDialog(mContext);
+ d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
+ d.setCancelable(false);
+ d.setTitle(mContext.getText(R.string.android_system_label));
+ d.setMessage(mContext.getText(R.string.system_error_manufacturer));
+ d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok),
+ obtainMessage(DISMISS_DIALOG_MSG, d));
+ d.show();
+ }
+ } break;
+ case SHOW_COMPAT_MODE_DIALOG_MSG: {
+ synchronized (ActivityManagerService.this) {
+ ActivityRecord ar = (ActivityRecord) msg.obj;
+ if (mCompatModeDialog != null) {
+ if (mCompatModeDialog.mAppInfo.packageName.equals(
+ ar.info.applicationInfo.packageName)) {
+ return;
+ }
+ mCompatModeDialog.dismiss();
+ mCompatModeDialog = null;
+ }
+ if (ar != null && false) {
+ if (mCompatModePackages.getPackageAskCompatModeLocked(
+ ar.packageName)) {
+ int mode = mCompatModePackages.computeCompatModeLocked(
+ ar.info.applicationInfo);
+ if (mode == ActivityManager.COMPAT_MODE_DISABLED
+ || mode == ActivityManager.COMPAT_MODE_ENABLED) {
+ mCompatModeDialog = new CompatModeDialog(
+ ActivityManagerService.this, mContext,
+ ar.info.applicationInfo);
+ mCompatModeDialog.show();
+ }
+ }
+ }
+ }
+ break;
+ }
+ case START_USER_SWITCH_MSG: {
+ showUserSwitchDialog(msg.arg1, (String) msg.obj);
+ break;
+ }
+ case DISMISS_DIALOG_MSG: {
+ final Dialog d = (Dialog) msg.obj;
+ d.dismiss();
+ break;
+ }
+ }
+ }
+ }
+
+ final class MainHandler extends Handler {
+ public MainHandler(Looper looper) {
+ super(looper, null, true);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case UPDATE_CONFIGURATION_MSG: {
+ final ContentResolver resolver = mContext.getContentResolver();
+ Settings.System.putConfiguration(resolver, (Configuration) msg.obj);
+ } break;
+ case GC_BACKGROUND_PROCESSES_MSG: {
+ synchronized (ActivityManagerService.this) {
+ performAppGcsIfAppropriateLocked();
+ }
+ } break;
case SERVICE_TIMEOUT_MSG: {
if (mDidDexOpt) {
mDidDexOpt = false;
@@ -1496,30 +1570,6 @@
}
}
} break;
- case SHOW_UID_ERROR_MSG: {
- if (mShowDialogs) {
- AlertDialog d = new BaseErrorDialog(mContext);
- d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
- d.setCancelable(false);
- d.setTitle(mContext.getText(R.string.android_system_label));
- d.setMessage(mContext.getText(R.string.system_error_wipe_data));
- d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok),
- mHandler.obtainMessage(DISMISS_DIALOG_MSG, d));
- d.show();
- }
- } break;
- case SHOW_FINGERPRINT_ERROR_MSG: {
- if (mShowDialogs) {
- AlertDialog d = new BaseErrorDialog(mContext);
- d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
- d.setCancelable(false);
- d.setTitle(mContext.getText(R.string.android_system_label));
- d.setMessage(mContext.getText(R.string.system_error_manufacturer));
- d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok),
- mHandler.obtainMessage(DISMISS_DIALOG_MSG, d));
- d.show();
- }
- } break;
case PROC_START_TIMEOUT_MSG: {
if (mDidDexOpt) {
mDidDexOpt = false;
@@ -1620,34 +1670,6 @@
sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
}
} break;
- case SHOW_COMPAT_MODE_DIALOG_MSG: {
- synchronized (ActivityManagerService.this) {
- ActivityRecord ar = (ActivityRecord)msg.obj;
- if (mCompatModeDialog != null) {
- if (mCompatModeDialog.mAppInfo.packageName.equals(
- ar.info.applicationInfo.packageName)) {
- return;
- }
- mCompatModeDialog.dismiss();
- mCompatModeDialog = null;
- }
- if (ar != null && false) {
- if (mCompatModePackages.getPackageAskCompatModeLocked(
- ar.packageName)) {
- int mode = mCompatModePackages.computeCompatModeLocked(
- ar.info.applicationInfo);
- if (mode == ActivityManager.COMPAT_MODE_DISABLED
- || mode == ActivityManager.COMPAT_MODE_ENABLED) {
- mCompatModeDialog = new CompatModeDialog(
- ActivityManagerService.this, mContext,
- ar.info.applicationInfo);
- mCompatModeDialog.show();
- }
- }
- }
- }
- break;
- }
case DISPATCH_PROCESSES_CHANGED: {
dispatchProcessesChanged();
break;
@@ -1668,10 +1690,6 @@
thread.start();
break;
}
- case START_USER_SWITCH_MSG: {
- showUserSwitchDialog(msg.arg1, (String) msg.obj);
- break;
- }
case REPORT_USER_SWITCH_MSG: {
dispatchUserSwitch((UserStartedState) msg.obj, msg.arg1, msg.arg2);
break;
@@ -1779,11 +1797,6 @@
}
break;
}
- case DISMISS_DIALOG_MSG: {
- final Dialog d = (Dialog) msg.obj;
- d.dismiss();
- break;
- }
case NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG: {
synchronized (ActivityManagerService.this) {
int i = mTaskStackListeners.beginBroadcast();
@@ -2078,6 +2091,7 @@
android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
mHandlerThread.start();
mHandler = new MainHandler(mHandlerThread.getLooper());
+ mUiHandler = new UiHandler();
mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
"foreground", BROADCAST_FG_TIMEOUT, false);
@@ -2443,7 +2457,7 @@
Message msg = Message.obtain();
msg.what = SHOW_COMPAT_MODE_DIALOG_MSG;
msg.obj = r.task.askedCompatMode ? null : r;
- mHandler.sendMessage(msg);
+ mUiHandler.sendMessage(msg);
}
private int updateLruProcessInternalLocked(ProcessRecord app, long now, int index,
@@ -5100,20 +5114,20 @@
map.put("activity", activity);
}
- mHandler.sendMessage(msg);
+ mUiHandler.sendMessage(msg);
}
}
final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
if (!mLaunchWarningShown) {
mLaunchWarningShown = true;
- mHandler.post(new Runnable() {
+ mUiHandler.post(new Runnable() {
@Override
public void run() {
synchronized (ActivityManagerService.this) {
final Dialog d = new LaunchWarningWindow(mContext, cur, next);
d.show();
- mHandler.postDelayed(new Runnable() {
+ mUiHandler.postDelayed(new Runnable() {
@Override
public void run() {
synchronized (ActivityManagerService.this) {
@@ -8053,7 +8067,7 @@
msg.what = WAIT_FOR_DEBUGGER_MSG;
msg.obj = app;
msg.arg1 = waiting ? 1 : 0;
- mHandler.sendMessage(msg);
+ mUiHandler.sendMessage(msg);
}
}
@@ -11359,7 +11373,7 @@
Message msg = Message.obtain();
msg.what = SHOW_FACTORY_ERROR_MSG;
msg.getData().putCharSequence("msg", errorMsg);
- mHandler.sendMessage(msg);
+ mUiHandler.sendMessage(msg);
}
}
}
@@ -11409,14 +11423,14 @@
if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
Slog.e(TAG, "UIDs on the system are inconsistent, you need to wipe your"
+ " data partition or your device will be unstable.");
- mHandler.obtainMessage(SHOW_UID_ERROR_MSG).sendToTarget();
+ mUiHandler.obtainMessage(SHOW_UID_ERROR_MSG).sendToTarget();
}
} catch (RemoteException e) {
}
if (!Build.isFingerprintConsistent()) {
Slog.e(TAG, "Build fingerprint is not consistent, warning user");
- mHandler.obtainMessage(SHOW_FINGERPRINT_ERROR_MSG).sendToTarget();
+ mUiHandler.obtainMessage(SHOW_FINGERPRINT_ERROR_MSG).sendToTarget();
}
long ident = Binder.clearCallingIdentity();
@@ -11702,7 +11716,7 @@
data.put("violationMask", violationMask);
data.put("info", info);
msg.obj = data;
- mHandler.sendMessage(msg);
+ mUiHandler.sendMessage(msg);
Binder.restoreCallingIdentity(origId);
}
@@ -12157,7 +12171,7 @@
data.put("result", result);
data.put("app", r);
msg.obj = data;
- mHandler.sendMessage(msg);
+ mUiHandler.sendMessage(msg);
Binder.restoreCallingIdentity(origId);
}
@@ -18918,8 +18932,8 @@
userName = userInfo.name;
mTargetUserId = userId;
}
- mHandler.removeMessages(START_USER_SWITCH_MSG);
- mHandler.sendMessage(mHandler.obtainMessage(START_USER_SWITCH_MSG, userId, 0, userName));
+ mUiHandler.removeMessages(START_USER_SWITCH_MSG);
+ mUiHandler.sendMessage(mUiHandler.obtainMessage(START_USER_SWITCH_MSG, userId, 0, userName));
return true;
}