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

Commit 91619830 authored by Vadim Caen's avatar Vadim Caen Committed by Android (Google) Code Review
Browse files

Merge changes I244b3cb8,I194673d6

* changes:
  Fixed rotation: rotate wallpaper
  Fixed rotation: home and recents animation
parents 6ed0e8c2 2a9ccc9d
Loading
Loading
Loading
Loading
+17 −4
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.android.server.wm;

import static android.app.ActivityTaskManager.INVALID_STACK_ID;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
@@ -84,9 +83,6 @@ import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
import static android.view.WindowManager.TRANSIT_TASK_OPEN;
import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;

import static com.android.server.wm.DisplayContentProto.FOCUSED_ROOT_TASK_ID;
import static com.android.server.wm.DisplayContentProto.RESUMED_ACTIVITY;
import static com.android.server.wm.DisplayContentProto.SINGLE_TASK_INSTANCE;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
@@ -105,12 +101,15 @@ import static com.android.server.wm.DisplayContentProto.DISPLAY_INFO;
import static com.android.server.wm.DisplayContentProto.DOCKED_STACK_DIVIDER_CONTROLLER;
import static com.android.server.wm.DisplayContentProto.DPI;
import static com.android.server.wm.DisplayContentProto.FOCUSED_APP;
import static com.android.server.wm.DisplayContentProto.FOCUSED_ROOT_TASK_ID;
import static com.android.server.wm.DisplayContentProto.ID;
import static com.android.server.wm.DisplayContentProto.OPENING_APPS;
import static com.android.server.wm.DisplayContentProto.OVERLAY_WINDOWS;
import static com.android.server.wm.DisplayContentProto.RESUMED_ACTIVITY;
import static com.android.server.wm.DisplayContentProto.ROOT_DISPLAY_AREA;
import static com.android.server.wm.DisplayContentProto.ROTATION;
import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION;
import static com.android.server.wm.DisplayContentProto.SINGLE_TASK_INSTANCE;
import static com.android.server.wm.DisplayContentProto.TASKS;
import static com.android.server.wm.DisplayContentProto.WINDOW_CONTAINER;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
@@ -1552,6 +1551,20 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        token.applyFixedRotationTransform(info, displayFrames, mTmpConfiguration);
    }

    /**
     * If the provided {@link ActivityRecord} can be displayed in an orientation different from the
     * display's, it will be rotated to match its requested orientation.
     *
     * @see #rotationForActivityInDifferentOrientation(ActivityRecord).
     * @see WindowToken#applyFixedRotationTransform(DisplayInfo, DisplayFrames, Configuration)
     */
    void rotateInDifferentOrientationIfNeeded(ActivityRecord activityRecord) {
        int rotation = rotationForActivityInDifferentOrientation(activityRecord);
        if (rotation != NO_ROTATION) {
            startFixedRotationTransform(activityRecord, rotation);
        }
    }

    /**
     * Update rotation of the display.
     *
+22 −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;
@@ -423,6 +424,11 @@ public class RecentsAnimationController implements DeathRecipient {

        mService.mWindowPlacerLocked.performSurfacePlacement();

        // If the target activity has a fixed orientation which is different from the current top
        // activity, it will be rotated before being shown so we avoid a screen rotation
        // animation when showing the Recents view.
        mDisplayContent.rotateInDifferentOrientationIfNeeded(mTargetActivityRecord);

        // Notify that the animation has started
        if (mStatusBar != null) {
            mStatusBar.onRecentsAnimationStateChanged(true /* running */);
@@ -695,6 +701,9 @@ public class RecentsAnimationController implements DeathRecipient {
                mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(
                        mTargetActivityRecord.token);
            }
            if (mTargetActivityRecord.hasFixedRotationTransform()) {
                mTargetActivityRecord.clearFixedRotationTransform();
            }
        }

        // Notify that the animation has ended
@@ -828,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) {
+109 −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;
@@ -53,6 +55,8 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;

import android.app.ActivityManager.TaskSnapshot;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.os.Binder;
import android.os.IBinder;
import android.os.IInterface;
@@ -65,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
@@ -330,6 +338,107 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
        assertTrue(activity.shouldAnimate(TRANSIT_ACTIVITY_CLOSE));
    }

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

        final ActivityStack homeStack = mDisplayContent.getOrCreateStack(
                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
        final ActivityRecord homeAppWindow =
                new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
                        .setStack(homeStack)
                        .setCreateTask(true)
                        .build();
        final ActivityRecord appWindow = createActivityRecord(mDisplayContent,
                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
        final WindowState win0 = createWindow(null, TYPE_BASE_APPLICATION, appWindow, "win1");
        appWindow.addWindow(win0);

        final ActivityRecord landActivity = createActivityRecord(mDisplayContent,
                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
        landActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, landActivity, "win1");
        landActivity.addWindow(win1);

        assertEquals(landActivity.getTask().getTopVisibleActivity(), landActivity);
        assertEquals(landActivity.findMainWindow(), win1);

        // Ensure that the display is in Landscape
        landActivity.onDescendantOrientationChanged(landActivity.token, landActivity);
        assertEquals(Configuration.ORIENTATION_LANDSCAPE,
                mDisplayContent.getConfiguration().orientation);

        mController.initialize(ACTIVITY_TYPE_HOME, new SparseBooleanArray(), homeAppWindow);

        // Check that the home app is in portrait
        assertEquals(Configuration.ORIENTATION_PORTRAIT,
                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);