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

Commit 1551cb73 authored by Evan Rosky's avatar Evan Rosky
Browse files

Initial support for display rotation in shell transitions

This puts display-content as another WC in a transition. It then
adds WC rotation to change tracking. If there is a rotation,
the shell-side handlers will play the transition.

This replaces ScreenTransitionAnimation, seamless-rotation, and
fixed-rotation:

 ScreenTransitionAnimation implementation will move to shell.

 seamless-rotation is redundant because the rotation setup is
 intrinsically "seamless": it requires shell to imbue an
 animation onto it rather than just doing the jump-cut.

 fixed-rotation is now just a custom animation where we
 counter-rotate the closing app on frame 1 and then perform
 the normal open animation on the opening app.

Bug: 179270750
Test: DisplayContentTests#testShellTransitRotation
      enable shell transitions and rotate the device or launch
      and close apps in different orientations.
Change-Id: I4bc23b2e614ba85bf9752f62da4c3f8d0c90436d
parent d96c8193
Loading
Loading
Loading
Loading
+24 −1
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


package android.window;
package android.window;


import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_NONE;
@@ -31,6 +32,7 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.view.WindowManager;


@@ -284,6 +286,8 @@ public final class TransitionInfo implements Parcelable {
        private final Rect mEndAbsBounds = new Rect();
        private final Rect mEndAbsBounds = new Rect();
        private final Point mEndRelOffset = new Point();
        private final Point mEndRelOffset = new Point();
        private ActivityManager.RunningTaskInfo mTaskInfo = null;
        private ActivityManager.RunningTaskInfo mTaskInfo = null;
        private int mStartRotation = ROTATION_UNDEFINED;
        private int mEndRotation = ROTATION_UNDEFINED;


        public Change(@Nullable WindowContainerToken container, @NonNull SurfaceControl leash) {
        public Change(@Nullable WindowContainerToken container, @NonNull SurfaceControl leash) {
            mContainer = container;
            mContainer = container;
@@ -301,6 +305,8 @@ public final class TransitionInfo implements Parcelable {
            mEndAbsBounds.readFromParcel(in);
            mEndAbsBounds.readFromParcel(in);
            mEndRelOffset.readFromParcel(in);
            mEndRelOffset.readFromParcel(in);
            mTaskInfo = in.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR);
            mTaskInfo = in.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR);
            mStartRotation = in.readInt();
            mEndRotation = in.readInt();
        }
        }


        /** Sets the parent of this change's container. The parent must be a participant or null. */
        /** Sets the parent of this change's container. The parent must be a participant or null. */
