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

Commit 2a9ccc9d authored by Vadim Caen's avatar Vadim Caen
Browse files

Fixed rotation: rotate wallpaper

The wallpaper should be rotated if its target WindowState is rotated.

The fixed rotation is applied to the WallpaperWindowToken and
the offsets are computed using the overriden DisplayInfo contained in
the WindowToken.ForcedRotationState.

Test: atest WmTests:RecentsAnimationControllerTest#testWallpaperHasFixedRotationApplied
Bug: 143053092, 148000485, 147999946
Change-Id: I244b3cb81dd29995a1a9181949e4f3f973816825
parent a0fa966a
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
import static com.android.server.wm.WindowManagerInternal.AppTransitionListener;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.app.ActivityManager.TaskSnapshot;
import android.app.WindowConfiguration;
import android.graphics.Point;
@@ -836,6 +837,19 @@ public class RecentsAnimationController implements DeathRecipient {
        return task != null && isAnimatingTask(task) && !isTargetApp(windowState.mActivityRecord);
    }

    /**
     * If the animation target ActivityRecord has a fixed rotation ({@link
     * WindowToken#hasFixedRotationTransform()}, the provided wallpaper will be rotated accordingly.
     *
     * This avoids any screen rotation animation when animating to the Recents view.
     */
    void applyFixedRotationTransformIfNeeded(@NonNull WindowToken wallpaper) {
        if (mTargetActivityRecord == null) {
            return;
        }
        wallpaper.applyFixedRotationTransform(mTargetActivityRecord);
    }

    @VisibleForTesting
    class TaskAnimationAdapter implements AnimationAdapter {

+29 −2
Original line number Diff line number Diff line
@@ -122,10 +122,37 @@ class WallpaperWindowToken extends WindowToken {
            mDisplayContent.setLayoutNeeded();
        }

        final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
        final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;

        if (visible) {
            final WindowState wallpaperTarget = wallpaperController.getWallpaperTarget();
            final RecentsAnimationController recentsAnimationController =
                    mWmService.getRecentsAnimationController();
            if (wallpaperTarget != null
                    && recentsAnimationController != null
                    && recentsAnimationController.isAnimatingTask(wallpaperTarget.getTask())) {
                // If the Recents animation is running, and the wallpaper target is the animating
                // task we want the wallpaper to be rotated in the same orientation as the
                // RecentsAnimation's target (e.g the launcher)
                recentsAnimationController.applyFixedRotationTransformIfNeeded(this);
            } else if (wallpaperTarget != null
                    && wallpaperTarget.mToken.hasFixedRotationTransform()) {
                // If the wallpaper target has a fixed rotation, we want the wallpaper to follow its
                // rotation
                applyFixedRotationTransform(wallpaperTarget.mToken);
            } else if (hasFixedRotationTransform()) {
                clearFixedRotationTransform();
            }
        }

        DisplayInfo displayInfo = getFixedRotationTransformDisplayInfo();
        if (displayInfo == null) {
            displayInfo = mDisplayContent.getDisplayInfo();
        }

        final int dw = displayInfo.logicalWidth;
        final int dh = displayInfo.logicalHeight;
        final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;

        for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
            final WindowState wallpaper = mChildren.get(wallpaperNdx);

+13 −0
Original line number Diff line number Diff line
@@ -377,6 +377,19 @@ class WindowToken extends WindowContainer<WindowState> {
        onConfigurationChanged(getParent().getConfiguration());
    }

    /**
     * Copies the {@link FixedRotationTransformState} (if any) from the other WindowToken to this
     * one.
     */
    void applyFixedRotationTransform(WindowToken other) {
        final FixedRotationTransformState fixedRotationState = other.mFixedRotationTransformState;
        if (fixedRotationState != null) {
            applyFixedRotationTransform(fixedRotationState.mDisplayInfo,
                    fixedRotationState.mDisplayFrames,
                    fixedRotationState.mRotatedOverrideConfiguration);
        }
    }

    /** Clears the transformation and continue updating the orientation change of display. */
    void clearFixedRotationTransform() {
        if (mFixedRotationTransformState == null) {
+69 −0
Original line number Diff line number Diff line
@@ -20,7 +20,9 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.atLeast;
@@ -67,12 +69,16 @@ import androidx.test.filters.SmallTest;

import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;

import com.google.common.truth.Truth;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.ArrayList;

/**
 * Build/Install/Run:
 *  atest WmTests:RecentsAnimationControllerTest
@@ -370,6 +376,69 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
                homeAppWindow.getConfiguration().orientation);
    }

    @Test
    public void testWallpaperHasFixedRotationApplied() {
        mWm.mIsFixedRotationTransformEnabled = true;
        mWm.setRecentsAnimationController(mController);

        // Create a portrait home stack, a wallpaper and a landscape application displayed on top.

        // Home stack
        final ActivityStack homeStack = mDisplayContent.getOrCreateStack(
                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
        final ActivityRecord homeActivity =
                new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
                        .setStack(homeStack)
                        .setCreateTask(true)
                        .build();
        homeActivity.setOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        final WindowState homeWindow = createWindow(null, TYPE_BASE_APPLICATION, homeActivity,
                "homeWindow");
        homeActivity.addWindow(homeWindow);
        homeWindow.getAttrs().flags |= FLAG_SHOW_WALLPAPER;

        // Landscape application
        final ActivityRecord activity = createActivityRecord(mDisplayContent,
                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
        final WindowState applicationWindow = createWindow(null, TYPE_BASE_APPLICATION, activity,
                "applicationWindow");
        activity.addWindow(applicationWindow);
        activity.setOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        // Wallpaper
        final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
                mock(IBinder.class), true, mDisplayContent, true /* ownerCanManageAppTokens */);
        final WindowState wallpaperWindow = createWindow(null, TYPE_WALLPAPER, wallpaperWindowToken,
                "wallpaperWindow");

        // Make sure the landscape activity is on top and the display is in landscape
        activity.moveFocusableActivityToTop("test");
        mDisplayContent.getConfiguration().windowConfiguration.setRotation(
                mDisplayContent.getRotation());


        spyOn(mDisplayContent.mWallpaperController);
        doReturn(true).when(mDisplayContent.mWallpaperController).isWallpaperVisible();

        // Start the recents animation
        mController
                .initialize(ACTIVITY_TYPE_HOME, new SparseBooleanArray(), homeActivity);

        mDisplayContent.mWallpaperController.adjustWallpaperWindows();

        // Check preconditions
        ArrayList<WallpaperWindowToken> wallpapers = new ArrayList<>(1);
        mDisplayContent.forAllWallpaperWindows(wallpapers::add);

        Truth.assertThat(wallpapers).hasSize(1);
        Truth.assertThat(wallpapers.get(0).getTopChild()).isEqualTo(wallpaperWindow);

        // Actual check
        assertEquals(Configuration.ORIENTATION_PORTRAIT,
                wallpapers.get(0).getConfiguration().orientation);
    }

    private static void verifyNoMoreInteractionsExceptAsBinder(IInterface binder) {
        verify(binder, atLeast(0)).asBinder();
        verifyNoMoreInteractions(binder);