From b696aee7b30487feaf6188675a3f01e13ac65a13 Mon Sep 17 00:00:00 2001 From: Christopher Tate Date: Fri, 2 Apr 2010 19:08:30 -0700 Subject: [PATCH] Fix "incall in landscape sometimes" bug #2523942 The problem turns out to have been a deep weirdness in the way that keyguard and incall interact. Incall gets relaunched when the keyboard is opened/closed, which transiently exposes keyguard with its nosensor orientation demands, and that plus the long keyguard-hide animation was leaving incall in a bad state from which the window manager didn't try to recover. We now disregard animating-towards-hidden windows [i.e. keyguard] when running through the app tokens to determine what orientation should be, and do not do configuration calculations at all while the display is frozen. There can still be a transient state in which incall is drawn in landscape, but things proceed from there to relaunch it back into the proper portrait orientation, and it ends up in the right state in the end. Change-Id: I0d74ee19064b6d7f65600976f1b5b16b7ec36f31 --- .../android/server/WindowManagerService.java | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index a1a8bf27e65c2..cd6a13102be38 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -367,6 +367,8 @@ public class WindowManagerService extends IWindowManager.Stub boolean mSafeMode; boolean mDisplayEnabled = false; boolean mSystemBooted = false; + int mInitialDisplayWidth = 0; + int mInitialDisplayHeight = 0; int mRotation = 0; int mRequestedRotation = 0; int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; @@ -1842,6 +1844,8 @@ public class WindowManagerService extends IWindowManager.Stub if (mDisplay == null) { WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); mDisplay = wm.getDefaultDisplay(); + mInitialDisplayWidth = mDisplay.getWidth(); + mInitialDisplayHeight = mDisplay.getHeight(); mQueue.setDisplay(mDisplay); reportNewConfig = true; } @@ -3025,7 +3029,7 @@ public class WindowManagerService extends IWindowManager.Stub // app window. No point in continuing further. return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; } - if (!wtoken.isVisibleLw()) { + if (!wtoken.isVisibleLw() || !wtoken.mPolicyVisibilityAfterAnim) { continue; } int req = wtoken.mAttrs.screenOrientation; @@ -3154,6 +3158,15 @@ public class WindowManagerService extends IWindowManager.Stub * android.os.IBinder) */ boolean updateOrientationFromAppTokensLocked() { + if (mDisplayFrozen) { + // If the display is frozen, some activities may be in the middle + // of restarting, and thus have removed their old window. If the + // window has the flag to hide the lock screen, then the lock screen + // can re-appear and inflict its own orientation on us. Keep the + // orientation stable until this all settles down. + return false; + } + boolean changed = false; long ident = Binder.clearCallingIdentity(); try { @@ -4843,8 +4856,13 @@ public class WindowManagerService extends IWindowManager.Stub return false; } mQueue.getInputConfiguration(config); - final int dw = mDisplay.getWidth(); - final int dh = mDisplay.getHeight(); + + // Use the effective "visual" dimensions based on current rotation + final boolean rotated = (mRotation == Surface.ROTATION_90 + || mRotation == Surface.ROTATION_270); + final int dw = rotated ? mInitialDisplayHeight : mInitialDisplayWidth; + final int dh = rotated ? mInitialDisplayWidth : mInitialDisplayHeight; + int orientation = Configuration.ORIENTATION_SQUARE; if (dw < dh) { orientation = Configuration.ORIENTATION_PORTRAIT; @@ -10998,6 +11016,14 @@ public class WindowManagerService extends IWindowManager.Stub mKeyWaiter.notifyAll(); } + // While the display is frozen we don't re-compute the orientation + // to avoid inconsistent states. However, something interesting + // could have actually changed during that time so re-evaluate it + // now to catch that. + if (updateOrientationFromAppTokensLocked()) { + mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); + } + // A little kludge: a lot could have happened while the // display was frozen, so now that we are coming back we // do a gc so that any remote references the system