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

Commit 84443907 authored by Jeremy Sim's avatar Jeremy Sim
Browse files

Flexible 2-app split: Dimming (part 2)

This CL adds dim layers to the recents transition, so that they correctly fade in and out when going from splitscreen to recents and back.

Remaining issues:
- A small dark flash when the app initially settles in the 90:10 ratio. Deferring this because I suspect it will be fixed by an upcoming app surface change.

Bug: 349828130
Flag: com.android.wm.shell.enable_flexible_two_app_split
Test: Visually correct when a 90:10 pair goes to recents and back
Change-Id: I053b587f6fbeabf27e3dfbc15fe81f17768db78f
parent b71fa427
Loading
Loading
Loading
Loading
+42 −3
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.view.RemoteAnimationTarget.MODE_CHANGING;
import static android.view.RemoteAnimationTarget.MODE_CLOSING;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
import static android.view.WindowManager.LayoutParams.LAST_SYSTEM_WINDOW;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
@@ -55,9 +56,15 @@ import java.util.function.Predicate;
public class TransitionUtil {
    /** 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;
    public static final int FLAG_IS_DIM_LAYER = FLAG_FIRST_CUSTOM << 1;

    /** Flag applied to a transition change to identify it as a desktop wallpaper activity. */
    public static final int FLAG_IS_DESKTOP_WALLPAPER_ACTIVITY = FLAG_FIRST_CUSTOM << 1;
    public static final int FLAG_IS_DESKTOP_WALLPAPER_ACTIVITY = FLAG_FIRST_CUSTOM << 2;

    /**
     * Applied to a {@link RemoteAnimationTarget} to identify dim layers for animation in Launcher.
     */
    public static final int TYPE_SPLIT_SCREEN_DIM_LAYER = LAST_SYSTEM_WINDOW + 1;

