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

Commit 570b2eb4 authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Use rotation transition to handle display config change

1. Support fade animation with rotation delta 0.
   Rotation animation is also used to cover display configuration
   change, e.g. density, font size.
2. Use normal rotation animation when app requests orientation,
   e.g. from Activity#setRequestedOrientation.
3. Fix flickering of rotation animation
   The layers are:
     Transition Root
       - Animation leash
         - RotationLayer
       - Windowing layer
   So the higher layer should be leash instead of RotationLayer.

Bug: 199836343
Test: ShellTransitionTests
Test: setprop persist.debug.shell_transit 1; reboot
      Change font size in Settings, there should be a fade
      out animation for transiting to new configuration.
      Toggle portrait and landscape from app without specifying
      rotation animation type, seamless rotation should not
      be used.

Change-Id: I7ec9553cc8df2b98f89b6fbda67c3834d018883b
parent 9fbadb5a
Loading
Loading
Loading
Loading
+9 −4
Original line number Diff line number Diff line
@@ -141,8 +141,9 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
    static boolean isRotationSeamless(@NonNull TransitionInfo info,
            DisplayController displayController) {
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
                "Display is rotating, check if it should be seamless.");
                "Display is changing, check if it should be seamless.");
        boolean checkedDisplayLayout = false;
        boolean hasTask = false;
        for (int i = info.getChanges().size() - 1; i >= 0; --i) {
            final TransitionInfo.Change change = info.getChanges().get(i);

@@ -166,6 +167,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
                    return false;
                }
            } else if (change.getTaskInfo() != null) {
                hasTask = true;
                // We only enable seamless rotation if all the visible task windows requested it.
                if (change.getRotationAnimation() != ROTATION_ANIMATION_SEAMLESS) {
                    ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
@@ -209,9 +211,13 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
            }
        }

        // ROTATION_ANIMATION_SEAMLESS can only be requested by task.
        if (hasTask) {
            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "  Rotation IS seamless.");
            return true;
        }
        return false;
    }

    /**
     * Gets the rotation animation for the topmost task. Assumes that seamless is checked
@@ -280,7 +286,6 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
            final TransitionInfo.Change change = info.getChanges().get(i);

            if (info.getType() == TRANSIT_CHANGE && change.getMode() == TRANSIT_CHANGE
                    && (change.getEndRotation() != change.getStartRotation())
                    && (change.getFlags() & FLAG_IS_DISPLAY) != 0) {
                boolean isSeamless = isRotationSeamless(info, mDisplayController);
                final int anim = getRotationAnimation(info);
+1 −1
Original line number Diff line number Diff line
@@ -186,11 +186,11 @@ class ScreenRotationAnimation {
            t.setAlpha(mBackColorSurface, 1);
            t.show(mBackColorSurface);

            t.setLayer(mAnimLeash, SCREEN_FREEZE_LAYER_BASE);
            t.setPosition(mAnimLeash, 0, 0);
            t.setAlpha(mAnimLeash, 1);
            t.show(mAnimLeash);

            t.setLayer(mScreenshotLayer, SCREEN_FREEZE_LAYER_BASE);
            t.setBuffer(mScreenshotLayer, buffer);
            t.setColorSpace(mScreenshotLayer, screenshotBuffer.getColorSpace());
            t.show(mScreenshotLayer);
+7 −0
Original line number Diff line number Diff line
@@ -583,6 +583,13 @@ public class ShellTransitionTests {
                        .setRotate(ROTATION_ANIMATION_SEAMLESS).build())
                .build();
        assertFalse(DefaultTransitionHandler.isRotationSeamless(seamlessButAlert, displays));

        // Not seamless if there is no changed task.
        final TransitionInfo noTask = new TransitionInfoBuilder(TRANSIT_CHANGE)
                .addChange(new ChangeBuilder(TRANSIT_CHANGE).setFlags(FLAG_IS_DISPLAY)
                        .setRotate().build())
                .build();
        assertFalse(DefaultTransitionHandler.isRotationSeamless(noTask, displays));
    }

    class TransitionInfoBuilder {
+4 −3
Original line number Diff line number Diff line
@@ -5943,6 +5943,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
    }

    void startFreezingScreen(int overrideOriginalDisplayRotation) {
        if (mAtmService.getTransitionController().isShellTransitionsEnabled()) {
            return;
        }
        ProtoLog.i(WM_DEBUG_ORIENTATION,
                "Set freezing of %s: visible=%b freezing=%b visibleRequested=%b. %s",
                appToken, isVisible(), mFreezingScreen, mVisibleRequested,
@@ -8443,9 +8446,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        if (shouldRelaunchLocked(changes, mTmpConfig) || forceNewConfig) {
            // Aha, the activity isn't handling the change, so DIE DIE DIE.
            configChangeFlags |= changes;
            if (!mAtmService.getTransitionController().isShellTransitionsEnabled()) {
            startFreezingScreenLocked(globalChanges);
            }
            forceNewConfig = false;
            // Do not preserve window if it is freezing screen because the original window won't be
            // able to update drawn state that causes freeze timeout.
+29 −2
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.window.DisplayAreaOrganizer.FEATURE_ROOT;
@@ -1389,11 +1390,16 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        final Configuration currentDisplayConfig = getConfiguration();
        mTmpConfiguration.setTo(currentDisplayConfig);
        computeScreenConfiguration(mTmpConfiguration);
        configChanged |= currentDisplayConfig.diff(mTmpConfiguration) != 0;
        final int changes = currentDisplayConfig.diff(mTmpConfiguration);
        configChanged |= changes != 0;

        if (configChanged) {
            mWaitingForConfig = true;
            if (mAtmService.getTransitionController().isShellTransitionsEnabled()) {
                requestChangeTransitionIfNeeded(changes);
            } else {
                mWmService.startFreezingDisplay(0 /* exitAnim */, 0 /* enterAnim */, this);
            }
            sendNewConfiguration();
        }

@@ -3165,6 +3171,24 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        return mScreenRotationAnimation;
    }

    /**
     * Requests to start a transition for the display configuration change. The given changes must
     * be non-zero. This method is no-op if the display has been collected.
     */
    void requestChangeTransitionIfNeeded(@ActivityInfo.Config int changes) {
        final TransitionController controller = mAtmService.getTransitionController();
        if (controller.isCollecting()) {
            if (!controller.isCollecting(this)) {
                controller.collect(this);
            }
            return;
        }
        final Transition t = controller.requestTransitionIfNeeded(TRANSIT_CHANGE, this);
        if (t != null) {
            t.setKnownConfigChanges(this, changes);
        }
    }

    /** If the display is in transition, there should be a screenshot covering it. */
    @Override
    boolean inTransition() {
@@ -5724,6 +5748,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
            }
            mWmService.mDisplayNotificationController.dispatchDisplayChanged(
                    this, getConfiguration());
            if (isReady() && mAtmService.getTransitionController().isShellTransitionsEnabled()) {
                requestChangeTransitionIfNeeded(changes);
            }
        }
        return changes;
    }
Loading