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

Commit 54fed092 authored by Hongwei Wang's avatar Hongwei Wang Committed by Android (Google) Code Review
Browse files

Merge "Fix the transition from Split to PiP" into sc-v2-dev

parents ecc936a0 d4848611
Loading
Loading
Loading
Loading
+89 −29
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@ package android.window;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.graphics.Matrix;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable;
@@ -34,9 +35,10 @@ import java.util.Objects;
 * @hide
 * @hide
 */
 */
public final class PictureInPictureSurfaceTransaction implements Parcelable {
public final class PictureInPictureSurfaceTransaction implements Parcelable {
    private static final float NOT_SET = -1f;


    public final float mPositionX;
    public final float mAlpha;
    public final float mPositionY;
    public final PointF mPosition;


    public final float[] mFloat9;
    public final float[] mFloat9;


@@ -45,33 +47,37 @@ public final class PictureInPictureSurfaceTransaction implements Parcelable {


    public final float mCornerRadius;
    public final float mCornerRadius;


    private final Rect mWindowCrop = new Rect();
    private final Rect mWindowCrop;


    public PictureInPictureSurfaceTransaction(Parcel in) {
    private PictureInPictureSurfaceTransaction(Parcel in) {
        mPositionX = in.readFloat();
        mAlpha = in.readFloat();
        mPositionY = in.readFloat();
        mPosition = in.readTypedObject(PointF.CREATOR);
        mFloat9 = new float[9];
        mFloat9 = new float[9];
        in.readFloatArray(mFloat9);
        in.readFloatArray(mFloat9);
        mRotation = in.readFloat();
        mRotation = in.readFloat();
        mCornerRadius = in.readFloat();
        mCornerRadius = in.readFloat();
        mWindowCrop.set(Objects.requireNonNull(in.readTypedObject(Rect.CREATOR)));
        mWindowCrop = in.readTypedObject(Rect.CREATOR);
    }
    }


    public PictureInPictureSurfaceTransaction(float positionX, float positionY,
    private PictureInPictureSurfaceTransaction(float alpha, @Nullable PointF position,
            float[] float9, float rotation, float cornerRadius,
            @Nullable float[] float9, float rotation, float cornerRadius,
            @Nullable Rect windowCrop) {
            @Nullable Rect windowCrop) {
        mPositionX = positionX;
        mAlpha = alpha;
        mPositionY = positionY;
        mPosition = position;
        if (float9 == null) {
            mFloat9 = new float[9];
            Matrix.IDENTITY_MATRIX.getValues(mFloat9);
            mRotation = 0;
        } else {
            mFloat9 = Arrays.copyOf(float9, 9);
            mFloat9 = Arrays.copyOf(float9, 9);
            mRotation = rotation;
            mRotation = rotation;
        mCornerRadius = cornerRadius;
        if (windowCrop != null) {
            mWindowCrop.set(windowCrop);
        }
        }
        mCornerRadius = cornerRadius;
        mWindowCrop = (windowCrop == null) ? null : new Rect(windowCrop);
    }
    }


    public PictureInPictureSurfaceTransaction(PictureInPictureSurfaceTransaction other) {
    public PictureInPictureSurfaceTransaction(PictureInPictureSurfaceTransaction other) {
        this(other.mPositionX, other.mPositionY,
        this(other.mAlpha, other.mPosition,
                other.mFloat9, other.mRotation, other.mCornerRadius, other.mWindowCrop);
                other.mFloat9, other.mRotation, other.mCornerRadius, other.mWindowCrop);
    }
    }


@@ -82,13 +88,18 @@ public final class PictureInPictureSurfaceTransaction implements Parcelable {
        return matrix;
        return matrix;
    }
    }


    /** @return {@code true} if this transaction contains setting corner radius. */
    public boolean hasCornerRadiusSet() {
        return mCornerRadius > 0;
    }

