diff options
16 files changed, 172 insertions, 73 deletions
diff --git a/libs/WindowManager/Shell/res/layout/pip_menu.xml b/libs/WindowManager/Shell/res/layout/pip_menu.xml index 9fe024748610..7dc2f31e9871 100644 --- a/libs/WindowManager/Shell/res/layout/pip_menu.xml +++ b/libs/WindowManager/Shell/res/layout/pip_menu.xml @@ -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> diff --git a/libs/WindowManager/Shell/res/values/strings.xml b/libs/WindowManager/Shell/res/values/strings.xml index 764854af3b3f..c88fc16e218e 100644 --- a/libs/WindowManager/Shell/res/values/strings.xml +++ b/libs/WindowManager/Shell/res/values/strings.xml @@ -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> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java index b6e5804a64dd..6cc5f09827af 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java @@ -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. - taskBounds = null; + if (direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN) { + taskBounds = destinationBounds; + } else { + taskBounds = null; + } applyWindowingModeChangeOnExit(wct, direction); } else { // Just a resize in PIP @@ -1261,8 +1273,20 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, * applying it. */ public void applyFinishBoundsResize(@NonNull WindowContainerTransaction wct, - @PipAnimationController.TransitionDirection int direction) { - mTaskOrganizer.applyTransaction(wct); + @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()); } /** @@ -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; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java index ae8c1b6f8c1a..5687f4d62444 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java @@ -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. */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipAccessibilityInteractionConnection.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipAccessibilityInteractionConnection.java index 47a8c67a22e6..69ae45d12795 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipAccessibilityInteractionConnection.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipAccessibilityInteractionConnection.java @@ -151,7 +151,7 @@ public class PipAccessibilityInteractionConnection { result = true; break; case AccessibilityNodeInfo.ACTION_EXPAND: - mMotionHelper.expandLeavePip(); + mMotionHelper.expandLeavePip(false /* skipAnimation */); result = true; break; default: diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java index 51eea370b98d..61a6dbafe3d8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java @@ -482,7 +482,8 @@ public class PipController implements PipTransitionController.PipTransitionCallb false /* fromShelfAdjustment */, wct /* windowContainerTransaction */); if (wct != null) { - mPipTaskOrganizer.applyFinishBoundsResize(wct, TRANSITION_DIRECTION_SAME); + mPipTaskOrganizer.applyFinishBoundsResize(wct, TRANSITION_DIRECTION_SAME, + false /* wasPipTopLeft */); } }; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuIconsAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuIconsAlgorithm.java index 3eeba6eb5366..06446573840c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuIconsAlgorithm.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuIconsAlgorithm.java @@ -18,8 +18,6 @@ package com.android.wm.shell.pip.phone; import android.content.Context; import android.graphics.Rect; -import android.util.Log; -import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; @@ -34,6 +32,7 @@ public class PipMenuIconsAlgorithm { protected ViewGroup mViewRoot; protected ViewGroup mTopEndContainer; protected View mDragHandle; + protected View mEnterSplitButton; protected View mSettingsButton; protected View mDismissButton; @@ -44,14 +43,13 @@ public class PipMenuIconsAlgorithm { * Bind the necessary views. */ public void bindViews(ViewGroup viewRoot, ViewGroup topEndContainer, View dragHandle, - View settingsButton, View dismissButton) { + View enterSplitButton, View settingsButton, View dismissButton) { mViewRoot = viewRoot; mTopEndContainer = topEndContainer; mDragHandle = dragHandle; + mEnterSplitButton = enterSplitButton; mSettingsButton = settingsButton; mDismissButton = dismissButton; - - bindInitialViewState(); } /** @@ -72,22 +70,4 @@ public class PipMenuIconsAlgorithm { v.setLayoutParams(params); } } - - /** Calculate the initial state of the menu icons. Called when the menu is first created. */ - private void bindInitialViewState() { - if (mViewRoot == null || mTopEndContainer == null || mDragHandle == null - || mSettingsButton == null || mDismissButton == null) { - Log.e(TAG, "One of the required views is null."); - return; - } - // The menu view layout starts out with the settings button aligned at the top|end of the - // view group next to the dismiss button. On phones, the settings button should be aligned - // to the top|start of the view, so move it to parent view group to then align it to the - // top|start of the menu. - mTopEndContainer.removeView(mSettingsButton); - mViewRoot.addView(mSettingsButton); - - setLayoutGravity(mDragHandle, Gravity.START | Gravity.TOP); - setLayoutGravity(mSettingsButton, Gravity.START | Gravity.TOP); - } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java index 8ef2b6b12030..7bbebe5bf287 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java @@ -99,7 +99,7 @@ public class PipMenuView extends FrameLayout { private static final float MENU_BACKGROUND_ALPHA = 0.3f; private static final float DISABLED_ACTION_ALPHA = 0.54f; - private static final boolean ENABLE_RESIZE_HANDLE = false; + private static final boolean ENABLE_ENTER_SPLIT = false; private int mMenuState; private boolean mAllowMenuTimeout = true; @@ -139,7 +139,7 @@ public class PipMenuView extends FrameLayout { protected View mViewRoot; protected View mSettingsButton; protected View mDismissButton; - protected View mResizeHandle; + protected View mEnterSplitButton; protected View mTopEndContainer; protected PipMenuIconsAlgorithm mPipMenuIconsAlgorithm; @@ -177,14 +177,23 @@ public class PipMenuView extends FrameLayout { } }); - mResizeHandle = findViewById(R.id.resize_handle); - mResizeHandle.setAlpha(0); + mEnterSplitButton = findViewById(R.id.enter_split); + mEnterSplitButton.setAlpha(0); + mEnterSplitButton.setOnClickListener(v -> { + if (mMenuContainer.getAlpha() != 0) { + enterSplit(); + } + }); + + findViewById(R.id.resize_handle).setAlpha(0); + mActionsGroup = findViewById(R.id.actions_group); mBetweenActionPaddingLand = getResources().getDimensionPixelSize( R.dimen.pip_between_action_padding_land); mPipMenuIconsAlgorithm = new PipMenuIconsAlgorithm(mContext); mPipMenuIconsAlgorithm.bindViews((ViewGroup) mViewRoot, (ViewGroup) mTopEndContainer, - mResizeHandle, mSettingsButton, mDismissButton); + findViewById(R.id.resize_handle), mEnterSplitButton, mSettingsButton, + mDismissButton); mDismissFadeOutDurationMs = context.getResources() .getInteger(R.integer.config_pipExitAnimationDuration); @@ -268,14 +277,13 @@ public class PipMenuView extends FrameLayout { mSettingsButton.getAlpha(), 1f); ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA, mDismissButton.getAlpha(), 1f); - ObjectAnimator resizeAnim = ObjectAnimator.ofFloat(mResizeHandle, View.ALPHA, - mResizeHandle.getAlpha(), - ENABLE_RESIZE_HANDLE && showResizeHandle ? 1f : 0f); + ObjectAnimator enterSplitAnim = ObjectAnimator.ofFloat(mEnterSplitButton, View.ALPHA, + mEnterSplitButton.getAlpha(), ENABLE_ENTER_SPLIT ? 1f : 0f); if (menuState == MENU_STATE_FULL) { mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim, - resizeAnim); + enterSplitAnim); } else { - mMenuContainerAnimator.playTogether(resizeAnim); + mMenuContainerAnimator.playTogether(enterSplitAnim); } mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_IN); mMenuContainerAnimator.setDuration(ANIMATION_HIDE_DURATION_MS); @@ -328,7 +336,7 @@ public class PipMenuView extends FrameLayout { mMenuContainer.setAlpha(0f); mSettingsButton.setAlpha(0f); mDismissButton.setAlpha(0f); - mResizeHandle.setAlpha(0f); + mEnterSplitButton.setAlpha(0f); } void pokeMenu() { @@ -368,9 +376,10 @@ public class PipMenuView extends FrameLayout { mSettingsButton.getAlpha(), 0f); ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA, mDismissButton.getAlpha(), 0f); - ObjectAnimator resizeAnim = ObjectAnimator.ofFloat(mResizeHandle, View.ALPHA, - mResizeHandle.getAlpha(), 0f); - mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim, resizeAnim); + ObjectAnimator enterSplitAnim = ObjectAnimator.ofFloat(mEnterSplitButton, View.ALPHA, + mEnterSplitButton.getAlpha(), 0f); + mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim, + enterSplitAnim); mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_OUT); mMenuContainerAnimator.setDuration(getFadeOutDuration(animationType)); mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() { @@ -522,6 +531,14 @@ public class PipMenuView extends FrameLayout { } } + private void enterSplit() { + // Do not notify menu visibility when hiding the menu, the controller will do this when it + // handles the message + hideMenu(mController::onEnterSplit, false /* notifyMenuVisibility */, true /* resize */, + ANIM_TYPE_HIDE); + } + + private void showSettings() { final Pair<ComponentName, Integer> topPipActivityInfo = PipUtils.getTopPipActivity(mContext); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java index c42750d62dd4..96fd59f0c911 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java @@ -337,22 +337,29 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, * Resizes the pinned stack back to unknown windowing mode, which could be freeform or * * fullscreen depending on the display area's windowing mode. */ - void expandLeavePip() { - expandLeavePip(false /* skipAnimation */); + void expandLeavePip(boolean skipAnimation) { + expandLeavePip(skipAnimation, false /* enterSplit */); + } + + /** + * Resizes the pinned task to split-screen mode. + */ + void expandIntoSplit() { + expandLeavePip(false, true /* enterSplit */); } /** * Resizes the pinned stack back to unknown windowing mode, which could be freeform or * fullscreen depending on the display area's windowing mode. */ - void expandLeavePip(boolean skipAnimation) { + private void expandLeavePip(boolean skipAnimation, boolean enterSplit) { if (DEBUG) { Log.d(TAG, "exitPip: skipAnimation=" + skipAnimation + " callers=\n" + Debug.getCallers(5, " ")); } cancelPhysicsAnimation(); mMenuController.hideMenu(ANIM_TYPE_NONE, false /* resize */); - mPipTaskOrganizer.exitPip(skipAnimation ? 0 : LEAVE_PIP_DURATION); + mPipTaskOrganizer.exitPip(skipAnimation ? 0 : LEAVE_PIP_DURATION, enterSplit); } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java index 9f2f6a575aca..570fd5eab9f6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java @@ -139,7 +139,12 @@ public class PipTouchHandler { @Override public void onPipExpand() { - mMotionHelper.expandLeavePip(); + mMotionHelper.expandLeavePip(false /* skipAnimation */); + } + + @Override + public void onEnterSplit() { + mMotionHelper.expandIntoSplit(); } @Override @@ -899,7 +904,7 @@ public class PipTouchHandler { // Expand to fullscreen if this is a double tap // the PiP should be frozen until the transition ends setTouchEnabled(false); - mMotionHelper.expandLeavePip(); + mMotionHelper.expandLeavePip(false /* skipAnimation */); } } else if (mMenuState != MENU_STATE_FULL) { if (mPipBoundsState.isStashed()) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java index a2e9b64046fd..00083d986dbe 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java @@ -219,7 +219,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal public void movePipToFullscreen() { if (DEBUG) Log.d(TAG, "movePipToFullscreen(), state=" + stateToName(mState)); - mPipTaskOrganizer.exitPip(mResizeAnimationDuration); + mPipTaskOrganizer.exitPip(mResizeAnimationDuration, false /* requestEnterSplit */); onPipDisappeared(); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java index 14a6574e51a7..dbd0ff831073 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java @@ -160,11 +160,25 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, return moveToSideStage(task, sideStagePosition); } + public boolean moveToSideStage(int taskId, @SplitPosition int sideStagePosition, + WindowContainerTransaction wct) { + final ActivityManager.RunningTaskInfo task = mTaskOrganizer.getRunningTaskInfo(taskId); + if (task == null) { + throw new IllegalArgumentException("Unknown taskId" + taskId); + } + return moveToSideStage(task, sideStagePosition, wct); + } + public boolean moveToSideStage(ActivityManager.RunningTaskInfo task, @SplitPosition int sideStagePosition) { return mStageCoordinator.moveToSideStage(task, sideStagePosition); } + public boolean moveToSideStage(ActivityManager.RunningTaskInfo task, + @SplitPosition int sideStagePosition, WindowContainerTransaction wct) { + return mStageCoordinator.moveToSideStage(task, sideStagePosition, wct); + } + public boolean removeFromSideStage(int taskId) { return mStageCoordinator.removeFromSideStage(taskId); } @@ -182,6 +196,11 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT); } + public void enterSplitScreen(int taskId, boolean leftOrTop, WindowContainerTransaction wct) { + moveToSideStage(taskId, + leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT, wct); + } + public void exitSplitScreen(int toTopTaskId, int exitReason) { mStageCoordinator.exitSplitScreen(toTopTaskId, exitReason); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index 3345613f077c..a94a081e2d33 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -271,6 +271,11 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, boolean moveToSideStage(ActivityManager.RunningTaskInfo task, @SplitPosition int sideStagePosition) { final WindowContainerTransaction wct = new WindowContainerTransaction(); + return moveToSideStage(task, sideStagePosition, wct); + } + + boolean moveToSideStage(ActivityManager.RunningTaskInfo task, + @SplitPosition int sideStagePosition, WindowContainerTransaction wct) { final WindowContainerTransaction evictWct = new WindowContainerTransaction(); setSideStagePosition(sideStagePosition, wct); mSideStage.evictAllChildren(evictWct); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java index 0270093da938..0172cf324eea 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java @@ -50,6 +50,7 @@ import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController; import com.android.wm.shell.pip.phone.PhonePipMenuController; +import com.android.wm.shell.splitscreen.SplitScreenController; import org.junit.Before; import org.junit.Test; @@ -75,7 +76,8 @@ public class PipTaskOrganizerTest extends ShellTestCase { @Mock private PipTransitionController mMockPipTransitionController; @Mock private PipSurfaceTransactionHelper mMockPipSurfaceTransactionHelper; @Mock private PipUiEventLogger mMockPipUiEventLogger; - @Mock private Optional<LegacySplitScreenController> mMockOptionalSplitScreen; + @Mock private Optional<LegacySplitScreenController> mMockOptionalLegacySplitScreen; + @Mock private Optional<SplitScreenController> mMockOptionalSplitScreen; @Mock private ShellTaskOrganizer mMockShellTaskOrganizer; private TestShellExecutor mMainExecutor; private PipBoundsState mPipBoundsState; @@ -99,8 +101,9 @@ public class PipTaskOrganizerTest extends ShellTestCase { mMockSyncTransactionQueue, mPipTransitionState, mPipBoundsState, mPipBoundsAlgorithm, mMockPhonePipMenuController, mMockPipAnimationController, mMockPipSurfaceTransactionHelper, - mMockPipTransitionController, mMockOptionalSplitScreen, mMockDisplayController, - mMockPipUiEventLogger, mMockShellTaskOrganizer, mMainExecutor)); + mMockPipTransitionController, mMockOptionalLegacySplitScreen, + mMockOptionalSplitScreen, mMockDisplayController, mMockPipUiEventLogger, + mMockShellTaskOrganizer, mMainExecutor)); mMainExecutor.flushAll(); preparePipTaskOrg(); } diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java index 3be1d3cab869..4e80151d009d 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java @@ -44,6 +44,7 @@ import com.android.wm.shell.pip.tv.TvPipController; import com.android.wm.shell.pip.tv.TvPipMenuController; import com.android.wm.shell.pip.tv.TvPipNotificationController; import com.android.wm.shell.pip.tv.TvPipTransition; +import com.android.wm.shell.splitscreen.SplitScreenController; import com.android.wm.shell.transition.Transitions; import java.util.Optional; @@ -161,13 +162,14 @@ public abstract class TvPipModule { PipTransitionController pipTransitionController, PipSurfaceTransactionHelper pipSurfaceTransactionHelper, Optional<LegacySplitScreenController> splitScreenOptional, + Optional<SplitScreenController> newSplitScreenOptional, DisplayController displayController, PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer, @ShellMainThread ShellExecutor mainExecutor) { return new PipTaskOrganizer(context, syncTransactionQueue, pipTransitionState, pipBoundsState, pipBoundsAlgorithm, tvPipMenuController, pipAnimationController, pipSurfaceTransactionHelper, - pipTransitionController, splitScreenOptional, displayController, pipUiEventLogger, - shellTaskOrganizer, mainExecutor); + pipTransitionController, splitScreenOptional, newSplitScreenOptional, + displayController, pipUiEventLogger, shellTaskOrganizer, mainExecutor); } } diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java index a7c5ad2e3716..5f8bcf935a95 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java @@ -57,6 +57,7 @@ import com.android.wm.shell.pip.phone.PipAppOpsListener; import com.android.wm.shell.pip.phone.PipController; import com.android.wm.shell.pip.phone.PipMotionHelper; import com.android.wm.shell.pip.phone.PipTouchHandler; +import com.android.wm.shell.splitscreen.SplitScreenController; import com.android.wm.shell.startingsurface.StartingWindowTypeAlgorithm; import com.android.wm.shell.startingsurface.phone.PhoneStartingWindowTypeAlgorithm; import com.android.wm.shell.transition.Transitions; @@ -217,14 +218,15 @@ public class WMShellModule { PipSurfaceTransactionHelper pipSurfaceTransactionHelper, PipTransitionController pipTransitionController, Optional<LegacySplitScreenController> splitScreenOptional, + Optional<SplitScreenController> newSplitScreenOptional, DisplayController displayController, PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer, @ShellMainThread ShellExecutor mainExecutor) { return new PipTaskOrganizer(context, syncTransactionQueue, pipTransitionState, pipBoundsState, pipBoundsAlgorithm, menuPhoneController, pipAnimationController, pipSurfaceTransactionHelper, - pipTransitionController, splitScreenOptional, displayController, pipUiEventLogger, - shellTaskOrganizer, mainExecutor); + pipTransitionController, splitScreenOptional, newSplitScreenOptional, + displayController, pipUiEventLogger, shellTaskOrganizer, mainExecutor); } @WMSingleton |