diff options
3 files changed, 58 insertions, 35 deletions
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index f18f2369f133..257d79d2c153 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -1641,7 +1641,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D final Configuration config = mWindowManager.updateOrientationFromAppTokens( getDisplayOverrideConfiguration(displayId), r != null && r.mayFreezeScreenLocked(r.app) ? r.appToken : null, - displayId); + displayId, true /* forceUpdate */); if (r != null && markFrozenIfConfigChanged && config != null) { r.frozenBeforeDestroy = true; } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index f3423c63e270..b59e728a721e 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -944,33 +944,50 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo /** * Update rotation of the display. * - * Returns true if the rotation has been changed. In this case YOU MUST CALL - * {@link WindowManagerService#sendNewConfiguration(int)} TO UNFREEZE THE SCREEN. + * @return {@code true} if the rotation has been changed. In this case YOU MUST CALL + * {@link WindowManagerService#sendNewConfiguration(int)} TO UNFREEZE THE SCREEN. */ boolean updateRotationUnchecked() { - if (mService.mDeferredRotationPauseCount > 0) { - // Rotation updates have been paused temporarily. Defer the update until - // updates have been resumed. - if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, rotation is paused."); - return false; - } + return updateRotationUnchecked(false /* forceUpdate */); + } - ScreenRotationAnimation screenRotationAnimation = - mService.mAnimator.getScreenRotationAnimationLocked(mDisplayId); - if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { - // Rotation updates cannot be performed while the previous rotation change - // animation is still in progress. Skip this update. We will try updating - // again after the animation is finished and the display is unfrozen. - if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, animation in progress."); - return false; - } - if (mService.mDisplayFrozen) { - // Even if the screen rotation animation has finished (e.g. isAnimating - // returns false), there is still some time where we haven't yet unfrozen - // the display. We also need to abort rotation here. - if (DEBUG_ORIENTATION) Slog.v(TAG_WM, - "Deferring rotation, still finishing previous rotation"); - return false; + /** + * Update rotation of the display with an option to force the update. + * @param forceUpdate Force the rotation update. Sometimes in WM we might skip updating + * orientation because we're waiting for some rotation to finish or display + * to unfreeze, which results in configuration of the previously visible + * activity being applied to a newly visible one. Forcing the rotation + * update allows to workaround this issue. + * @return {@code true} if the rotation has been changed. In this case YOU MUST CALL + * {@link WindowManagerService#sendNewConfiguration(int)} TO UNFREEZE THE SCREEN. + */ + boolean updateRotationUnchecked(boolean forceUpdate) { + ScreenRotationAnimation screenRotationAnimation; + if (!forceUpdate) { + if (mService.mDeferredRotationPauseCount > 0) { + // Rotation updates have been paused temporarily. Defer the update until + // updates have been resumed. + if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, rotation is paused."); + return false; + } + + screenRotationAnimation = + mService.mAnimator.getScreenRotationAnimationLocked(mDisplayId); + if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { + // Rotation updates cannot be performed while the previous rotation change + // animation is still in progress. Skip this update. We will try updating + // again after the animation is finished and the display is unfrozen. + if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, animation in progress."); + return false; + } + if (mService.mDisplayFrozen) { + // Even if the screen rotation animation has finished (e.g. isAnimating + // returns false), there is still some time where we haven't yet unfrozen + // the display. We also need to abort rotation here. + if (DEBUG_ORIENTATION) Slog.v(TAG_WM, + "Deferring rotation, still finishing previous rotation"); + return false; + } } if (!mService.mDisplayEnabled) { @@ -992,7 +1009,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo if (mayRotateSeamlessly) { final WindowState seamlessRotated = getWindow((w) -> w.mSeamlesslyRotated); - if (seamlessRotated != null) { + if (seamlessRotated != null && !forceUpdate) { // We can't rotate (seamlessly or not) while waiting for the last seamless rotation // to complete (that is, waiting for windows to redraw). It's tempting to check // w.mSeamlessRotationCount but that could be incorrect in the case of diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index f42f855e7ac5..9c253fb949e1 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2372,6 +2372,12 @@ public class WindowManagerService extends IWindowManager.Stub @Override public Configuration updateOrientationFromAppTokens(Configuration currentConfig, IBinder freezeThisOneIfNeeded, int displayId) { + return updateOrientationFromAppTokens(currentConfig, freezeThisOneIfNeeded, displayId, + false /* forceUpdate */); + } + + public Configuration updateOrientationFromAppTokens(Configuration currentConfig, + IBinder freezeThisOneIfNeeded, int displayId, boolean forceUpdate) { if (!checkCallingPermission(MANAGE_APP_TOKENS, "updateOrientationFromAppTokens()")) { throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); } @@ -2381,7 +2387,7 @@ public class WindowManagerService extends IWindowManager.Stub try { synchronized(mWindowMap) { config = updateOrientationFromAppTokensLocked(currentConfig, freezeThisOneIfNeeded, - displayId); + displayId, forceUpdate); } } finally { Binder.restoreCallingIdentity(ident); @@ -2391,13 +2397,13 @@ public class WindowManagerService extends IWindowManager.Stub } private Configuration updateOrientationFromAppTokensLocked(Configuration currentConfig, - IBinder freezeThisOneIfNeeded, int displayId) { + IBinder freezeThisOneIfNeeded, int displayId, boolean forceUpdate) { if (!mDisplayReady) { return null; } Configuration config = null; - if (updateOrientationFromAppTokensLocked(displayId)) { + if (updateOrientationFromAppTokensLocked(displayId, forceUpdate)) { // If we changed the orientation but mOrientationChangeComplete is already true, // we used seamless rotation, and we don't need to freeze the screen. if (freezeThisOneIfNeeded != null && !mRoot.mOrientationChangeComplete) { @@ -2445,11 +2451,15 @@ public class WindowManagerService extends IWindowManager.Stub * @see android.view.IWindowManager#updateOrientationFromAppTokens(Configuration, IBinder, int) */ boolean updateOrientationFromAppTokensLocked(int displayId) { + return updateOrientationFromAppTokensLocked(displayId, false /* forceUpdate */); + } + + boolean updateOrientationFromAppTokensLocked(int displayId, boolean forceUpdate) { long ident = Binder.clearCallingIdentity(); try { final DisplayContent dc = mRoot.getDisplayContent(displayId); final int req = dc.getOrientation(); - if (req != dc.getLastOrientation()) { + if (req != dc.getLastOrientation() || forceUpdate) { dc.setLastOrientation(req); //send a message to Policy indicating orientation change to take //action like disabling/enabling sensors etc., @@ -2457,12 +2467,8 @@ public class WindowManagerService extends IWindowManager.Stub if (dc.isDefaultDisplay) { mPolicy.setCurrentOrientationLw(req); } - if (dc.updateRotationUnchecked()) { - // changed - return true; - } + return dc.updateRotationUnchecked(forceUpdate); } - return false; } finally { Binder.restoreCallingIdentity(ident); |