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

Commit 46a4f036 authored by Jerry Chang's avatar Jerry Chang
Browse files

Integrate split pair cold launch transition with shell transition

Separate RemoteAnimationTargetCompat.wrap to wrapApps and wrapNonApps to
support extracting non-app targets. Update to distinguish a divider
change from non-app targets to ensure it can be animated properly.

Fix: 222163803
Test: atest RemoteTransitionTest
Test: atest SplitTransitionTests
Test: enabled shell transition, cold launch a split pair from overview
      has proper transition.
Change-Id: Ibd45d612e75c3a3b664aaf3944f424289419858b
parent b1e4053c
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.window.TransitionInfo.FLAG_FIRST_CUSTOM;

import android.annotation.IntDef;

@@ -55,4 +56,7 @@ public class SplitScreenConstants {
            {WINDOWING_MODE_FULLSCREEN, WINDOWING_MODE_UNDEFINED};
    public static final int[] CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE =
            {WINDOWING_MODE_FULLSCREEN, WINDOWING_MODE_UNDEFINED, WINDOWING_MODE_MULTI_WINDOW};

    /** Flag applied to a transition change to identify it as a divider bar for animation. */
    public static final int FLAG_IS_DIVIDER_BAR = FLAG_FIRST_CUSTOM;
}
+19 −18
Original line number Diff line number Diff line
@@ -31,13 +31,13 @@ import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.WindowManager.transitTypeToString;
import static android.window.TransitionInfo.FLAG_FIRST_CUSTOM;
import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER;

import static com.android.wm.shell.common.split.SplitLayout.PARALLAX_ALIGN_CENTER;
import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES;
import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES;
import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
@@ -146,9 +146,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,

    private static final String TAG = StageCoordinator.class.getSimpleName();

    /** Flag applied to a transition change to identify it as a divider bar for animation. */
    public static final int FLAG_IS_DIVIDER_BAR = FLAG_FIRST_CUSTOM;

    private final SurfaceSession mSurfaceSession = new SurfaceSession();

    private final MainStage mMainStage;
@@ -1737,7 +1734,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,

        boolean shouldAnimate = true;
        if (mSplitTransitions.isPendingEnter(transition)) {
            shouldAnimate = startPendingEnterAnimation(transition, info, startTransaction);
            shouldAnimate = startPendingEnterAnimation(
                    transition, info, startTransaction, finishTransaction);
        } else if (mSplitTransitions.isPendingRecent(transition)) {
            shouldAnimate = startPendingRecentAnimation(transition, info, startTransaction);
        } else if (mSplitTransitions.isPendingDismiss(transition)) {
@@ -1765,7 +1763,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
    }

    private boolean startPendingEnterAnimation(@NonNull IBinder transition,
            @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t) {
            @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t,
            @NonNull SurfaceControl.Transaction finishT) {
        // First, verify that we actually have opened apps in both splits.
        TransitionInfo.Change mainChild = null;
        TransitionInfo.Change sideChild = null;
@@ -1812,8 +1811,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                    + " before startAnimation().");
        }

        finishEnterSplitScreen(t);
        addDividerBarToTransition(info, t, true /* show */);
        finishEnterSplitScreen(finishT);
        addDividerBarToTransition(info, finishT, true /* show */);
        return true;
    }

@@ -1898,7 +1897,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            return false;
        }

        addDividerBarToTransition(info, t, false /* show */);
        addDividerBarToTransition(info, finishT, false /* show */);
        return true;
    }

