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

Commit a0fa966a authored by Vadim Caen's avatar Vadim Caen
Browse files

Fixed rotation: home and recents animation

Add support for home and recents animations using the fixed
orientation transform.

When the recent animation is started, the target ActivityRecord is
rotated before being displayed.

Bug: 143053092, 146416687, 147469164
Test: atest WmTests:RecentsAnimationControllerTest
                #testRecentViewInFixedPortraitWhenTopAppInLandscape

Change-Id: I194673d621e8c0e8222306915a60f69e4de53b75
parent 1ad9e57d
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.
     *
+8 −0
Original line number Diff line number Diff line
@@ -423,6 +423,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 +700,9 @@ public class RecentsAnimationController implements DeathRecipient {
                mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(
                        mTargetActivityRecord.token);
            }
            if (mTargetActivityRecord.hasFixedRotationTransform()) {
                mTargetActivityRecord.clearFixedRotationTransform();
            }
        }

        // Notify that the animation has ended
+40 −0
Original line number Diff line number Diff line
@@ -53,6 +53,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;
@@ -330,6 +332,44 @@ 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);
    }

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