    @Override
    @Override
    public boolean equals(Object o) {
    public boolean equals(Object o) {
        if (this == o) return true;
        if (this == o) return true;
        if (!(o instanceof PictureInPictureSurfaceTransaction)) return false;
        if (!(o instanceof PictureInPictureSurfaceTransaction)) return false;
        PictureInPictureSurfaceTransaction that = (PictureInPictureSurfaceTransaction) o;
        PictureInPictureSurfaceTransaction that = (PictureInPictureSurfaceTransaction) o;
        return Objects.equals(mPositionX, that.mPositionX)
        return Objects.equals(mAlpha, that.mAlpha)
                && Objects.equals(mPositionY, that.mPositionY)
                && Objects.equals(mPosition, that.mPosition)
                && Arrays.equals(mFloat9, that.mFloat9)
                && Arrays.equals(mFloat9, that.mFloat9)
                && Objects.equals(mRotation, that.mRotation)
                && Objects.equals(mRotation, that.mRotation)
                && Objects.equals(mCornerRadius, that.mCornerRadius)
                && Objects.equals(mCornerRadius, that.mCornerRadius)
@@ -97,7 +108,7 @@ public final class PictureInPictureSurfaceTransaction implements Parcelable {


    @Override
    @Override
    public int hashCode() {
    public int hashCode() {
        return Objects.hash(mPositionX, mPositionY, Arrays.hashCode(mFloat9),
        return Objects.hash(mAlpha, mPosition, Arrays.hashCode(mFloat9),
                mRotation, mCornerRadius, mWindowCrop);
                mRotation, mCornerRadius, mWindowCrop);
    }
    }


@@ -108,8 +119,8 @@ public final class PictureInPictureSurfaceTransaction implements Parcelable {


    @Override
    @Override
    public void writeToParcel(Parcel out, int flags) {
    public void writeToParcel(Parcel out, int flags) {
        out.writeFloat(mPositionX);
        out.writeFloat(mAlpha);
        out.writeFloat(mPositionY);
        out.writeTypedObject(mPosition, 0 /* flags */);
        out.writeFloatArray(mFloat9);
        out.writeFloatArray(mFloat9);
        out.writeFloat(mRotation);
        out.writeFloat(mRotation);
        out.writeFloat(mCornerRadius);
        out.writeFloat(mCornerRadius);
@@ -120,8 +131,8 @@ public final class PictureInPictureSurfaceTransaction implements Parcelable {
    public String toString() {
    public String toString() {
        final Matrix matrix = getMatrix();
        final Matrix matrix = getMatrix();
        return "PictureInPictureSurfaceTransaction("
        return "PictureInPictureSurfaceTransaction("
                + " posX=" + mPositionX
                + " alpha=" + mAlpha
                + " posY=" + mPositionY
                + " position=" + mPosition
                + " matrix=" + matrix.toShortString()
                + " matrix=" + matrix.toShortString()
                + " rotation=" + mRotation
                + " rotation=" + mRotation
                + " cornerRadius=" + mCornerRadius
                + " cornerRadius=" + mCornerRadius
@@ -134,11 +145,20 @@ public final class PictureInPictureSurfaceTransaction implements Parcelable {
            @NonNull SurfaceControl surfaceControl,
            @NonNull SurfaceControl surfaceControl,
            @NonNull SurfaceControl.Transaction tx) {
            @NonNull SurfaceControl.Transaction tx) {
        final Matrix matrix = surfaceTransaction.getMatrix();
        final Matrix matrix = surfaceTransaction.getMatrix();
        tx.setMatrix(surfaceControl, matrix, new float[9])
        tx.setMatrix(surfaceControl, matrix, new float[9]);
                .setPosition(surfaceControl,
        if (surfaceTransaction.mPosition != null) {
                        surfaceTransaction.mPositionX, surfaceTransaction.mPositionY)
            tx.setPosition(surfaceControl,
                .setWindowCrop(surfaceControl, surfaceTransaction.mWindowCrop)
                    surfaceTransaction.mPosition.x, surfaceTransaction.mPosition.y);
                .setCornerRadius(surfaceControl, surfaceTransaction.mCornerRadius);
        }
        if (surfaceTransaction.mWindowCrop != null) {
            tx.setWindowCrop(surfaceControl, surfaceTransaction.mWindowCrop);
        }
        if (surfaceTransaction.hasCornerRadiusSet()) {
            tx.setCornerRadius(surfaceControl, surfaceTransaction.mCornerRadius);
        }
        if (surfaceTransaction.mAlpha != NOT_SET) {
            tx.setAlpha(surfaceControl, surfaceTransaction.mAlpha);
        }
    }
    }


    public static final @android.annotation.NonNull Creator<PictureInPictureSurfaceTransaction>
    public static final @android.annotation.NonNull Creator<PictureInPictureSurfaceTransaction>
@@ -151,4 +171,44 @@ public final class PictureInPictureSurfaceTransaction implements Parcelable {
                    return new PictureInPictureSurfaceTransaction[size];
                    return new PictureInPictureSurfaceTransaction[size];
                }
                }
            };
            };

    public static class Builder {
        private float mAlpha = NOT_SET;
        private PointF mPosition;
        private float[] mFloat9;
        private float mRotation;
        private float mCornerRadius = NOT_SET;
        private Rect mWindowCrop;

        public Builder setAlpha(float alpha) {
            mAlpha = alpha;
            return this;
        }

        public Builder setPosition(float x, float y) {
            mPosition = new PointF(x, y);
            return this;
        }

        public Builder setTransform(@NonNull float[] float9, float rotation) {
            mFloat9 = Arrays.copyOf(float9, 9);
            mRotation = rotation;
            return this;
        }

        public Builder setCornerRadius(float cornerRadius) {
            mCornerRadius = cornerRadius;
            return this;
        }

        public Builder setWindowCrop(@NonNull Rect windowCrop) {
            mWindowCrop = new Rect(windowCrop);
            return this;
        }

        public PictureInPictureSurfaceTransaction build() {
            return new PictureInPictureSurfaceTransaction(mAlpha, mPosition,
                    mFloat9, mRotation, mCornerRadius, mWindowCrop);
        }
    }
}
}
+4 −0
Original line number Original line Diff line number Diff line
@@ -102,6 +102,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
    static final int EXIT_REASON_ROOT_TASK_VANISHED = 6;
    static final int EXIT_REASON_ROOT_TASK_VANISHED = 6;
    static final int EXIT_REASON_SCREEN_LOCKED = 7;
    static final int EXIT_REASON_SCREEN_LOCKED = 7;
    static final int EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP = 8;
    static final int EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP = 8;
    static final int EXIT_REASON_CHILD_TASK_ENTER_PIP = 9;
    @IntDef(value = {
    @IntDef(value = {
            EXIT_REASON_UNKNOWN,
            EXIT_REASON_UNKNOWN,
            EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW,
            EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW,
@@ -112,6 +113,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
            EXIT_REASON_ROOT_TASK_VANISHED,
            EXIT_REASON_ROOT_TASK_VANISHED,
            EXIT_REASON_SCREEN_LOCKED,
            EXIT_REASON_SCREEN_LOCKED,
            EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP,
            EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP,
            EXIT_REASON_CHILD_TASK_ENTER_PIP,
    })
    })
    @Retention(RetentionPolicy.SOURCE)
    @Retention(RetentionPolicy.SOURCE)
    @interface ExitReason{}
    @interface ExitReason{}
@@ -406,6 +408,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
                return "APP_FINISHED";
                return "APP_FINISHED";
            case EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW:
            case EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW:
                return "APP_DOES_NOT_SUPPORT_MULTIWINDOW";
                return "APP_DOES_NOT_SUPPORT_MULTIWINDOW";
            case EXIT_REASON_CHILD_TASK_ENTER_PIP:
                return "CHILD_TASK_ENTER_PIP";
            default:
            default:
                return "unknown reason, reason int = " + exitReason;
                return "unknown reason, reason int = " + exitReason;
        }
        }
+19 −2
Original line number Original line Diff line number Diff line
@@ -35,6 +35,7 @@ import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
import static com.android.wm.shell.splitscreen.SplitScreen.stageTypeToString;
import static com.android.wm.shell.splitscreen.SplitScreen.stageTypeToString;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_APP_FINISHED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_APP_FINISHED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_CHILD_TASK_ENTER_PIP;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DEVICE_FOLDED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DEVICE_FOLDED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DRAG_DIVIDER;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DRAG_DIVIDER;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RETURN_HOME;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RETURN_HOME;
@@ -629,8 +630,12 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        });
        });
        mShouldUpdateRecents = false;
        mShouldUpdateRecents = false;


        mSideStage.removeAllTasks(wct, childrenToTop == mSideStage);
        // When the exit split-screen is caused by one of the task enters auto pip,
        mMainStage.deactivate(wct, childrenToTop == mMainStage);
        // we want the tasks to be put to bottom instead of top, otherwise it will end up
        // a fullscreen plus a pinned task instead of pinned only at the end of the transition.
        final boolean fromEnteringPip = exitReason == EXIT_REASON_CHILD_TASK_ENTER_PIP;
        mSideStage.removeAllTasks(wct, !fromEnteringPip && childrenToTop == mSideStage);
        mMainStage.deactivate(wct, !fromEnteringPip && childrenToTop == mMainStage);
        mTaskOrganizer.applyTransaction(wct);
        mTaskOrganizer.applyTransaction(wct);
        mSyncQueue.runInSync(t -> t
        mSyncQueue.runInSync(t -> t
                .setWindowCrop(mMainStage.mRootLeash, null)
                .setWindowCrop(mMainStage.mRootLeash, null)
@@ -660,6 +665,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            case EXIT_REASON_DRAG_DIVIDER:
            case EXIT_REASON_DRAG_DIVIDER:
            // Either of the split apps have finished
            // Either of the split apps have finished
            case EXIT_REASON_APP_FINISHED:
            case EXIT_REASON_APP_FINISHED:
            // One of the children enters PiP
            case EXIT_REASON_CHILD_TASK_ENTER_PIP:
                return true;
                return true;
            default:
            default:
                return false;
                return false;
@@ -749,6 +756,11 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        }
        }
    }
    }


    private void onStageChildTaskEnterPip(StageListenerImpl stageListener, int taskId) {
        exitSplitScreen(stageListener == mMainStageListener ? mMainStage : mSideStage,
                EXIT_REASON_CHILD_TASK_ENTER_PIP);
    }

    private void updateRecentTasksSplitPair() {
    private void updateRecentTasksSplitPair() {
        if (!mShouldUpdateRecents) {
        if (!mShouldUpdateRecents) {
            return;
            return;
@@ -1436,6 +1448,11 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            StageCoordinator.this.onStageChildTaskStatusChanged(this, taskId, present, visible);
            StageCoordinator.this.onStageChildTaskStatusChanged(this, taskId, present, visible);
        }
        }


        @Override
        public void onChildTaskEnterPip(int taskId) {
            StageCoordinator.this.onStageChildTaskEnterPip(this, taskId);
        }

        @Override
        @Override
        public void onRootTaskVanished() {
        public void onRootTaskVanished() {
            reset();
            reset();
+6 −0
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;


import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
@@ -73,6 +74,8 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {


        void onChildTaskStatusChanged(int taskId, boolean present, boolean visible);
        void onChildTaskStatusChanged(int taskId, boolean present, boolean visible);


        void onChildTaskEnterPip(int taskId);

        void onRootTaskVanished();
        void onRootTaskVanished();


        void onNoLongerSupportMultiWindow();
        void onNoLongerSupportMultiWindow();
@@ -256,6 +259,9 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
            mChildrenTaskInfo.remove(taskId);
            mChildrenTaskInfo.remove(taskId);
            mChildrenLeashes.remove(taskId);
            mChildrenLeashes.remove(taskId);
            mCallbacks.onChildTaskStatusChanged(taskId, false /* present */, taskInfo.isVisible);
            mCallbacks.onChildTaskStatusChanged(taskId, false /* present */, taskInfo.isVisible);
            if (taskInfo.getWindowingMode() == WINDOWING_MODE_PINNED) {
                mCallbacks.onChildTaskEnterPip(taskId);
            }
            if (ENABLE_SHELL_TRANSITIONS) {
            if (ENABLE_SHELL_TRANSITIONS) {
                // Status is managed/synchronized by the transition lifecycle.
                // Status is managed/synchronized by the transition lifecycle.
                return;
                return;
+18 −8
Original line number Original line Diff line number Diff line
@@ -53,8 +53,8 @@ public class PipSurfaceTransactionHelper {
        tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
        tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
                .setPosition(leash, positionX, positionY)
                .setPosition(leash, positionX, positionY)
                .setCornerRadius(leash, cornerRadius);
                .setCornerRadius(leash, cornerRadius);
        return new PictureInPictureSurfaceTransaction(
        return newPipSurfaceTransaction(positionX, positionY,
                positionX, positionY, mTmpFloat9, 0 /* rotation */, cornerRadius, sourceBounds);
                mTmpFloat9, 0 /* rotation */, cornerRadius, sourceBounds);
    }
    }


    public PictureInPictureSurfaceTransaction scale(
    public PictureInPictureSurfaceTransaction scale(
@@ -70,8 +70,8 @@ public class PipSurfaceTransactionHelper {
        tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
        tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
                .setPosition(leash, positionX, positionY)
                .setPosition(leash, positionX, positionY)
                .setCornerRadius(leash, cornerRadius);
                .setCornerRadius(leash, cornerRadius);
        return new PictureInPictureSurfaceTransaction(
        return newPipSurfaceTransaction(positionX, positionY,
                positionX, positionY, mTmpFloat9, degree, cornerRadius, sourceBounds);
                mTmpFloat9, degree, cornerRadius, sourceBounds);
    }
    }


    public PictureInPictureSurfaceTransaction scaleAndCrop(
    public PictureInPictureSurfaceTransaction scaleAndCrop(
@@ -93,8 +93,8 @@ public class PipSurfaceTransactionHelper {
                .setWindowCrop(leash, mTmpDestinationRect)
                .setWindowCrop(leash, mTmpDestinationRect)
                .setPosition(leash, left, top)
                .setPosition(leash, left, top)
                .setCornerRadius(leash, cornerRadius);
                .setCornerRadius(leash, cornerRadius);
        return new PictureInPictureSurfaceTransaction(
        return newPipSurfaceTransaction(left, top,
                left, top, mTmpFloat9, 0 /* rotation */, cornerRadius, mTmpDestinationRect);
                mTmpFloat9, 0 /* rotation */, cornerRadius, mTmpDestinationRect);
    }
    }


    public PictureInPictureSurfaceTransaction scaleAndRotate(
    public PictureInPictureSurfaceTransaction scaleAndRotate(
@@ -125,8 +125,7 @@ public class PipSurfaceTransactionHelper {
                .setWindowCrop(leash, mTmpDestinationRect)
                .setWindowCrop(leash, mTmpDestinationRect)
                .setPosition(leash, adjustedPositionX, adjustedPositionY)
                .setPosition(leash, adjustedPositionX, adjustedPositionY)
                .setCornerRadius(leash, cornerRadius);
                .setCornerRadius(leash, cornerRadius);
        return new PictureInPictureSurfaceTransaction(
        return newPipSurfaceTransaction(adjustedPositionX, adjustedPositionY,
                adjustedPositionX, adjustedPositionY,
                mTmpFloat9, degree, cornerRadius, mTmpDestinationRect);
                mTmpFloat9, degree, cornerRadius, mTmpDestinationRect);
    }
    }


@@ -137,6 +136,17 @@ public class PipSurfaceTransactionHelper {
        return mCornerRadius * scale;
        return mCornerRadius * scale;
    }
    }


    private static PictureInPictureSurfaceTransaction newPipSurfaceTransaction(
            float posX, float posY, float[] float9, float rotation, float cornerRadius,
            Rect windowCrop) {
        return new PictureInPictureSurfaceTransaction.Builder()
                .setPosition(posX, posY)
                .setTransform(float9, rotation)
                .setCornerRadius(cornerRadius)
                .setWindowCrop(windowCrop)
                .build();
    }

    /** @return {@link SurfaceControl.Transaction} instance with vsync-id */
    /** @return {@link SurfaceControl.Transaction} instance with vsync-id */
    public static SurfaceControl.Transaction newSurfaceControlTransaction() {
    public static SurfaceControl.Transaction newSurfaceControlTransaction() {
        final SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
        final SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
Loading