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

Commit 885f0613 authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Use parent bounds for fixed rotation activity end bounds

This is similar to what legacy transition did. Activity bounds
may not be the proper region to animate because the letterbox
is also a part of activity. And because fixed rotation applies
to activity level, this doesn't need to let shell to know the
info about fixed rotation, just animate as in the same rotation.

Also
1. Since commit 6dcb756b, inTransition() also includes parent, which
   doesn't match the usage of collectForDisplayChange(), e.g. all
   container under changing display will be in transition. So it
   should only check if itself is collecting, to avoid missing some
   windows that need to be in sync group.
2. The rotation-leash doesn't have color or shadow effect, so it
   can be a simple ContainerLayer.

Bug: 223397500
Test: atest TransitionTests#testTransitionBounds
Test: adb shell setprop persist.wm.debug.shell_transit 1; reboot
      Launch a landscape activity, and it launches a portrait
      activity in new task. The animation should not be cropped.

Change-Id: I9ca872d62ab82fd326d20fc069d76cfd50090cf8
parent 525ddc37
Loading
Loading
Loading
Loading
+19 −4
Original line number Diff line number Diff line
@@ -1316,11 +1316,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
            }
            change.setMode(info.getTransitMode(target));
            change.setStartAbsBounds(info.mAbsoluteBounds);
            change.setEndAbsBounds(target.getBounds());
            change.setEndRelOffset(target.getBounds().left - target.getParent().getBounds().left,
                    target.getBounds().top - target.getParent().getBounds().top);
            change.setFlags(info.getChangeFlags(target));
            change.setRotation(info.mRotation, target.getWindowConfiguration().getRotation());
            final Task task = target.asTask();
            if (task != null) {
                final ActivityManager.RunningTaskInfo tinfo = new ActivityManager.RunningTaskInfo();
@@ -1348,13 +1344,32 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
            } else if ((info.mFlags & ChangeInfo.FLAG_SEAMLESS_ROTATION) != 0) {
                change.setRotationAnimation(ROTATION_ANIMATION_SEAMLESS);
            }

            final WindowContainer<?> parent = target.getParent();
            final Rect bounds = target.getBounds();
            final Rect parentBounds = parent.getBounds();
            change.setEndRelOffset(bounds.left - parentBounds.left,
                    bounds.top - parentBounds.top);
            int endRotation = target.getWindowConfiguration().getRotation();
            final ActivityRecord activityRecord = target.asActivityRecord();
            if (activityRecord != null) {
                final Task arTask = activityRecord.getTask();
                final int backgroundColor = ColorUtils.setAlphaComponent(
                        arTask.getTaskDescription().getBackgroundColor(), 255);
                change.setBackgroundColor(backgroundColor);
                // TODO(b/227427984): Shell needs to aware letterbox.
                // Always use parent bounds of activity because letterbox area (e.g. fixed aspect
                // ratio or size compat mode) should be included in the animation.
                change.setEndAbsBounds(parentBounds);
                if (activityRecord.getRelativeDisplayRotation() != 0
                        && !activityRecord.mTransitionController.useShellTransitionsRotation()) {
                    // Use parent rotation because shell doesn't know the surface is rotated.
                    endRotation = parent.getWindowConfiguration().getRotation();
                }
            } else {
                change.setEndAbsBounds(bounds);
            }
            change.setRotation(info.mRotation, endRotation);

            out.addChange(change);
        }
+1 −1
Original line number Diff line number Diff line
@@ -430,7 +430,7 @@ class TransitionController {
        }, true /* traverseTopToBottom */);
        // Collect all visible non-app windows which need to be drawn before the animation starts.
        dc.forAllWindows(w -> {
            if (w.mActivityRecord == null && w.isVisible() && !inTransition(w.mToken)
            if (w.mActivityRecord == null && w.isVisible() && !isCollecting(w.mToken)
                    && dc.shouldSyncRotationChange(w)) {
                transition.collect(w.mToken);
            }
+0 −1
Original line number Diff line number Diff line
@@ -580,7 +580,6 @@ class WindowToken extends WindowContainer<WindowState> {
                .setParent(getParentSurfaceControl())
                .setName(getSurfaceControl() + " - rotation-leash")
                .setHidden(false)
                .setEffectLayer()
                .setCallsite("WindowToken.getOrCreateFixedRotationLeash")
                .build();
        t.setPosition(leash, mLastSurfacePosition.x, mLastSurfacePosition.y);
+45 −0
Original line number Diff line number Diff line
@@ -53,6 +53,8 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import android.graphics.Point;
import android.graphics.Rect;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
import android.util.ArrayMap;
@@ -73,6 +75,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

/**
 * Build/Install/Run:
@@ -588,6 +591,48 @@ public class TransitionTests extends WindowTestsBase {
        assertTrue(awaitInWmLock(() -> latch.await(3, TimeUnit.SECONDS)));
    }

    @Test
    public void testTransitionBounds() {
        registerTestTransitionPlayer();
        final int offset = 10;
        final Function<WindowContainer<?>, TransitionInfo.Change> test = wc -> {
            final Transition transition = wc.mTransitionController.createTransition(TRANSIT_OPEN);
            transition.collect(wc);
            final int nextRotation = (wc.getWindowConfiguration().getRotation() + 1) % 4;
            wc.getWindowConfiguration().setRotation(nextRotation);
            wc.getWindowConfiguration().setDisplayRotation(nextRotation);
            final Rect bounds = wc.getWindowConfiguration().getBounds();
            // Flip the bounds with offset.
            wc.getWindowConfiguration().setBounds(
                    new Rect(offset, offset, bounds.height(), bounds.width()));
            final int flags = 0;
            final TransitionInfo info = Transition.calculateTransitionInfo(transition.mType, flags,
                    Transition.calculateTargets(transition.mParticipants, transition.mChanges),
                    transition.mChanges);
            transition.abort();
            return info.getChanges().get(0);
        };

        final ActivityRecord app = createActivityRecord(mDisplayContent);
        final TransitionInfo.Change changeOfActivity = test.apply(app);
        // There will be letterbox if the activity bounds don't match parent, so always use its
        // parent bounds for animation.
        assertEquals(app.getParent().getBounds(), changeOfActivity.getEndAbsBounds());
        final int endRotation = app.mTransitionController.useShellTransitionsRotation()
                ? app.getWindowConfiguration().getRotation()
                // Without shell rotation, fixed rotation is done by core so the info should not
                // contain rotation change.
                : app.getParent().getWindowConfiguration().getRotation();
        assertEquals(endRotation, changeOfActivity.getEndRotation());

        // Non-activity target always uses its configuration for end info.
        final Task task = app.getTask();
        final TransitionInfo.Change changeOfTask = test.apply(task);
        assertEquals(task.getBounds(), changeOfTask.getEndAbsBounds());
        assertEquals(new Point(offset, offset), changeOfTask.getEndRelOffset());
        assertEquals(task.getWindowConfiguration().getRotation(), changeOfTask.getEndRotation());
    }

    @Test
    public void testDisplayRotationChange() {
        final Task task = createActivityRecord(mDisplayContent).getTask();