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

Commit f33e3595 authored by Ben Lin's avatar Ben Lin Committed by Automerger Merge Worker
Browse files

Merge "PiP: support direct entering split from PiP." into sc-v2-dev am: 5574121d

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16119347

Change-Id: Iea8bffc5fa29c3637daf27432c38bba665e8ab04
parents b6519294 5574121d
Loading
Loading
Loading
Loading
+17 −4
Original line number Diff line number Diff line
@@ -65,25 +65,28 @@
    <LinearLayout
        android:id="@+id/top_end_container"
        android:layout_gravity="top|end"
        android:layout_width="wrap_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <ImageButton
            android:id="@+id/settings"
            android:layout_width="@dimen/pip_action_size"
            android:layout_height="@dimen/pip_action_size"
            android:contentDescription="@string/pip_phone_settings"
            android:layout_gravity="top|start"
            android:gravity="center"
            android:src="@drawable/pip_ic_settings"
            android:background="?android:selectableItemBackgroundBorderless" />

        <ImageButton
            android:id="@+id/dismiss"
            android:id="@+id/enter_split"
            android:layout_width="@dimen/pip_action_size"
            android:layout_height="@dimen/pip_action_size"
            android:contentDescription="@string/pip_phone_close"
            android:layout_gravity="top|start"
            android:gravity="center"
            android:src="@drawable/pip_ic_close_white"
            android:contentDescription="@string/pip_phone_enter_split"
            android:src="@drawable/pip_expand"
            android:background="?android:selectableItemBackgroundBorderless" />
    </LinearLayout>

@@ -97,4 +100,14 @@
        android:padding="@dimen/pip_resize_handle_padding"
        android:src="@drawable/pip_resize_handle"
        android:background="?android:selectableItemBackgroundBorderless" />

    <ImageButton
        android:id="@+id/dismiss"
        android:layout_width="@dimen/pip_action_size"
        android:layout_height="@dimen/pip_action_size"
        android:contentDescription="@string/pip_phone_close"
        android:layout_gravity="top|end"
        android:gravity="center"
        android:src="@drawable/pip_ic_close_white"
        android:background="?android:selectableItemBackgroundBorderless" />
</FrameLayout>
+3 −0
Original line number Diff line number Diff line
@@ -24,6 +24,9 @@
    <!-- Label for PIP settings button [CHAR LIMIT=NONE]-->
    <string name="pip_phone_settings">Settings</string>

    <!-- Label for the PIP enter split button [CHAR LIMIT=NONE] -->
    <string name="pip_phone_enter_split">Enter split screen</string>

    <!-- Title of menu shown over picture-in-picture. Used for accessibility. -->
    <string name="pip_menu_title">Menu</string>

+49 −16
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
import com.android.wm.shell.pip.phone.PipMotionHelper;
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.transition.Transitions;

import java.io.PrintWriter;
@@ -126,7 +127,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
    private final int mExitAnimationDuration;
    private final int mCrossFadeAnimationDuration;
    private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
    private final Optional<LegacySplitScreenController> mSplitScreenOptional;
    private final Optional<LegacySplitScreenController> mLegacySplitScreenOptional;
    private final Optional<SplitScreenController> mSplitScreenOptional;
    protected final ShellTaskOrganizer mTaskOrganizer;
    protected final ShellExecutor mMainExecutor;

@@ -252,7 +254,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
            @NonNull PipAnimationController pipAnimationController,
            @NonNull PipSurfaceTransactionHelper surfaceTransactionHelper,
            @NonNull PipTransitionController pipTransitionController,
            Optional<LegacySplitScreenController> splitScreenOptional,
            Optional<LegacySplitScreenController> legacySplitScreenOptional,
            Optional<SplitScreenController> splitScreenOptional,
            @NonNull DisplayController displayController,
            @NonNull PipUiEventLogger pipUiEventLogger,
            @NonNull ShellTaskOrganizer shellTaskOrganizer,
@@ -274,6 +277,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
        mPipAnimationController = pipAnimationController;
        mPipUiEventLoggerLogger = pipUiEventLogger;
        mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
        mLegacySplitScreenOptional = legacySplitScreenOptional;
        mSplitScreenOptional = splitScreenOptional;
        mTaskOrganizer = shellTaskOrganizer;
        mMainExecutor = mainExecutor;
