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

Commit 2289ba17 authored by Evan Rosky's avatar Evan Rosky
Browse files

Change Transition

This adds a new transition classification for apps which are
switching between 2 visible states. The primary example of this
is windowing-mode change.

This new classification is mChangingApps in DisplayContent and
there is a transition type for TASK_CHANGE_WINDOWING_MODE.

The mode-change transition is scheduled when AppWindowToken
detects a windowing-mode change. It immediately creates
a snapshot and temporary leash to "freeze" the visuals of
the app until the animation starts (all transitioning apps
are ready).

The transition itself is a blend of fading, scaling, and
cropping based on whether the end-state is bigger than the
start state.

The RemoteAnimationTarget now includes a startBounds and an
extra "snapshot" leash for controlling the snapshot overlay
relative to the AppWindowToken. If either of those is
populated, the client of the RemoteAnimation can assume it
is animating a change and is responsible for transforming
the leash from the startBounds to its final state.

Bug: 113253723
Bug: 111762928
Test: go/wm-smoke + RemoteAnimationControllerTests
Change-Id: I8654656124b888950e55e31d88ce7a4101e935f8
parent e2c3e477
Loading
Loading
Loading
Loading
+35 −2
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ import static android.view.RemoteAnimationTargetProto.MODE;
import static android.view.RemoteAnimationTargetProto.POSITION;
import static android.view.RemoteAnimationTargetProto.PREFIX_ORDER_INDEX;
import static android.view.RemoteAnimationTargetProto.SOURCE_CONTAINER_BOUNDS;
import static android.view.RemoteAnimationTargetProto.START_BOUNDS;
import static android.view.RemoteAnimationTargetProto.START_LEASH;
import static android.view.RemoteAnimationTargetProto.TASK_ID;
import static android.view.RemoteAnimationTargetProto.WINDOW_CONFIGURATION;

