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 Diff line number Diff line
@@ -19,6 +19,7 @@ package android.window;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
@@ -34,9 +35,10 @@ import java.util.Objects;
 * @hide
 */
public final class PictureInPictureSurfaceTransaction implements Parcelable {
    private static final float NOT_SET = -1f;

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

    public final float[] mFloat9;

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

    public final float mCornerRadius;

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

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

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

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

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

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

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

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

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

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeFloat(mPositionX);
        out.writeFloat(mPositionY);
        out.writeFloat(mAlpha);
        out.writeTypedObject(mPosition, 0 /* flags */);
        out.writeFloatArray(mFloat9);
        out.writeFloat(mRotation);
        out.writeFloat(mCornerRadius);
@@ -120,8 +131,8 @@ public final class PictureInPictureSurfaceTransaction implements Parcelable {
    public String toString() {
        final Matrix matrix = getMatrix();
        return "PictureInPictureSurfaceTransaction("
                + " posX=" + mPositionX
                + " posY=" + mPositionY
                + " alpha=" + mAlpha
                + " position=" + mPosition
                + " matrix=" + matrix.toShortString()
                + " rotation=" + mRotation
                + " cornerRadius=" + mCornerRadius
@@ -134,11 +145,20 @@ public final class PictureInPictureSurfaceTransaction implements Parcelable {
            @NonNull SurfaceControl surfaceControl,
            @NonNull SurfaceControl.Transaction tx) {
        final Matrix matrix = surfaceTransaction.getMatrix();
        tx.setMatrix(surfaceControl, matrix, new float[9])
                .setPosition(surfaceControl,
                        surfaceTransaction.mPositionX, surfaceTransaction.mPositionY)
                .setWindowCrop(surfaceControl, surfaceTransaction.mWindowCrop)
                .setCornerRadius(surfaceControl, surfaceTransaction.mCornerRadius);
        tx.setMatrix(surfaceControl, matrix, new float[9]);
        if (surfaceTransaction.mPosition != null) {
            tx.setPosition(surfaceControl,
                    surfaceTransaction.mPosition.x, surfaceTransaction.mPosition.y);
        }
        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>
@@ -151,4 +171,44 @@ public final class PictureInPictureSurfaceTransaction implements Parcelable {
                    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 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_SCREEN_LOCKED = 7;
    static final int EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP = 8;
    static final int EXIT_REASON_CHILD_TASK_ENTER_PIP = 9;
    @IntDef(value = {
            EXIT_REASON_UNKNOWN,
            EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW,
@@ -112,6 +113,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
            EXIT_REASON_ROOT_TASK_VANISHED,
            EXIT_REASON_SCREEN_LOCKED,
            EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP,
            EXIT_REASON_CHILD_TASK_ENTER_PIP,
    })
    @Retention(RetentionPolicy.SOURCE)
    @interface ExitReason{}
@@ -406,6 +408,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
                return "APP_FINISHED";
            case EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW:
                return "APP_DOES_NOT_SUPPORT_MULTIWINDOW";
            case EXIT_REASON_CHILD_TASK_ENTER_PIP:
                return "CHILD_TASK_ENTER_PIP";
            default:
                return "unknown reason, reason int = " + exitReason;
        }
+19 −2
Original line number 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.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_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_DRAG_DIVIDER;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RETURN_HOME;
@@ -629,8 +630,12 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        });
        mShouldUpdateRecents = false;

        mSideStage.removeAllTasks(wct, childrenToTop == mSideStage);
        mMainStage.deactivate(wct, childrenToTop == mMainStage);
        // When the exit split-screen is caused by one of the task enters auto pip,
        // 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);
        mSyncQueue.runInSync(t -> t
                .setWindowCrop(mMainStage.mRootLeash, null)
@@ -660,6 +665,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            case EXIT_REASON_DRAG_DIVIDER:
            // Either of the split apps have finished
            case EXIT_REASON_APP_FINISHED:
            // One of the children enters PiP
            case EXIT_REASON_CHILD_TASK_ENTER_PIP:
                return true;
            default:
                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() {
        if (!mShouldUpdateRecents) {
            return;
@@ -1436,6 +1448,11 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            StageCoordinator.this.onStageChildTaskStatusChanged(this, taskId, present, visible);
        }

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

        @Override
        public void onRootTaskVanished() {
            reset();
+6 −0
Original line number 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.WINDOWING_MODE_FULLSCREEN;
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 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 onChildTaskEnterPip(int taskId);

        void onRootTaskVanished();

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

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

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

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

@@ -137,6 +136,17 @@ public class PipSurfaceTransactionHelper {
        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 */
    public static SurfaceControl.Transaction newSurfaceControlTransaction() {
        final SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
Loading