@@ -1909,23 +1908,25 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
    }

    private void addDividerBarToTransition(@NonNull TransitionInfo info,
            @NonNull SurfaceControl.Transaction t, boolean show) {
            @NonNull SurfaceControl.Transaction finishT, boolean show) {
        final SurfaceControl leash = mSplitLayout.getDividerLeash();
        final TransitionInfo.Change barChange = new TransitionInfo.Change(null /* token */, leash);
        final Rect bounds = mSplitLayout.getDividerBounds();
        barChange.setStartAbsBounds(bounds);
        barChange.setEndAbsBounds(bounds);
        mSplitLayout.getRefDividerBounds(mTempRect1);
        barChange.setStartAbsBounds(mTempRect1);
        barChange.setEndAbsBounds(mTempRect1);
        barChange.setMode(show ? TRANSIT_TO_FRONT : TRANSIT_TO_BACK);
        barChange.setFlags(FLAG_IS_DIVIDER_BAR);
        // Technically this should be order-0, but this is running after layer assignment
        // and it's a special case, so just add to end.
        info.addChange(barChange);
        // Be default, make it visible. The remote animator can adjust alpha if it plans to animate.

        if (show) {
            t.setAlpha(leash, 1.f);
            t.setLayer(leash, Integer.MAX_VALUE);
            t.setPosition(leash, bounds.left, bounds.top);
            t.show(leash);
            finishT.setLayer(leash, Integer.MAX_VALUE);
            finishT.setPosition(leash, mTempRect1.left, mTempRect1.top);
            finishT.show(leash);
            // Ensure divider surface are re-parented back into the hierarchy at the end of the
            // transition. See Transition#buildFinishTransaction for more detail.
            finishT.reparent(leash, mRootTaskLeash);
        }
    }

+1 −1
Original line number Diff line number Diff line
@@ -20,9 +20,9 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;

import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_CHILD_TASK_ENTER_PIP;
import static com.android.wm.shell.splitscreen.StageCoordinator.FLAG_IS_DIVIDER_BAR;