@@ -341,6 +347,12 @@ public final class TransitionInfo implements Parcelable {
            mTaskInfo = taskInfo;
            mTaskInfo = taskInfo;
        }
        }


        /** Sets the start and end rotation of this container. */
        public void setRotation(@Surface.Rotation int start, @Surface.Rotation int end) {
            mStartRotation = start;
            mEndRotation = end;
        }

        /** @return the container that is changing. May be null if non-remotable (eg. activity) */
        /** @return the container that is changing. May be null if non-remotable (eg. activity) */
        @Nullable
        @Nullable
        public WindowContainerToken getContainer() {
        public WindowContainerToken getContainer() {
@@ -404,6 +416,14 @@ public final class TransitionInfo implements Parcelable {
            return mTaskInfo;
            return mTaskInfo;
        }
        }


        public int getStartRotation() {
            return mStartRotation;
        }

        public int getEndRotation() {
            return mEndRotation;
        }

        @Override
        @Override
        /** @hide */
        /** @hide */
        public void writeToParcel(@NonNull Parcel dest, int flags) {
        public void writeToParcel(@NonNull Parcel dest, int flags) {
@@ -416,6 +436,8 @@ public final class TransitionInfo implements Parcelable {
            mEndAbsBounds.writeToParcel(dest, flags);
            mEndAbsBounds.writeToParcel(dest, flags);
            mEndRelOffset.writeToParcel(dest, flags);
            mEndRelOffset.writeToParcel(dest, flags);
            dest.writeTypedObject(mTaskInfo, flags);
            dest.writeTypedObject(mTaskInfo, flags);
            dest.writeInt(mStartRotation);
            dest.writeInt(mEndRotation);
        }
        }


        @NonNull
        @NonNull
@@ -442,7 +464,8 @@ public final class TransitionInfo implements Parcelable {
        public String toString() {
        public String toString() {
            return "{" + mContainer + "(" + mParent + ") leash=" + mLeash
            return "{" + mContainer + "(" + mParent + ") leash=" + mLeash
                    + " m=" + modeToString(mMode) + " f=" + flagsToString(mFlags) + " sb="
                    + " m=" + modeToString(mMode) + " f=" + flagsToString(mFlags) + " sb="
                    + mStartAbsBounds + " eb=" + mEndAbsBounds + " eo=" + mEndRelOffset + "}";
                    + mStartAbsBounds + " eb=" + mEndAbsBounds + " eo=" + mEndRelOffset + " r="
                    + mStartRotation + "->" + mEndRotation + "}";
        }
        }
    }
    }
}
}
+6 −12
Original line number Original line Diff line number Diff line
@@ -823,12 +823,6 @@
      "group": "WM_DEBUG_STATES",
      "group": "WM_DEBUG_STATES",
      "at": "com\/android\/server\/wm\/Task.java"
      "at": "com\/android\/server\/wm\/Task.java"
    },
    },
    "-1159577965": {
      "message": "Focus requested for input consumer=%s",
      "level": "VERBOSE",
      "group": "WM_DEBUG_FOCUS_LIGHT",
      "at": "com\/android\/server\/wm\/InputMonitor.java"
    },
    "-1156118957": {
    "-1156118957": {
      "message": "Updated config=%s",
      "message": "Updated config=%s",
      "level": "DEBUG",
      "level": "DEBUG",
@@ -1237,6 +1231,12 @@
      "group": "WM_DEBUG_TASKS",
      "group": "WM_DEBUG_TASKS",
      "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
      "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
    },
    },
    "-672355406": {
      "message": "  Rejecting as no-op: %s",
      "level": "VERBOSE",
      "group": "WM_DEBUG_WINDOW_TRANSITIONS",
      "at": "com\/android\/server\/wm\/Transition.java"
    },
    "-672228342": {
    "-672228342": {
      "message": "resumeTopActivityLocked: Top activity resumed %s",
      "message": "resumeTopActivityLocked: Top activity resumed %s",
      "level": "DEBUG",
      "level": "DEBUG",
@@ -2479,12 +2479,6 @@
      "group": "WM_DEBUG_RESIZE",
      "group": "WM_DEBUG_RESIZE",
      "at": "com\/android\/server\/wm\/WindowState.java"
      "at": "com\/android\/server\/wm\/WindowState.java"
    },
    },
    "690411811": {
      "message": "goodToGo(): No apps to animate",
      "level": "DEBUG",
      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
    },
    "691515534": {
    "691515534": {
      "message": "  Commit wallpaper becoming invisible: %s",
      "message": "  Commit wallpaper becoming invisible: %s",
      "level": "VERBOSE",
      "level": "VERBOSE",
+1 −1
Original line number Original line Diff line number Diff line
@@ -28,7 +28,7 @@ public enum ShellProtoLogGroup implements IProtoLogGroup {
    // with those in the framework ProtoLogGroup
    // with those in the framework ProtoLogGroup
    WM_SHELL_TASK_ORG(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
    WM_SHELL_TASK_ORG(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
            Consts.TAG_WM_SHELL),
            Consts.TAG_WM_SHELL),
    WM_SHELL_TRANSITIONS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
    WM_SHELL_TRANSITIONS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true,
            Consts.TAG_WM_SHELL),
            Consts.TAG_WM_SHELL),
    WM_SHELL_DRAG_AND_DROP(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
    WM_SHELL_DRAG_AND_DROP(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
            Consts.TAG_WM_SHELL),
            Consts.TAG_WM_SHELL),
+11 −0
Original line number Original line Diff line number Diff line
@@ -96,6 +96,17 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
        };
        };
        for (int i = info.getChanges().size() - 1; i >= 0; --i) {
        for (int i = info.getChanges().size() - 1; i >= 0; --i) {
            final TransitionInfo.Change change = info.getChanges().get(i);
            final TransitionInfo.Change change = info.getChanges().get(i);
            if (change.getMode() == TRANSIT_CHANGE) {
                // No default animation for this, so just update bounds/position.
                t.setPosition(change.getLeash(),
                        change.getEndAbsBounds().left - change.getEndRelOffset().x,
                        change.getEndAbsBounds().top - change.getEndRelOffset().y);
                if (change.getTaskInfo() != null) {
                    // Skip non-tasks since those usually have null bounds.
                    t.setWindowCrop(change.getLeash(),
                            change.getEndAbsBounds().width(), change.getEndAbsBounds().height());
                }
            }


            // Don't animate anything that isn't independent.
            // Don't animate anything that isn't independent.
            if (!TransitionInfo.isIndependent(change, info)) continue;
            if (!TransitionInfo.isIndependent(change, info)) continue;
+94 −1
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@ import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.WindowManager.TransitionOldType;
import static android.view.WindowManager.TransitionOldType;
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;


import android.os.RemoteException;
import android.os.RemoteException;
import android.util.Log;
import android.util.Log;
@@ -35,6 +36,8 @@ import android.window.IRemoteTransition;
import android.window.IRemoteTransitionFinishedCallback;
import android.window.IRemoteTransitionFinishedCallback;
import android.window.TransitionInfo;
import android.window.TransitionInfo;


import java.util.ArrayList;

/**
/**
 * @see RemoteAnimationAdapter
 * @see RemoteAnimationAdapter
 */
 */
@@ -100,6 +103,52 @@ public class RemoteAnimationAdapterCompat {
        };
        };
    }
    }


    private static class CounterRotator {
        SurfaceControl mSurface = null;
        ArrayList<SurfaceControl> mRotateChildren = null;

        void setup(SurfaceControl.Transaction t, SurfaceControl parent, int rotateDelta,
                float displayW, float displayH) {
            if (rotateDelta == 0) return;
            mRotateChildren = new ArrayList<>();
            // We want to counter-rotate, so subtract from 4
            rotateDelta = 4 - (rotateDelta + 4) % 4;
            mSurface = new SurfaceControl.Builder()
                    .setName("Transition Unrotate")
                    .setContainerLayer()
                    .setParent(parent)
                    .build();
            // column-major
            if (rotateDelta == 1) {
                t.setMatrix(mSurface, 0, 1, -1, 0);
                t.setPosition(mSurface, displayW, 0);
            } else if (rotateDelta == 2) {
                t.setMatrix(mSurface, -1, 0, 0, -1);
                t.setPosition(mSurface, displayW, displayH);
            } else if (rotateDelta == 3) {
                t.setMatrix(mSurface, 0, -1, 1, 0);
                t.setPosition(mSurface, 0, displayH);
            }
            t.show(mSurface);
        }

        void addChild(SurfaceControl.Transaction t, SurfaceControl child) {
            if (mSurface == null) return;
            t.reparent(child, mSurface);
            mRotateChildren.add(child);
        }

        void cleanUp(SurfaceControl rootLeash) {
            if (mSurface == null) return;
            SurfaceControl.Transaction t = new SurfaceControl.Transaction();
            for (int i = mRotateChildren.size() - 1; i >= 0; --i) {
                t.reparent(mRotateChildren.get(i), rootLeash);
            }
            t.remove(mSurface);
            t.apply();
        }
    }

    private static IRemoteTransition.Stub wrapRemoteTransition(
    private static IRemoteTransition.Stub wrapRemoteTransition(
            final RemoteAnimationRunnerCompat remoteAnimationAdapter) {
            final RemoteAnimationRunnerCompat remoteAnimationAdapter) {
        return new IRemoteTransition.Stub() {
        return new IRemoteTransition.Stub() {
@@ -116,17 +165,46 @@ public class RemoteAnimationAdapterCompat {


                // TODO(b/177438007): Move this set-up logic into launcher's animation impl.
                // TODO(b/177438007): Move this set-up logic into launcher's animation impl.
                boolean isReturnToHome = false;
                boolean isReturnToHome = false;
                TransitionInfo.Change launcherTask = null;
                TransitionInfo.Change wallpaper = null;
                int launcherLayer = 0;
                int rotateDelta = 0;
                float displayW = 0;
                float displayH = 0;
                for (int i = info.getChanges().size() - 1; i >= 0; --i) {
                for (int i = info.getChanges().size() - 1; i >= 0; --i) {
                    final TransitionInfo.Change change = info.getChanges().get(i);
                    final TransitionInfo.Change change = info.getChanges().get(i);
                    if (change.getTaskInfo() != null
                    if (change.getTaskInfo() != null
                            && change.getTaskInfo().getActivityType() == ACTIVITY_TYPE_HOME) {
                            && change.getTaskInfo().getActivityType() == ACTIVITY_TYPE_HOME) {
                        isReturnToHome = change.getMode() == TRANSIT_OPEN
                        isReturnToHome = change.getMode() == TRANSIT_OPEN
                                || change.getMode() == TRANSIT_TO_FRONT;
                                || change.getMode() == TRANSIT_TO_FRONT;
                        break;
                        launcherTask = change;
                        launcherLayer = info.getChanges().size() - i;
                    } else if ((change.getFlags() & FLAG_IS_WALLPAPER) != 0) {
                        wallpaper = change;
                    }
                    if (change.getParent() == null && change.getEndRotation() >= 0
                            && change.getEndRotation() != change.getStartRotation()) {
                        rotateDelta = change.getEndRotation() - change.getStartRotation();
                        displayW = change.getEndAbsBounds().width();
                        displayH = change.getEndAbsBounds().height();
                    }
                }

                // Prepare for rotation if there is one
                final CounterRotator counterLauncher = new CounterRotator();
                final CounterRotator counterWallpaper = new CounterRotator();
                if (launcherTask != null && rotateDelta != 0 && launcherTask.getParent() != null) {
                    counterLauncher.setup(t, info.getChange(launcherTask.getParent()).getLeash(),
                            rotateDelta, displayW, displayH);
                    if (counterLauncher.mSurface != null) {
                        t.setLayer(counterLauncher.mSurface, launcherLayer);
                    }
                    }
                }
                }


                if (isReturnToHome) {
                if (isReturnToHome) {
                    if (counterLauncher.mSurface != null) {
                        t.setLayer(counterLauncher.mSurface, info.getChanges().size() * 3);
                    }
                    // Need to "boost" the closing things since that's what launcher expects.
                    // Need to "boost" the closing things since that's what launcher expects.
                    for (int i = info.getChanges().size() - 1; i >= 0; --i) {
                    for (int i = info.getChanges().size() - 1; i >= 0; --i) {
                        final TransitionInfo.Change change = info.getChanges().get(i);
                        final TransitionInfo.Change change = info.getChanges().get(i);
@@ -136,6 +214,7 @@ public class RemoteAnimationAdapterCompat {
                        if (!TransitionInfo.isIndependent(change, info)) continue;
                        if (!TransitionInfo.isIndependent(change, info)) continue;
                        if (mode == TRANSIT_CLOSE || mode == TRANSIT_TO_BACK) {
                        if (mode == TRANSIT_CLOSE || mode == TRANSIT_TO_BACK) {
                            t.setLayer(leash, info.getChanges().size() * 3 - i);
                            t.setLayer(leash, info.getChanges().size() * 3 - i);
                            counterLauncher.addChild(t, leash);
                        }
                        }
                    }
                    }
                    // Make wallpaper visible immediately since launcher apparently won't do this.
                    // Make wallpaper visible immediately since launcher apparently won't do this.
@@ -143,6 +222,18 @@ public class RemoteAnimationAdapterCompat {
                        t.show(wallpapersCompat[i].leash.getSurfaceControl());
                        t.show(wallpapersCompat[i].leash.getSurfaceControl());
                        t.setAlpha(wallpapersCompat[i].leash.getSurfaceControl(), 1.f);
                        t.setAlpha(wallpapersCompat[i].leash.getSurfaceControl(), 1.f);
                    }
                    }
                } else {
                    if (launcherTask != null) {
                        counterLauncher.addChild(t, launcherTask.getLeash());
                    }
                    if (wallpaper != null && rotateDelta != 0 && wallpaper.getParent() != null) {
                        counterWallpaper.setup(t, info.getChange(wallpaper.getParent()).getLeash(),
                                rotateDelta, displayW, displayH);
                        if (counterWallpaper.mSurface != null) {
                            t.setLayer(counterWallpaper.mSurface, -1);
                            counterWallpaper.addChild(t, wallpaper.getLeash());
                        }
                    }
                }
                }
                t.apply();
                t.apply();


@@ -150,6 +241,8 @@ public class RemoteAnimationAdapterCompat {
                    @Override
                    @Override
                    public void run() {
                    public void run() {
                        try {
                        try {
                            counterLauncher.cleanUp(info.getRootLeash());
                            counterWallpaper.cleanUp(info.getRootLeash());
                            finishCallback.onTransitionFinished(null /* wct */);
                            finishCallback.onTransitionFinished(null /* wct */);
                        } catch (RemoteException e) {
                        } catch (RemoteException e) {
                            Log.e("ActivityOptionsCompat", "Failed to call app controlled animation"
                            Log.e("ActivityOptionsCompat", "Failed to call app controlled animation"
Loading