@@ -57,9 +59,15 @@ public class RemoteAnimationTarget implements Parcelable {
     */
    public static final int MODE_CLOSING = 1;

    /**
     * The app is in the set of resizing apps (eg. mode change) of this transition.
     */
    public static final int MODE_CHANGING = 2;

    @IntDef(prefix = { "MODE_" }, value = {
            MODE_OPENING,
            MODE_CLOSING
            MODE_CLOSING,
            MODE_CHANGING
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Mode {}
@@ -82,6 +90,13 @@ public class RemoteAnimationTarget implements Parcelable {
    @UnsupportedAppUsage
    public final SurfaceControl leash;

    /**
     * The {@link SurfaceControl} for the starting state of a target if this transition is
     * MODE_CHANGING, {@code null)} otherwise. This is relative to the app window.
     */
    @UnsupportedAppUsage
    public final SurfaceControl startLeash;

    /**
     * Whether the app is translucent and may reveal apps behind.
     */
@@ -127,6 +142,15 @@ public class RemoteAnimationTarget implements Parcelable {
    @UnsupportedAppUsage
    public final Rect sourceContainerBounds;

    /**
     * The starting bounds of the source container in screen space coordinates. This is {@code null}
     * if the animation target isn't MODE_CHANGING. Since this is the starting bounds, it's size
     * should be equivalent to the size of the starting thumbnail. Note that sourceContainerBounds
     * is the end bounds of a change transition.
     */
    @UnsupportedAppUsage
    public final Rect startBounds;

    /**
     * The window configuration for the target.
     */
@@ -141,7 +165,8 @@ public class RemoteAnimationTarget implements Parcelable {

    public RemoteAnimationTarget(int taskId, int mode, SurfaceControl leash, boolean isTranslucent,
            Rect clipRect, Rect contentInsets, int prefixOrderIndex, Point position,
            Rect sourceContainerBounds, WindowConfiguration windowConfig, boolean isNotInRecents) {
            Rect sourceContainerBounds, WindowConfiguration windowConfig, boolean isNotInRecents,
            SurfaceControl startLeash, Rect startBounds) {
        this.mode = mode;
        this.taskId = taskId;
        this.leash = leash;
@@ -153,6 +178,8 @@ public class RemoteAnimationTarget implements Parcelable {
        this.sourceContainerBounds = new Rect(sourceContainerBounds);
        this.windowConfiguration = windowConfig;
        this.isNotInRecents = isNotInRecents;
        this.startLeash = startLeash;
        this.startBounds = startBounds == null ? null : new Rect(startBounds);
    }

    public RemoteAnimationTarget(Parcel in) {
@@ -167,6 +194,8 @@ public class RemoteAnimationTarget implements Parcelable {
        sourceContainerBounds = in.readParcelable(null);
        windowConfiguration = in.readParcelable(null);
        isNotInRecents = in.readBoolean();
        startLeash = in.readParcelable(null);
        startBounds = in.readParcelable(null);
    }

    @Override
@@ -187,6 +216,8 @@ public class RemoteAnimationTarget implements Parcelable {
        dest.writeParcelable(sourceContainerBounds, 0 /* flags */);
        dest.writeParcelable(windowConfiguration, 0 /* flags */);
        dest.writeBoolean(isNotInRecents);
        dest.writeParcelable(startLeash, 0 /* flags */);
        dest.writeParcelable(startBounds, 0 /* flags */);
    }

    public void dump(PrintWriter pw, String prefix) {
@@ -215,6 +246,8 @@ public class RemoteAnimationTarget implements Parcelable {
        position.writeToProto(proto, POSITION);
        sourceContainerBounds.writeToProto(proto, SOURCE_CONTAINER_BOUNDS);
        windowConfiguration.writeToProto(proto, WINDOW_CONFIGURATION);
        startLeash.writeToProto(proto, START_LEASH);
        startBounds.writeToProto(proto, START_BOUNDS);
        proto.end(token);
    }

+8 −1
Original line number Diff line number Diff line
@@ -254,6 +254,12 @@ public interface WindowManager extends ViewManager {
     */
    int TRANSIT_CRASHING_ACTIVITY_CLOSE = 26;

    /**
     * A task is changing windowing modes
     * @hide
     */
    int TRANSIT_TASK_CHANGE_WINDOWING_MODE = 27;

    /**
     * @hide
     */
@@ -280,7 +286,8 @@ public interface WindowManager extends ViewManager {
            TRANSIT_KEYGUARD_UNOCCLUDE,
            TRANSIT_TRANSLUCENT_ACTIVITY_OPEN,
            TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE,
            TRANSIT_CRASHING_ACTIVITY_CLOSE
            TRANSIT_CRASHING_ACTIVITY_CLOSE,
            TRANSIT_TASK_CHANGE_WINDOWING_MODE
    })
    @Retention(RetentionPolicy.SOURCE)
    @interface TransitionType {}
+2 −0
Original line number Diff line number Diff line
@@ -42,4 +42,6 @@ message RemoteAnimationTargetProto {
    optional .android.graphics.PointProto position = 8;
    optional .android.graphics.RectProto source_container_bounds = 9;
    optional .android.app.WindowConfigurationProto window_configuration = 10;
    optional .android.view.SurfaceControlProto start_leash = 11;
    optional .android.graphics.RectProto start_bounds = 12;
}
+2 −3
Original line number Diff line number Diff line
@@ -1901,9 +1901,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {

        mWindowManagerInternal.registerAppTransitionListener(new AppTransitionListener() {
            @Override
            public int onAppTransitionStartingLocked(int transit, IBinder openToken,
                    IBinder closeToken, long duration, long statusBarAnimationStartTime,
                    long statusBarAnimationDuration) {
            public int onAppTransitionStartingLocked(int transit, long duration,
                    long statusBarAnimationStartTime, long statusBarAnimationDuration) {
                return handleStartTransitionForKeyguardLw(transit, duration);
            }

+16 −14
Original line number Diff line number Diff line
@@ -174,6 +174,7 @@ public class AppTransition implements Dump {
    private int mLastUsedAppTransition = TRANSIT_UNSET;
    private String mLastOpeningApp;
    private String mLastClosingApp;
    private String mLastChangingApp;

    private static final int NEXT_TRANSIT_TYPE_NONE = 0;
    private static final int NEXT_TRANSIT_TYPE_CUSTOM = 1;
@@ -318,14 +319,16 @@ public class AppTransition implements Dump {
    private void setAppTransition(int transit, int flags) {
        mNextAppTransition = transit;
        mNextAppTransitionFlags |= flags;
        setLastAppTransition(TRANSIT_UNSET, null, null);
        setLastAppTransition(TRANSIT_UNSET, null, null, null);
        updateBooster();
    }

    void setLastAppTransition(int transit, AppWindowToken openingApp, AppWindowToken closingApp) {
    void setLastAppTransition(int transit, AppWindowToken openingApp, AppWindowToken closingApp,
            AppWindowToken changingApp) {
        mLastUsedAppTransition = transit;
        mLastOpeningApp = "" + openingApp;
        mLastClosingApp = "" + closingApp;
        mLastChangingApp = "" + changingApp;
    }

    boolean isReady() {
@@ -412,9 +415,7 @@ public class AppTransition implements Dump {
     * @return bit-map of WindowManagerPolicy#FINISH_LAYOUT_REDO_* to indicate whether another
     *         layout pass needs to be done
     */
    int goodToGo(int transit, AppWindowToken topOpeningApp,
            AppWindowToken topClosingApp, ArraySet<AppWindowToken> openingApps,
            ArraySet<AppWindowToken> closingApps) {
    int goodToGo(int transit, AppWindowToken topOpeningApp, ArraySet<AppWindowToken> openingApps) {
        mNextAppTransition = TRANSIT_UNSET;
        mNextAppTransitionFlags = 0;
        setAppTransitionState(APP_STATE_RUNNING);
@@ -422,8 +423,6 @@ public class AppTransition implements Dump {
                ? topOpeningApp.getAnimation()
                : null;
        int redoLayout = notifyAppTransitionStartingLocked(transit,
                topOpeningApp != null ? topOpeningApp.token : null,
                topClosingApp != null ? topClosingApp.token : null,
                topOpeningAnim != null ? topOpeningAnim.getDurationHint() : 0,
                topOpeningAnim != null
                        ? topOpeningAnim.getStatusBarTransitionsStartTime()
@@ -500,13 +499,12 @@ public class AppTransition implements Dump {
        }
    }

    private int notifyAppTransitionStartingLocked(int transit, IBinder openToken,
            IBinder closeToken, long duration, long statusBarAnimationStartTime,
            long statusBarAnimationDuration) {
    private int notifyAppTransitionStartingLocked(int transit, long duration,
            long statusBarAnimationStartTime, long statusBarAnimationDuration) {
        int redoLayout = 0;
        for (int i = 0; i < mListeners.size(); i++) {
            redoLayout |= mListeners.get(i).onAppTransitionStartingLocked(transit, openToken,
                    closeToken, duration, statusBarAnimationStartTime, statusBarAnimationDuration);
            redoLayout |= mListeners.get(i).onAppTransitionStartingLocked(transit, duration,
                    statusBarAnimationStartTime, statusBarAnimationDuration);
        }
        return redoLayout;
    }
@@ -2128,6 +2126,8 @@ public class AppTransition implements Dump {
                    pw.println(mLastOpeningApp);
            pw.print(prefix); pw.print("mLastClosingApp=");
                    pw.println(mLastClosingApp);
            pw.print(prefix); pw.print("mLastChangingApp=");
            pw.println(mLastChangingApp);
        }
    }

@@ -2226,14 +2226,16 @@ public class AppTransition implements Dump {
            if (dc == null) {
                return;
            }
            if (isTransitionSet() || !dc.mOpeningApps.isEmpty() || !dc.mClosingApps.isEmpty()) {
            if (isTransitionSet() || !dc.mOpeningApps.isEmpty() || !dc.mClosingApps.isEmpty()
                    || !dc.mChangingApps.isEmpty()) {
                if (DEBUG_APP_TRANSITIONS) {
                    Slog.v(TAG_WM, "*** APP TRANSITION TIMEOUT."
                            + " displayId=" + dc.getDisplayId()
                            + " isTransitionSet()="
                            + dc.mAppTransition.isTransitionSet()
                            + " mOpeningApps.size()=" + dc.mOpeningApps.size()
                            + " mClosingApps.size()=" + dc.mClosingApps.size());
                            + " mClosingApps.size()=" + dc.mClosingApps.size()
                            + " mChangingApps.size()=" + dc.mChangingApps.size());
                }
                setTimeout();
                mService.mWindowPlacerLocked.performSurfacePlacement();
Loading