diff options
| author | Dianne Hackborn <hackbod@google.com> | 2012-10-04 11:58:16 -0700 |
|---|---|---|
| committer | Dianne Hackborn <hackbod@google.com> | 2012-10-04 12:04:58 -0700 |
| commit | 5fe7e2a3043d6a8ca933c77ccf95c791b57b221a (patch) | |
| tree | f45af64c05358cec85257742b108b775c5cee8b3 /services/java/com | |
| parent | f7ee2a03c1f930db4b20c04225f496ada97e646b (diff) | |
| download | frameworks_base-5fe7e2a3043d6a8ca933c77ccf95c791b57b221a.zip frameworks_base-5fe7e2a3043d6a8ca933c77ccf95c791b57b221a.tar.gz frameworks_base-5fe7e2a3043d6a8ca933c77ccf95c791b57b221a.tar.bz2 | |
Fix issue #6968859: home not exiting an ANR'd dream
Add a new call to the activity manager for the input dispatcher
to report about any pid having an ANR. This has a new feature
where it can also tell the activity manager that it is above the
system alert layer, so the activity manager can pop its ANR dialog
on top of everything if it needs to. (Normally we don't want
these dialogs appearing on top of the lock screen.)
Also fixed some debugging stuff here and there that was useful
as I was working on this -- windows now very clearly include
their uid, various system dialogs now have titles so you know
what they are in the window manager, etc.
Change-Id: Ib8f5d29a5572542cc506e6d338599ab64088ce4e
Diffstat (limited to 'services/java/com')
14 files changed, 115 insertions, 23 deletions
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java index 1269433..7e3fdbd 100644 --- a/services/java/com/android/server/am/ActiveServices.java +++ b/services/java/com/android/server/am/ActiveServices.java @@ -1850,7 +1850,7 @@ public class ActiveServices { } if (anrMessage != null) { - mAm.appNotResponding(proc, null, null, anrMessage); + mAm.appNotResponding(proc, null, null, false, anrMessage); } } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index e90eef9..3ef6767 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -970,7 +970,8 @@ public final class ActivityManagerService extends ActivityManagerNative if (mShowDialogs) { Dialog d = new AppNotRespondingDialog(ActivityManagerService.this, - mContext, proc, (ActivityRecord)data.get("activity")); + mContext, proc, (ActivityRecord)data.get("activity"), + msg.arg1 != 0); d.show(); proc.anrDialog = d; } else { @@ -3247,7 +3248,7 @@ public final class ActivityManagerService extends ActivityManagerNative } final void appNotResponding(ProcessRecord app, ActivityRecord activity, - ActivityRecord parent, final String annotation) { + ActivityRecord parent, boolean aboveSystem, final String annotation) { ArrayList<Integer> firstPids = new ArrayList<Integer>(5); SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20); @@ -3388,6 +3389,7 @@ public final class ActivityManagerService extends ActivityManagerNative HashMap map = new HashMap(); msg.what = SHOW_NOT_RESPONDING_MSG; msg.obj = map; + msg.arg1 = aboveSystem ? 1 : 0; map.put("app", app); if (activity != null) { map.put("activity", activity); @@ -7340,6 +7342,51 @@ public final class ActivityManagerService extends ActivityManagerNative SystemProperties.set("ctl.start", "bugreport"); } + public long inputDispatchingTimedOut(int pid, boolean aboveSystem) { + if (checkCallingPermission(android.Manifest.permission.FILTER_EVENTS) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Requires permission " + + android.Manifest.permission.FILTER_EVENTS); + } + + ProcessRecord proc; + + // TODO: Unify this code with ActivityRecord.keyDispatchingTimedOut(). + synchronized (this) { + synchronized (mPidsSelfLocked) { + proc = mPidsSelfLocked.get(pid); + } + if (proc != null) { + if (proc.debugging) { + return -1; + } + + if (mDidDexOpt) { + // Give more time since we were dexopting. + mDidDexOpt = false; + return -1; + } + + if (proc.instrumentationClass != null) { + Bundle info = new Bundle(); + info.putString("shortMsg", "keyDispatchingTimedOut"); + info.putString("longMsg", "Timed out while dispatching key event"); + finishInstrumentationLocked(proc, Activity.RESULT_CANCELED, info); + proc = null; + } + } + } + + if (proc != null) { + appNotResponding(proc, null, null, aboveSystem, "keyDispatchingTimedOut"); + if (proc.instrumentationClass != null || proc.usingWrapper) { + return INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT; + } + } + + return KEY_DISPATCHING_TIMEOUT; + } + public void registerProcessObserver(IProcessObserver observer) { enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER, "registerProcessObserver()"); diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java index 6cd86fd..b9f5b5b 100644 --- a/services/java/com/android/server/am/ActivityRecord.java +++ b/services/java/com/android/server/am/ActivityRecord.java @@ -841,6 +841,7 @@ final class ActivityRecord { } public boolean keyDispatchingTimedOut() { + // TODO: Unify this code with ActivityManagerService.inputDispatchingTimedOut(). ActivityRecord r; ProcessRecord anrApp = null; synchronized(service) { @@ -869,8 +870,7 @@ final class ActivityRecord { } if (anrApp != null) { - service.appNotResponding(anrApp, r, this, - "keyDispatchingTimedOut"); + service.appNotResponding(anrApp, r, this, false, "keyDispatchingTimedOut"); } return true; diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index 90a7abc..a6dc867 100755 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -2436,8 +2436,8 @@ final class ActivityStack { if (err == ActivityManager.START_SUCCESS) { final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0; - Slog.i(TAG, "START {" + intent.toShortString(true, true, true, false) - + " u=" + userId + "} from pid " + (callerApp != null ? callerApp.pid : callingPid)); + Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false) + + "} from pid " + (callerApp != null ? callerApp.pid : callingPid)); } ActivityRecord sourceRecord = null; diff --git a/services/java/com/android/server/am/AppErrorDialog.java b/services/java/com/android/server/am/AppErrorDialog.java index 0ebbe3b..a9c77fc 100644 --- a/services/java/com/android/server/am/AppErrorDialog.java +++ b/services/java/com/android/server/am/AppErrorDialog.java @@ -23,12 +23,9 @@ import android.content.DialogInterface; import android.content.res.Resources; import android.os.Handler; import android.os.Message; -import android.util.Slog; import android.view.WindowManager; class AppErrorDialog extends BaseErrorDialog { - private final static String TAG = "AppErrorDialog"; - private final ActivityManagerService mService; private final AppErrorResult mResult; private final ProcessRecord mProc; @@ -76,7 +73,9 @@ class AppErrorDialog extends BaseErrorDialog { setTitle(res.getText(com.android.internal.R.string.aerr_title)); getWindow().addFlags(FLAG_SYSTEM_ERROR); - getWindow().setTitle("Application Error: " + app.info.processName); + WindowManager.LayoutParams attrs = getWindow().getAttributes(); + attrs.setTitle("Application Error: " + app.info.processName); + getWindow().setAttributes(attrs); if (app.persistent) { getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); } diff --git a/services/java/com/android/server/am/AppNotRespondingDialog.java b/services/java/com/android/server/am/AppNotRespondingDialog.java index b546ae7..58e533b 100644 --- a/services/java/com/android/server/am/AppNotRespondingDialog.java +++ b/services/java/com/android/server/am/AppNotRespondingDialog.java @@ -25,8 +25,8 @@ import android.content.Intent; import android.content.res.Resources; import android.os.Handler; import android.os.Message; -import android.os.Process; import android.util.Slog; +import android.view.WindowManager; class AppNotRespondingDialog extends BaseErrorDialog { private static final String TAG = "AppNotRespondingDialog"; @@ -40,7 +40,7 @@ class AppNotRespondingDialog extends BaseErrorDialog { private final ProcessRecord mProc; public AppNotRespondingDialog(ActivityManagerService service, Context context, - ProcessRecord app, ActivityRecord activity) { + ProcessRecord app, ActivityRecord activity, boolean aboveSystem) { super(context); mService = service; @@ -91,8 +91,13 @@ class AppNotRespondingDialog extends BaseErrorDialog { } setTitle(res.getText(com.android.internal.R.string.anr_title)); + if (aboveSystem) { + getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); + } getWindow().addFlags(FLAG_SYSTEM_ERROR); - getWindow().setTitle("Application Not Responding: " + app.info.processName); + WindowManager.LayoutParams attrs = getWindow().getAttributes(); + attrs.setTitle("Application Not Responding: " + app.info.processName); + getWindow().setAttributes(attrs); } public void onStop() { diff --git a/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java b/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java index 9fb48b3..d08bb10 100644 --- a/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java +++ b/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java @@ -20,6 +20,7 @@ import android.content.Context; import android.content.DialogInterface; import android.os.Handler; import android.os.Message; +import android.view.WindowManager; class AppWaitingForDebuggerDialog extends BaseErrorDialog { final ActivityManagerService mService; @@ -52,7 +53,9 @@ class AppWaitingForDebuggerDialog extends BaseErrorDialog { setMessage(text.toString()); setButton(DialogInterface.BUTTON_POSITIVE, "Force Close", mHandler.obtainMessage(1, app)); setTitle("Waiting For Debugger"); - getWindow().setTitle("Waiting For Debugger: " + app.info.processName); + WindowManager.LayoutParams attrs = getWindow().getAttributes(); + attrs.setTitle("Waiting For Debugger: " + app.info.processName); + getWindow().setAttributes(attrs); } public void onStop() { diff --git a/services/java/com/android/server/am/BaseErrorDialog.java b/services/java/com/android/server/am/BaseErrorDialog.java index d1e89bc..6ede8f8 100644 --- a/services/java/com/android/server/am/BaseErrorDialog.java +++ b/services/java/com/android/server/am/BaseErrorDialog.java @@ -33,7 +33,9 @@ class BaseErrorDialog extends AlertDialog { getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); - getWindow().setTitle("Error Dialog"); + WindowManager.LayoutParams attrs = getWindow().getAttributes(); + attrs.setTitle("Error Dialog"); + getWindow().setAttributes(attrs); setIconAttribute(R.attr.alertDialogIcon); } diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java index 9f27994..95c22ec 100644 --- a/services/java/com/android/server/am/BroadcastQueue.java +++ b/services/java/com/android/server/am/BroadcastQueue.java @@ -151,7 +151,7 @@ public class BroadcastQueue { @Override public void run() { - mService.appNotResponding(mApp, null, null, mAnnotation); + mService.appNotResponding(mApp, null, null, false, mAnnotation); } } diff --git a/services/java/com/android/server/am/FactoryErrorDialog.java b/services/java/com/android/server/am/FactoryErrorDialog.java index b19bb5c..0ffb588 100644 --- a/services/java/com/android/server/am/FactoryErrorDialog.java +++ b/services/java/com/android/server/am/FactoryErrorDialog.java @@ -20,6 +20,7 @@ import android.content.Context; import android.content.DialogInterface; import android.os.Handler; import android.os.Message; +import android.view.WindowManager; class FactoryErrorDialog extends BaseErrorDialog { public FactoryErrorDialog(Context context, CharSequence msg) { @@ -30,7 +31,9 @@ class FactoryErrorDialog extends BaseErrorDialog { setButton(DialogInterface.BUTTON_POSITIVE, context.getText(com.android.internal.R.string.factorytest_reboot), mHandler.obtainMessage(0)); - getWindow().setTitle("Factory Error"); + WindowManager.LayoutParams attrs = getWindow().getAttributes(); + attrs.setTitle("Factory Error"); + getWindow().setAttributes(attrs); } public void onStop() { diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java index 652fdb5..7fbab04 100644 --- a/services/java/com/android/server/am/ProcessRecord.java +++ b/services/java/com/android/server/am/ProcessRecord.java @@ -407,7 +407,7 @@ class ProcessRecord { sb.append('u'); sb.append(userId); sb.append('a'); - sb.append(info.uid%Process.FIRST_APPLICATION_UID); + sb.append(UserHandle.getAppId(info.uid)); if (uid != info.uid) { sb.append('i'); sb.append(UserHandle.getAppId(uid) - Process.FIRST_ISOLATED_UID); diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java index 61310ca..d966001 100644 --- a/services/java/com/android/server/wm/InputMonitor.java +++ b/services/java/com/android/server/wm/InputMonitor.java @@ -21,6 +21,7 @@ import com.android.server.input.InputApplicationHandle; import com.android.server.input.InputWindowHandle; import com.android.server.wm.WindowManagerService.AllWindowsIterator; +import android.app.ActivityManagerNative; import android.graphics.Rect; import android.os.RemoteException; import android.util.Log; @@ -89,8 +90,9 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { public long notifyANR(InputApplicationHandle inputApplicationHandle, InputWindowHandle inputWindowHandle) { AppWindowToken appWindowToken = null; + WindowState windowState = null; + boolean aboveSystem = false; synchronized (mService.mWindowMap) { - WindowState windowState = null; if (inputWindowHandle != null) { windowState = (WindowState) inputWindowHandle.windowState; if (windowState != null) { @@ -104,6 +106,12 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { if (windowState != null) { Slog.i(WindowManagerService.TAG, "Input event dispatching timed out " + "sending to " + windowState.mAttrs.getTitle()); + // Figure out whether this window is layered above system windows. + // We need to do this here to help the activity manager know how to + // layer its ANR dialog. + int systemAlertLayer = mService.mPolicy.windowTypeToLayerLw( + WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); + aboveSystem = windowState.mBaseLayer > systemAlertLayer; } else if (appWindowToken != null) { Slog.i(WindowManagerService.TAG, "Input event dispatching timed out " + "sending to application " + appWindowToken.stringName); @@ -126,6 +134,19 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { } } catch (RemoteException ex) { } + } else if (windowState != null) { + try { + // Notify the activity manager about the timeout and let it decide whether + // to abort dispatching or keep waiting. + long timeout = ActivityManagerNative.getDefault().inputDispatchingTimedOut( + windowState.mSession.mPid, aboveSystem); + if (timeout >= 0) { + // The activity manager declined to abort dispatching. + // Wait a bit longer and timeout again later. + return timeout; + } + } catch (RemoteException ex) { + } } return 0; // abort dispatching } diff --git a/services/java/com/android/server/wm/Session.java b/services/java/com/android/server/wm/Session.java index d84a52b..3b4c1ab 100644 --- a/services/java/com/android/server/wm/Session.java +++ b/services/java/com/android/server/wm/Session.java @@ -30,8 +30,10 @@ import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.Parcel; +import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.UserHandle; import android.util.Slog; import android.view.Display; import android.view.IWindow; @@ -69,8 +71,17 @@ final class Session extends IWindowSession.Stub StringBuilder sb = new StringBuilder(); sb.append("Session{"); sb.append(Integer.toHexString(System.identityHashCode(this))); - sb.append(" uid "); - sb.append(mUid); + sb.append(" "); + sb.append(mPid); + if (mUid < Process.FIRST_APPLICATION_UID) { + sb.append(":"); + sb.append(mUid); + } else { + sb.append(":u"); + sb.append(UserHandle.getUserId(mUid)); + sb.append('a'); + sb.append(UserHandle.getAppId(mUid)); + } sb.append("}"); mStringName = sb.toString(); diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java index 9963d14..d23448b 100644 --- a/services/java/com/android/server/wm/WindowState.java +++ b/services/java/com/android/server/wm/WindowState.java @@ -1219,7 +1219,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { mLastTitle = mAttrs.getTitle(); mWasPaused = mToken.paused; mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this)) - + " " + mLastTitle + " paused=" + mWasPaused + "}"; + + " u" + UserHandle.getUserId(mSession.mUid) + + " " + mLastTitle + (mWasPaused ? " PAUSED}" : "}"); } return mStringNameCache; } |