    /** @return true if the transition was triggered by opening something vs closing something */
    public static boolean isOpeningType(@WindowManager.TransitionType int type) {
@@ -117,6 +124,11 @@ public class TransitionUtil {
        return isNonApp(change) && change.hasFlags(FLAG_IS_DIVIDER_BAR);
    }

    /** Returns `true` if `change` is an app's dim layer. */
    public static boolean isDimLayer(TransitionInfo.Change change) {
        return isNonApp(change) && change.hasFlags(FLAG_IS_DIM_LAYER);
    }

    /** Returns `true` if `change` is only re-ordering. */
    public static boolean isOrderOnly(TransitionInfo.Change change) {
        return change.getMode() == TRANSIT_CHANGE
@@ -231,6 +243,14 @@ public class TransitionUtil {
            t.setLayer(leash, Integer.MAX_VALUE);
            return;
        }
        if (isDimLayer(change)) {
            // When a dim layer gets reparented onto the transition root, we need to zero out its
            // position so that it's in line with everything else on the transition root. Also,
            // we need to set a crop because we don't want it applying MATCH_PARENT on the whole
            // root surface.
            t.setPosition(leash, 0, 0);
            t.setCrop(leash, change.getEndAbsBounds());
        }

        // Put all the OPEN/SHOW on top
        if ((change.getFlags() & FLAG_IS_WALLPAPER) != 0) {
@@ -284,14 +304,19 @@ public class TransitionUtil {
        // Copied Transitions setup code (which expects bottom-to-top order, so we swap here)
        setupLeash(leashSurface, change, info.getChanges().size() - order, info, t);
        t.reparent(change.getLeash(), leashSurface);
        if (!isDimLayer(change)) {
            // Most leashes going onto the transition root should have their alpha set here to make
            // them visible. But dim layers should be left untouched (their alpha value is their
            // actual dim value).
            t.setAlpha(change.getLeash(), 1.0f);
        t.show(change.getLeash());
        }
        if (!isDividerBar(change)) {
            // For divider, don't modify its inner leash position when creating the outer leash
            // for the transition. In case the position being wrong after the transition finished.
            t.setPosition(change.getLeash(), 0, 0);
        }
        t.setLayer(change.getLeash(), 0);
        t.show(change.getLeash());
        return leashSurface;
    }

@@ -333,6 +358,9 @@ public class TransitionUtil {
        if (isDividerBar(change)) {
            return getDividerTarget(change, leash);
        }
        if (isDimLayer(change)) {
            return getDimLayerTarget(change, leash);
        }

        int taskId;
        boolean isNotInRecents;
@@ -439,6 +467,17 @@ public class TransitionUtil {
                TYPE_DOCK_DIVIDER);
    }

    private static RemoteAnimationTarget getDimLayerTarget(TransitionInfo.Change change,
            SurfaceControl leash) {
        return new RemoteAnimationTarget(-1 /* taskId */, newModeToLegacyMode(change.getMode()),
                leash, false /* isTranslucent */, null /* clipRect */,
                null /* contentInsets */, Integer.MAX_VALUE /* prefixOrderIndex */,
                new android.graphics.Point(0, 0) /* position */, change.getStartAbsBounds(),
                change.getStartAbsBounds(), new WindowConfiguration(), true, null /* startLeash */,
                null /* startBounds */, null /* taskInfo */, false /* allowEnterPip */,
                TYPE_SPLIT_SCREEN_DIM_LAYER);
    }

    /**
     * Finds the "correct" root idx for a change. The change's end display is prioritized, then
     * the start display. If there is no display, it will fallback on the 0th root in the
+1 −0
Original line number Diff line number Diff line
@@ -262,6 +262,7 @@ public class SplitScreenConstants {

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

    public static final String splitPositionToString(@SplitPosition int pos) {
        switch (pos) {
+8 −0
Original line number Diff line number Diff line
@@ -128,6 +128,8 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
    // The touch layer is on a stage root, and is sibling with things like the app activity itself
    // and the app veil. We want it to be above all those.
    public static final int RESTING_TOUCH_LAYER = Integer.MAX_VALUE;
    // The dim layer is also on the stage root, and stays under the touch layer.
    public static final int RESTING_DIM_LAYER = RESTING_TOUCH_LAYER - 1;

    // Animation specs for the swap animation
    private static final int SWAP_ANIMATION_TOTAL_DURATION = 500;
@@ -1201,6 +1203,12 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
            // Resets layer of divider bar to make sure it is always on top.
            t.setLayer(dividerLeash, RESTING_DIVIDER_LAYER);
        }
        if (dimLayer1 != null) {
            t.setLayer(dimLayer1, RESTING_DIM_LAYER);
        }
        if (dimLayer2 != null) {
            t.setLayer(dimLayer2, RESTING_DIM_LAYER);
        }
        copyTopLeftRefBounds(mTempRect);
        t.setPosition(leash1, mTempRect.left, mTempRect.top)
                .setWindowCrop(leash1, mTempRect.width(), mTempRect.height());
+5 −0
Original line number Diff line number Diff line
@@ -57,4 +57,9 @@ public class SplitState {
    public List<RectF> getLayout(@SplitScreenState int state) {
        return mSplitSpec.getSpec(state);
    }

    /** Returns the layout associated with the current split state. */
    public List<RectF> getCurrentLayout() {
        return getLayout(mState);
    }
}
+2 −1
Original line number Diff line number Diff line
@@ -796,7 +796,8 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler,
                        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                                "  unhandled root taskId=%d", taskInfo.taskId);
                    }
                } else if (TransitionUtil.isDividerBar(change)) {
                } else if (TransitionUtil.isDividerBar(change)
                        || TransitionUtil.isDimLayer(change)) {
                    final RemoteAnimationTarget target = TransitionUtil.newTarget(change,
                            belowLayers - i, info, t, mLeashMap);
                    // Add this as a app and we will separate them on launcher side by window type.
Loading