import android.annotation.NonNull;
import android.annotation.Nullable;
+5 −4
Original line number Diff line number Diff line
@@ -122,12 +122,13 @@ public class RemoteAnimationAdapterCompat {
                    IRemoteTransitionFinishedCallback finishCallback) {
                final ArrayMap<SurfaceControl, SurfaceControl> leashMap = new ArrayMap<>();
                final RemoteAnimationTargetCompat[] appsCompat =
                        RemoteAnimationTargetCompat.wrap(info, false /* wallpapers */, t, leashMap);
                        RemoteAnimationTargetCompat.wrapApps(info, t, leashMap);
                final RemoteAnimationTargetCompat[] wallpapersCompat =
                        RemoteAnimationTargetCompat.wrap(info, true /* wallpapers */, t, leashMap);
                // TODO(bc-unlock): Build wrapped object for non-apps target.
                        RemoteAnimationTargetCompat.wrapNonApps(
                                info, true /* wallpapers */, t, leashMap);
                final RemoteAnimationTargetCompat[] nonAppsCompat =
                        new RemoteAnimationTargetCompat[0];
                        RemoteAnimationTargetCompat.wrapNonApps(
                                info, false /* wallpapers */, t, leashMap);

                // TODO(b/177438007): Move this set-up logic into launcher's animation impl.
                boolean isReturnToHome = false;
+61 −31
Original line number Diff line number Diff line
@@ -16,7 +16,9 @@

package com.android.systemui.shared.system;

import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_BACK;
@@ -24,6 +26,8 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;

import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR;

import android.annotation.NonNull;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
@@ -76,7 +80,7 @@ public class RemoteAnimationTargetCompat {

    private final SurfaceControl mStartLeash;

    // Fields used only to unrap into RemoteAnimationTarget
    // Fields used only to unwrap into RemoteAnimationTarget
    private final Rect startBounds;

    public RemoteAnimationTargetCompat(RemoteAnimationTarget app) {
@@ -199,8 +203,19 @@ public class RemoteAnimationTargetCompat {

    public RemoteAnimationTargetCompat(TransitionInfo.Change change, int order,
            TransitionInfo info, SurfaceControl.Transaction t) {
        taskId = change.getTaskInfo() != null ? change.getTaskInfo().taskId : -1;
        mode = newModeToLegacyMode(change.getMode());
        taskInfo = change.getTaskInfo();
        if (taskInfo != null) {
            taskId = taskInfo.taskId;
            isNotInRecents = !taskInfo.isRunning;
            activityType = taskInfo.getActivityType();
            windowConfiguration = taskInfo.configuration.windowConfiguration;
        } else {
            taskId = INVALID_TASK_ID;
            isNotInRecents = true;
            activityType = ACTIVITY_TYPE_UNDEFINED;
            windowConfiguration = new WindowConfiguration();
        }

        // TODO: once we can properly sync transactions across process, then get rid of this leash.
        leash = createLeash(info, change, order, t);
@@ -218,22 +233,12 @@ public class RemoteAnimationTargetCompat {
        prefixOrderIndex = order;
        // TODO(shell-transitions): I guess we need to send content insets? evaluate how its used.
        contentInsets = new Rect(0, 0, 0, 0);
        if (change.getTaskInfo() != null) {
            isNotInRecents = !change.getTaskInfo().isRunning;
            activityType = change.getTaskInfo().getActivityType();
        } else {
            isNotInRecents = true;
            activityType = ACTIVITY_TYPE_UNDEFINED;
        }
        taskInfo = change.getTaskInfo();
        allowEnterPip = change.getAllowEnterPip();
        mStartLeash = null;
        rotationChange = change.getEndRotation() - change.getStartRotation();
        windowType = INVALID_WINDOW_TYPE;
        windowType = (change.getFlags() & FLAG_IS_DIVIDER_BAR) != 0
                ? TYPE_DOCK_DIVIDER : INVALID_WINDOW_TYPE;

        windowConfiguration = change.getTaskInfo() != null
            ? change.getTaskInfo().configuration.windowConfiguration
            : new WindowConfiguration();
        startBounds = change.getStartAbsBounds();
    }

@@ -247,24 +252,19 @@ public class RemoteAnimationTargetCompat {
    }

    /**
     * Represents a TransitionInfo object as an array of old-style targets
     * Represents a TransitionInfo object as an array of old-style app targets
     *
     * @param wallpapers If true, this will return wallpaper targets; otherwise it returns
     *                   non-wallpaper targets.
     * @param leashMap Temporary map of change leash -> launcher leash. Is an output, so should be
     *                 populated by this function. If null, it is ignored.
     */
    public static RemoteAnimationTargetCompat[] wrap(TransitionInfo info, boolean wallpapers,
    public static RemoteAnimationTargetCompat[] wrapApps(TransitionInfo info,
            SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
        final ArrayList<RemoteAnimationTargetCompat> out = new ArrayList<>();
        final SparseArray<TransitionInfo.Change> childTaskTargets = new SparseArray<>();
        for (int i = 0; i < info.getChanges().size(); i++) {
            final TransitionInfo.Change change = info.getChanges().get(i);
            final boolean changeIsWallpaper =
                    (change.getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0;
            if (wallpapers != changeIsWallpaper) continue;
            if (change.getTaskInfo() == null) continue;

            if (!wallpapers) {
            final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
            // Children always come before parent since changes are in top-to-bottom z-order.
            if (taskInfo != null) {
@@ -276,8 +276,38 @@ public class RemoteAnimationTargetCompat {
                    childTaskTargets.put(taskInfo.parentTaskId, change);
                }
            }

            final RemoteAnimationTargetCompat targetCompat =
                    new RemoteAnimationTargetCompat(change, info.getChanges().size() - i, info, t);
            if (leashMap != null) {
                leashMap.put(change.getLeash(), targetCompat.leash);
            }
            out.add(targetCompat);
        }

        return out.toArray(new RemoteAnimationTargetCompat[out.size()]);
    }

    /**
     * Represents a TransitionInfo object as an array of old-style non-app targets
     *
     * @param wallpapers If true, this will return wallpaper targets; otherwise it returns
     *                   non-wallpaper targets.
     * @param leashMap Temporary map of change leash -> launcher leash. Is an output, so should be
     *                 populated by this function. If null, it is ignored.
     */
    public static RemoteAnimationTargetCompat[] wrapNonApps(TransitionInfo info, boolean wallpapers,
            SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
        final ArrayList<RemoteAnimationTargetCompat> out = new ArrayList<>();

        for (int i = 0; i < info.getChanges().size(); i++) {
            final TransitionInfo.Change change = info.getChanges().get(i);
            if (change.getTaskInfo() != null) continue;

            final boolean changeIsWallpaper =
                    (change.getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0;
            if (wallpapers != changeIsWallpaper) continue;

            final RemoteAnimationTargetCompat targetCompat =
                    new RemoteAnimationTargetCompat(change, info.getChanges().size() - i, info, t);
            if (leashMap != null) {
Loading