@@ -373,8 +377,11 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
     *   activity render it's final configuration while the Task is still in PiP.
     * - setWindowingMode to undefined at the end of transition
     * @param animationDurationMs duration in millisecond for the exiting PiP transition
     * @param requestEnterSplit whether the enterSplit button is pressed on PiP or not.
     *                             Indicate the user wishes to directly put PiP into split screen
     *                             mode.
     */
    public void exitPip(int animationDurationMs) {
    public void exitPip(int animationDurationMs, boolean requestEnterSplit) {
        if (!mPipTransitionState.isInPip()
                || mPipTransitionState.getTransitionState() == PipTransitionState.EXITING_PIP
                || mToken == null) {
@@ -387,7 +394,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
                PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_EXPAND_TO_FULLSCREEN);
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        final Rect destinationBounds = mPipBoundsState.getDisplayBounds();
        final int direction = syncWithSplitScreenBounds(destinationBounds)
        final int direction = syncWithSplitScreenBounds(destinationBounds, requestEnterSplit)
                ? TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN
                : TRANSITION_DIRECTION_LEAVE_PIP;
        final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
@@ -396,7 +403,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
        // We set to fullscreen here for now, but later it will be set to UNDEFINED for
        // the proper windowing mode to take place. See #applyWindowingModeChangeOnExit.
        wct.setActivityWindowingMode(mToken,
                direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN
                direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN && !requestEnterSplit
                        ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
                        : WINDOWING_MODE_FULLSCREEN);
        wct.setBounds(mToken, destinationBounds);
@@ -435,7 +442,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
        wct.setWindowingMode(mToken, getOutPipWindowingMode());
        // Simply reset the activity mode set prior to the animation running.
        wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
        mSplitScreenOptional.ifPresent(splitScreen -> {
        mLegacySplitScreenOptional.ifPresent(splitScreen -> {
            if (direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN) {
                wct.reparent(mToken, splitScreen.getSecondaryRoot(), true /* onTop */);
            }
@@ -1165,6 +1172,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
            @PipAnimationController.TransitionDirection int direction,
            @PipAnimationController.AnimationType int type) {
        final Rect preResizeBounds = new Rect(mPipBoundsState.getBounds());
        final boolean isPipTopLeft = isPipTopLeft();
        mPipBoundsState.setBounds(destinationBounds);
        if (direction == TRANSITION_DIRECTION_REMOVE_STACK) {
            removePipImmediately();
@@ -1210,10 +1218,10 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
                            null /* callback */, false /* withStartDelay */);
                });
            } else {
                applyFinishBoundsResize(wct, direction);
                applyFinishBoundsResize(wct, direction, isPipTopLeft);
            }
        } else {
            applyFinishBoundsResize(wct, direction);
            applyFinishBoundsResize(wct, direction, isPipTopLeft);
        }

        finishResizeForMenu(destinationBounds);
@@ -1241,7 +1249,11 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
        } else if (isOutPipDirection(direction)) {
            // If we are animating to fullscreen or split screen, then we need to reset the
            // override bounds on the task to ensure that the task "matches" the parent's bounds.
            if (direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN) {
                taskBounds = destinationBounds;
            } else {
                taskBounds = null;
            }
            applyWindowingModeChangeOnExit(wct, direction);
        } else {
            // Just a resize in PIP
@@ -1261,9 +1273,21 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
     * applying it.
     */
    public void applyFinishBoundsResize(@NonNull WindowContainerTransaction wct,
            @PipAnimationController.TransitionDirection int direction) {
            @PipAnimationController.TransitionDirection int direction, boolean wasPipTopLeft) {
        if (direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN) {
            mSplitScreenOptional.get().enterSplitScreen(mTaskInfo.taskId, wasPipTopLeft, wct);
        } else {
            mTaskOrganizer.applyTransaction(wct);
        }
    }

    private boolean isPipTopLeft() {
        final Rect topLeft = new Rect();
        final Rect bottomRight = new Rect();
        mSplitScreenOptional.get().getStageBounds(topLeft, bottomRight);

        return topLeft.contains(mPipBoundsState.getBounds());
    }

    /**
     * The windowing mode to restore to when resizing out of PIP direction. Defaults to undefined
@@ -1347,18 +1371,27 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
    }

    /**
     * Sync with {@link LegacySplitScreenController} on destination bounds if PiP is going to split
     * screen.
     * Sync with {@link LegacySplitScreenController} or {@link SplitScreenController} on destination
     * bounds if PiP is going to split screen.
     *
     * @param destinationBoundsOut contain the updated destination bounds if applicable
     * @return {@code true} if destinationBounds is altered for split screen
     */
    private boolean syncWithSplitScreenBounds(Rect destinationBoundsOut) {
        if (!mSplitScreenOptional.isPresent()) {
    private boolean syncWithSplitScreenBounds(Rect destinationBoundsOut, boolean enterSplit) {
        if (enterSplit && mSplitScreenOptional.isPresent()) {
            final Rect topLeft = new Rect();
            final Rect bottomRight = new Rect();
            mSplitScreenOptional.get().getStageBounds(topLeft, bottomRight);
            final boolean isPipTopLeft = isPipTopLeft();
            destinationBoundsOut.set(isPipTopLeft ? topLeft : bottomRight);
            return true;
        }

        if (!mLegacySplitScreenOptional.isPresent()) {
            return false;
        }

        LegacySplitScreenController legacySplitScreen = mSplitScreenOptional.get();
        LegacySplitScreenController legacySplitScreen = mLegacySplitScreenOptional.get();
        if (!legacySplitScreen.isDividerVisible()) {
            // fail early if system is not in split screen mode
            return false;
+9 −0
Original line number Diff line number Diff line
@@ -95,6 +95,11 @@ public class PhonePipMenuController implements PipMenuController {
         * Called when the PIP requested to show the menu.
         */
        void onPipShowMenu();

        /**
         * Called when the PIP requested to enter Split.
         */
        void onEnterSplit();
    }

    private final Matrix mMoveTransform = new Matrix();
@@ -458,6 +463,10 @@ public class PhonePipMenuController implements PipMenuController {
        mListeners.forEach(Listener::onPipDismiss);
    }

    void onEnterSplit() {
        mListeners.forEach(Listener::onEnterSplit);
    }

    /**
     * @return the best set of actions to show in the PiP menu.
     */
+1 −1
Original line number Diff line number Diff line
@@ -151,7 +151,7 @@ public class PipAccessibilityInteractionConnection {
                        result = true;
                        break;
                    case AccessibilityNodeInfo.ACTION_EXPAND:
                        mMotionHelper.expandLeavePip();
                        mMotionHelper.expandLeavePip(false /* skipAnimation */);
                        result = true;
                        break;
                    default:
Loading