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

Commit 819e1209 authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Allow to replace fixed rotation state

Assume there are 2 activities with different fixed rotation states
A and B. And wallpaper was associated with A. When the wallpaper
target is changed to B, wallpaper should be able to change the
association to B so their rotation transform can be updated at the
same time. This also avoids that if the previous associated token
is somehow inactive, wallpaper won't in a dangling rotated state.

Also add a check of updating rotated launching app for the case:
launching a portrait app from a landscape app and trigger recents
animation immediately before the animation of portrait app is done.
And then finish recents animation by keeping the portrait app as
the top activity. The expected result should be that the display is
rotated from landscape to portrait seamlessly. But if the recents
activity is set to the rotated launching app, the display rotation
will be unable to update because when receiving animation done of
the portrait app, the recents animation is still active that skips
the rotation change. Then the portrait app will be updated to
landscape temporally.

Fixes: 161056612
Test: atest WindowTokenTests#testFinishFixedRotationTransform
Change-Id: Ic134c4326db836e35385f290f996f0d841da693d
parent b511a73d
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -1557,7 +1557,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
            // the heavy operations. This also benefits that the states of multiple activities
            // are handled together.
            r.linkFixedRotationTransform(prevRotatedLaunchingApp);
            if (r != mFixedRotationTransitionListener.mAnimatingRecents) {
                // Only update the record for normal activity so the display orientation can be
                // updated when the transition is done if it becomes the top. And the case of
                // recents can be handled when the recents animation is finished.
                setFixedRotationLaunchingAppUnchecked(r, rotation);
            }
            return;
        }

+13 −7
Original line number Diff line number Diff line
@@ -548,7 +548,7 @@ class WindowToken extends WindowContainer<WindowState> {
    void applyFixedRotationTransform(DisplayInfo info, DisplayFrames displayFrames,
            Configuration config) {
        if (mFixedRotationTransformState != null) {
            return;
            cleanUpFixedRotationTransformState(true /* replacing */);
        }
        mFixedRotationTransformState = new FixedRotationTransformState(info, displayFrames,
                new Configuration(config), mDisplayContent.getRotation());
@@ -565,13 +565,13 @@ class WindowToken extends WindowContainer<WindowState> {
     * one. This takes the same effect as {@link #applyFixedRotationTransform}.
     */
    void linkFixedRotationTransform(WindowToken other) {
        if (mFixedRotationTransformState != null) {
            return;
        }
        final FixedRotationTransformState fixedRotationState = other.mFixedRotationTransformState;
        if (fixedRotationState == null) {
        if (fixedRotationState == null || mFixedRotationTransformState == fixedRotationState) {
            return;
        }
        if (mFixedRotationTransformState != null) {
            cleanUpFixedRotationTransformState(true /* replacing */);
        }
        mFixedRotationTransformState = fixedRotationState;
        fixedRotationState.mAssociatedTokens.add(this);
        onConfigurationChanged(getParent().getConfiguration());
@@ -626,11 +626,17 @@ class WindowToken extends WindowContainer<WindowState> {
        // The state is cleared at the end, because it is used to indicate that other windows can
        // use seamless rotation when applying rotation to display.
        for (int i = state.mAssociatedTokens.size() - 1; i >= 0; i--) {
            state.mAssociatedTokens.get(i).cleanUpFixedRotationTransformState();
            state.mAssociatedTokens.get(i).cleanUpFixedRotationTransformState(
                    false /* replacing */);
        }
    }

    private void cleanUpFixedRotationTransformState() {
    private void cleanUpFixedRotationTransformState(boolean replacing) {
        if (replacing && mFixedRotationTransformState.mAssociatedTokens.size() > 1) {
            // The state is not only used by self. Make sure to leave the influence by others.
            mFixedRotationTransformState.mAssociatedTokens.remove(this);
            mFixedRotationTransformState.mRotatedContainers.remove(this);
        }
        mFixedRotationTransformState = null;
        notifyFixedRotationTransform(false /* enabled */);
    }
+24 −12
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -145,29 +146,40 @@ public class WindowTokenTests extends WindowTestsBase {
        assertEquals(0, token.getWindowsCount());
    }

    @UseTestDisplay(addWindows = { W_ACTIVITY, W_WALLPAPER })
    @Test
    public void testFinishFixedRotationTransform() {
        final WindowToken appToken = mAppWindow.mToken;
        final WindowToken wallpaperToken = mWallpaperWindow.mToken;
        final WindowToken[] tokens = new WindowToken[3];
        for (int i = 0; i < tokens.length; i++) {
            tokens[i] = createTestWindowToken(TYPE_APPLICATION_OVERLAY, mDisplayContent);
        }

        final Configuration config = new Configuration(mDisplayContent.getConfiguration());
        final int originalRotation = config.windowConfiguration.getRotation();
        final int targetRotation = (originalRotation + 1) % 4;

        config.windowConfiguration.setRotation(targetRotation);
        appToken.applyFixedRotationTransform(mDisplayInfo, mDisplayContent.mDisplayFrames, config);
        wallpaperToken.linkFixedRotationTransform(appToken);
        tokens[0].applyFixedRotationTransform(mDisplayInfo, mDisplayContent.mDisplayFrames, config);
        tokens[1].linkFixedRotationTransform(tokens[0]);

        // The window tokens should apply the rotation by the transformation.
        assertEquals(targetRotation, appToken.getWindowConfiguration().getRotation());
        assertEquals(targetRotation, wallpaperToken.getWindowConfiguration().getRotation());
        assertEquals(targetRotation, tokens[0].getWindowConfiguration().getRotation());
        assertEquals(targetRotation, tokens[1].getWindowConfiguration().getRotation());

        tokens[2].applyFixedRotationTransform(mDisplayInfo, mDisplayContent.mDisplayFrames, config);
        // The tokens[1] was linked to tokens[0], this should make tokens[1] link to tokens[2].
        tokens[1].linkFixedRotationTransform(tokens[2]);

        // Assume the display doesn't rotate, the transformation will be canceled.
        tokens[0].finishFixedRotationTransform();

        // The display doesn't rotate, the transformation will be canceled.
        mAppWindow.mToken.finishFixedRotationTransform();
        // The tokens[0] should restore to the original rotation.
        assertEquals(originalRotation, tokens[0].getWindowConfiguration().getRotation());
        // The tokens[1] is linked to tokens[2], it should keep the target rotation.
        assertNotEquals(originalRotation, tokens[1].getWindowConfiguration().getRotation());

        // The window tokens should restore to the original rotation.
        assertEquals(originalRotation, appToken.getWindowConfiguration().getRotation());
        assertEquals(originalRotation, wallpaperToken.getWindowConfiguration().getRotation());
        tokens[2].finishFixedRotationTransform();
        // The rotation of tokens[1] should be restored because its linked state is finished.
        assertEquals(originalRotation, tokens[1].getWindowConfiguration().getRotation());
    }

    /**