Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c90c4a54 authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Only rotate seamlessly if the app window fills its parent

e.g. An activity with fixed aspect ratio:
----------
|        |    -----------------
|        |    || |          | |
|Activity| -> || | Activity | |
|        |    || |          | |
|________|    || |          | |
|  Lbox  |    -----------------
==========   <^              ^ Letterbox
              Navigation bar

The relative position is changed after rotation, so it may
look like a sudden jump when rotating seamlessly.

Bug: 112288258
Test: atest DisplayPolicyTests#testShouldRotateSeamlessly
Change-Id: I520534e11b35e3d570bc7f65198bc3cc3c82aac1
parent ddc0fa51
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -3271,7 +3271,12 @@ public class DisplayPolicy {
        }

        final WindowState w = mTopFullscreenOpaqueWindowState;
        if (w != mFocusedWindow) {
        if (w == null || w != mFocusedWindow) {
            return false;
        }
        // If the bounds of activity window is different from its parent, then reject to be seamless
        // because the window position may change after rotation that will look like a sudden jump.
        if (w.mAppToken != null && !w.mAppToken.matchParentBounds()) {
            return false;
        }

@@ -3279,8 +3284,7 @@ public class DisplayPolicy {
        // it and is in the fullscreen opaque state. Seamless rotation
        // requires freezing various Surface states and won't work well
        // with animations, so we disable it in the animation case for now.
        if (w != null && !w.isAnimatingLw()
                && w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS) {
        if (!w.isAnimatingLw() && w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS) {
            return true;
        }
        return false;
+36 −0
Original line number Diff line number Diff line
@@ -25,20 +25,27 @@ import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACK
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM;
import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_RIGHT;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

import android.graphics.PixelFormat;
import android.platform.test.annotations.Presubmit;
import android.view.Surface;
import android.view.WindowManager;

import androidx.test.filters.SmallTest;
@@ -196,4 +203,33 @@ public class DisplayPolicyTests extends WindowTestsBase {
                DisplayPolicy.updateLightNavigationBarLw(0, opaqueDarkNavBar,
                        opaqueDarkNavBar, imeDrawLightNavBar, imeDrawLightNavBar));
    }

    @Test
    public void testShouldRotateSeamlessly() {
        final DisplayPolicy policy = mDisplayContent.getDisplayPolicy();
        final WindowManager.LayoutParams attrs = mAppWindow.mAttrs;
        attrs.x = attrs.y = 0;
        attrs.height = attrs.width = WindowManager.LayoutParams.MATCH_PARENT;
        attrs.rotationAnimation = ROTATION_ANIMATION_SEAMLESS;
        final DisplayRotation displayRotation = mock(DisplayRotation.class);
        doReturn(Surface.ROTATION_180).when(displayRotation).getUpsideDownRotation();

        synchronized (mWm.mGlobalLock) {
            policy.focusChangedLw(null /* lastFocus */, mAppWindow);
            policy.applyPostLayoutPolicyLw(
                    mAppWindow, attrs, null /* attached */, null /* imeTarget */);
            spyOn(policy);
            doReturn(true).when(policy).navigationBarCanMove();
            // The focused fullscreen opaque window without override bounds should be able to be
            // rotated seamlessly.
            assertTrue(policy.shouldRotateSeamlessly(
                    displayRotation, Surface.ROTATION_0, Surface.ROTATION_90));

            spyOn(mAppWindow.mAppToken);
            doReturn(false).when(mAppWindow.mAppToken).matchParentBounds();
            // No seamless rotation if the window may be positioned with offset after rotation.
            assertFalse(policy.shouldRotateSeamlessly(
                    displayRotation, Surface.ROTATION_0, Surface.ROTATION_90));
        }
    }
}