Merge "Revert "PiP: support direct entering split from PiP."" into sc-v2-dev

This commit is contained in:
Hongwei Wang
2021-11-09 17:45:43 +00:00
committed by Android (Google) Code Review
16 changed files with 73 additions and 172 deletions

View File

@@ -65,28 +65,25 @@
<LinearLayout <LinearLayout
android:id="@+id/top_end_container" android:id="@+id/top_end_container"
android:layout_gravity="top|end" android:layout_gravity="top|end"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal">
<ImageButton <ImageButton
android:id="@+id/settings" android:id="@+id/settings"
android:layout_width="@dimen/pip_action_size" android:layout_width="@dimen/pip_action_size"
android:layout_height="@dimen/pip_action_size" android:layout_height="@dimen/pip_action_size"
android:contentDescription="@string/pip_phone_settings" android:contentDescription="@string/pip_phone_settings"
android:layout_gravity="top|start"
android:gravity="center" android:gravity="center"
android:src="@drawable/pip_ic_settings" android:src="@drawable/pip_ic_settings"
android:background="?android:selectableItemBackgroundBorderless" /> android:background="?android:selectableItemBackgroundBorderless" />
<ImageButton <ImageButton
android:id="@+id/enter_split" android:id="@+id/dismiss"
android:layout_width="@dimen/pip_action_size" android:layout_width="@dimen/pip_action_size"
android:layout_height="@dimen/pip_action_size" android:layout_height="@dimen/pip_action_size"
android:layout_gravity="top|start" android:contentDescription="@string/pip_phone_close"
android:gravity="center" android:gravity="center"
android:contentDescription="@string/pip_phone_enter_split" android:src="@drawable/pip_ic_close_white"
android:src="@drawable/pip_expand"
android:background="?android:selectableItemBackgroundBorderless" /> android:background="?android:selectableItemBackgroundBorderless" />
</LinearLayout> </LinearLayout>
@@ -100,14 +97,4 @@
android:padding="@dimen/pip_resize_handle_padding" android:padding="@dimen/pip_resize_handle_padding"
android:src="@drawable/pip_resize_handle" android:src="@drawable/pip_resize_handle"
android:background="?android:selectableItemBackgroundBorderless" /> 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> </FrameLayout>

View File

@@ -24,9 +24,6 @@
<!-- Label for PIP settings button [CHAR LIMIT=NONE]--> <!-- Label for PIP settings button [CHAR LIMIT=NONE]-->
<string name="pip_phone_settings">Settings</string> <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. --> <!-- Title of menu shown over picture-in-picture. Used for accessibility. -->
<string name="pip_menu_title">Menu</string> <string name="pip_menu_title">Menu</string>

View File

@@ -43,7 +43,6 @@ import com.android.wm.shell.pip.tv.TvPipController;
import com.android.wm.shell.pip.tv.TvPipMenuController; import com.android.wm.shell.pip.tv.TvPipMenuController;
import com.android.wm.shell.pip.tv.TvPipNotificationController; import com.android.wm.shell.pip.tv.TvPipNotificationController;
import com.android.wm.shell.pip.tv.TvPipTransition; import com.android.wm.shell.pip.tv.TvPipTransition;
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.transition.Transitions;
import java.util.Optional; import java.util.Optional;
@@ -161,14 +160,13 @@ public abstract class TvPipModule {
PipTransitionController pipTransitionController, PipTransitionController pipTransitionController,
PipSurfaceTransactionHelper pipSurfaceTransactionHelper, PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
Optional<LegacySplitScreenController> splitScreenOptional, Optional<LegacySplitScreenController> splitScreenOptional,
Optional<SplitScreenController> newSplitScreenOptional,
DisplayController displayController, DisplayController displayController,
PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer, PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer,
@ShellMainThread ShellExecutor mainExecutor) { @ShellMainThread ShellExecutor mainExecutor) {
return new PipTaskOrganizer(context, return new PipTaskOrganizer(context,
syncTransactionQueue, pipTransitionState, pipBoundsState, pipBoundsAlgorithm, syncTransactionQueue, pipTransitionState, pipBoundsState, pipBoundsAlgorithm,
tvPipMenuController, pipAnimationController, pipSurfaceTransactionHelper, tvPipMenuController, pipAnimationController, pipSurfaceTransactionHelper,
pipTransitionController, splitScreenOptional, newSplitScreenOptional, pipTransitionController, splitScreenOptional, displayController, pipUiEventLogger,
displayController, pipUiEventLogger, shellTaskOrganizer, mainExecutor); shellTaskOrganizer, mainExecutor);
} }
} }

View File

@@ -55,7 +55,6 @@ import com.android.wm.shell.pip.phone.PipAppOpsListener;
import com.android.wm.shell.pip.phone.PipController; import com.android.wm.shell.pip.phone.PipController;
import com.android.wm.shell.pip.phone.PipMotionHelper; import com.android.wm.shell.pip.phone.PipMotionHelper;
import com.android.wm.shell.pip.phone.PipTouchHandler; 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.StartingWindowTypeAlgorithm;
import com.android.wm.shell.startingsurface.phone.PhoneStartingWindowTypeAlgorithm; import com.android.wm.shell.startingsurface.phone.PhoneStartingWindowTypeAlgorithm;
import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.transition.Transitions;
@@ -216,15 +215,14 @@ public class WMShellModule {
PipSurfaceTransactionHelper pipSurfaceTransactionHelper, PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
PipTransitionController pipTransitionController, PipTransitionController pipTransitionController,
Optional<LegacySplitScreenController> splitScreenOptional, Optional<LegacySplitScreenController> splitScreenOptional,
Optional<SplitScreenController> newSplitScreenOptional,
DisplayController displayController, DisplayController displayController,
PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer, PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer,
@ShellMainThread ShellExecutor mainExecutor) { @ShellMainThread ShellExecutor mainExecutor) {
return new PipTaskOrganizer(context, return new PipTaskOrganizer(context,
syncTransactionQueue, pipTransitionState, pipBoundsState, pipBoundsAlgorithm, syncTransactionQueue, pipTransitionState, pipBoundsState, pipBoundsAlgorithm,
menuPhoneController, pipAnimationController, pipSurfaceTransactionHelper, menuPhoneController, pipAnimationController, pipSurfaceTransactionHelper,
pipTransitionController, splitScreenOptional, newSplitScreenOptional, pipTransitionController, splitScreenOptional, displayController, pipUiEventLogger,
displayController, pipUiEventLogger, shellTaskOrganizer, mainExecutor); shellTaskOrganizer, mainExecutor);
} }
@WMSingleton @WMSingleton

View File

@@ -77,7 +77,6 @@ import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.annotations.ShellMainThread; import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController; import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
import com.android.wm.shell.pip.phone.PipMotionHelper; import com.android.wm.shell.pip.phone.PipMotionHelper;
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.transition.Transitions;
import java.io.PrintWriter; import java.io.PrintWriter;
@@ -127,8 +126,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
private final int mExitAnimationDuration; private final int mExitAnimationDuration;
private final int mCrossFadeAnimationDuration; private final int mCrossFadeAnimationDuration;
private final PipSurfaceTransactionHelper mSurfaceTransactionHelper; private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
private final Optional<LegacySplitScreenController> mLegacySplitScreenOptional; private final Optional<LegacySplitScreenController> mSplitScreenOptional;
private final Optional<SplitScreenController> mSplitScreenOptional;
protected final ShellTaskOrganizer mTaskOrganizer; protected final ShellTaskOrganizer mTaskOrganizer;
protected final ShellExecutor mMainExecutor; protected final ShellExecutor mMainExecutor;
@@ -254,8 +252,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
@NonNull PipAnimationController pipAnimationController, @NonNull PipAnimationController pipAnimationController,
@NonNull PipSurfaceTransactionHelper surfaceTransactionHelper, @NonNull PipSurfaceTransactionHelper surfaceTransactionHelper,
@NonNull PipTransitionController pipTransitionController, @NonNull PipTransitionController pipTransitionController,
Optional<LegacySplitScreenController> legacySplitScreenOptional, Optional<LegacySplitScreenController> splitScreenOptional,
Optional<SplitScreenController> splitScreenOptional,
@NonNull DisplayController displayController, @NonNull DisplayController displayController,
@NonNull PipUiEventLogger pipUiEventLogger, @NonNull PipUiEventLogger pipUiEventLogger,
@NonNull ShellTaskOrganizer shellTaskOrganizer, @NonNull ShellTaskOrganizer shellTaskOrganizer,
@@ -277,7 +274,6 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
mPipAnimationController = pipAnimationController; mPipAnimationController = pipAnimationController;
mPipUiEventLoggerLogger = pipUiEventLogger; mPipUiEventLoggerLogger = pipUiEventLogger;
mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new; mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
mLegacySplitScreenOptional = legacySplitScreenOptional;
mSplitScreenOptional = splitScreenOptional; mSplitScreenOptional = splitScreenOptional;
mTaskOrganizer = shellTaskOrganizer; mTaskOrganizer = shellTaskOrganizer;
mMainExecutor = mainExecutor; mMainExecutor = mainExecutor;
@@ -377,11 +373,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
* activity render it's final configuration while the Task is still in PiP. * activity render it's final configuration while the Task is still in PiP.
* - setWindowingMode to undefined at the end of transition * - setWindowingMode to undefined at the end of transition
* @param animationDurationMs duration in millisecond for the exiting PiP 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, boolean requestEnterSplit) { public void exitPip(int animationDurationMs) {
if (!mPipTransitionState.isInPip() if (!mPipTransitionState.isInPip()
|| mPipTransitionState.getTransitionState() == PipTransitionState.EXITING_PIP || mPipTransitionState.getTransitionState() == PipTransitionState.EXITING_PIP
|| mToken == null) { || mToken == null) {
@@ -394,7 +387,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_EXPAND_TO_FULLSCREEN); PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_EXPAND_TO_FULLSCREEN);
final WindowContainerTransaction wct = new WindowContainerTransaction(); final WindowContainerTransaction wct = new WindowContainerTransaction();
final Rect destinationBounds = mPipBoundsState.getDisplayBounds(); final Rect destinationBounds = mPipBoundsState.getDisplayBounds();
final int direction = syncWithSplitScreenBounds(destinationBounds, requestEnterSplit) final int direction = syncWithSplitScreenBounds(destinationBounds)
? TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN ? TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN
: TRANSITION_DIRECTION_LEAVE_PIP; : TRANSITION_DIRECTION_LEAVE_PIP;
final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction(); final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
@@ -403,7 +396,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
// We set to fullscreen here for now, but later it will be set to UNDEFINED for // 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. // the proper windowing mode to take place. See #applyWindowingModeChangeOnExit.
wct.setActivityWindowingMode(mToken, wct.setActivityWindowingMode(mToken,
direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN && !requestEnterSplit direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN
? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
: WINDOWING_MODE_FULLSCREEN); : WINDOWING_MODE_FULLSCREEN);
wct.setBounds(mToken, destinationBounds); wct.setBounds(mToken, destinationBounds);
@@ -442,7 +435,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
wct.setWindowingMode(mToken, getOutPipWindowingMode()); wct.setWindowingMode(mToken, getOutPipWindowingMode());
// Simply reset the activity mode set prior to the animation running. // Simply reset the activity mode set prior to the animation running.
wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED); wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
mLegacySplitScreenOptional.ifPresent(splitScreen -> { mSplitScreenOptional.ifPresent(splitScreen -> {
if (direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN) { if (direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN) {
wct.reparent(mToken, splitScreen.getSecondaryRoot(), true /* onTop */); wct.reparent(mToken, splitScreen.getSecondaryRoot(), true /* onTop */);
} }
@@ -1172,7 +1165,6 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
@PipAnimationController.TransitionDirection int direction, @PipAnimationController.TransitionDirection int direction,
@PipAnimationController.AnimationType int type) { @PipAnimationController.AnimationType int type) {
final Rect preResizeBounds = new Rect(mPipBoundsState.getBounds()); final Rect preResizeBounds = new Rect(mPipBoundsState.getBounds());
final boolean isPipTopLeft = isPipTopLeft();
mPipBoundsState.setBounds(destinationBounds); mPipBoundsState.setBounds(destinationBounds);
if (direction == TRANSITION_DIRECTION_REMOVE_STACK) { if (direction == TRANSITION_DIRECTION_REMOVE_STACK) {
removePipImmediately(); removePipImmediately();
@@ -1218,10 +1210,10 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
null /* callback */, false /* withStartDelay */); null /* callback */, false /* withStartDelay */);
}); });
} else { } else {
applyFinishBoundsResize(wct, direction, isPipTopLeft); applyFinishBoundsResize(wct, direction);
} }
} else { } else {
applyFinishBoundsResize(wct, direction, isPipTopLeft); applyFinishBoundsResize(wct, direction);
} }
finishResizeForMenu(destinationBounds); finishResizeForMenu(destinationBounds);
@@ -1249,11 +1241,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
} else if (isOutPipDirection(direction)) { } else if (isOutPipDirection(direction)) {
// If we are animating to fullscreen or split screen, then we need to reset the // 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. // 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 = null;
taskBounds = destinationBounds;
} else {
taskBounds = null;
}
applyWindowingModeChangeOnExit(wct, direction); applyWindowingModeChangeOnExit(wct, direction);
} else { } else {
// Just a resize in PIP // Just a resize in PIP
@@ -1273,20 +1261,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
* applying it. * applying it.
*/ */
public void applyFinishBoundsResize(@NonNull WindowContainerTransaction wct, public void applyFinishBoundsResize(@NonNull WindowContainerTransaction wct,
@PipAnimationController.TransitionDirection int direction, boolean wasPipTopLeft) { @PipAnimationController.TransitionDirection int direction) {
if (direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN) { mTaskOrganizer.applyTransaction(wct);
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());
} }
/** /**
@@ -1371,27 +1347,18 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
} }
/** /**
* Sync with {@link LegacySplitScreenController} or {@link SplitScreenController} on destination * Sync with {@link LegacySplitScreenController} on destination bounds if PiP is going to split
* bounds if PiP is going to split screen. * screen.
* *
* @param destinationBoundsOut contain the updated destination bounds if applicable * @param destinationBoundsOut contain the updated destination bounds if applicable
* @return {@code true} if destinationBounds is altered for split screen * @return {@code true} if destinationBounds is altered for split screen
*/ */
private boolean syncWithSplitScreenBounds(Rect destinationBoundsOut, boolean enterSplit) { private boolean syncWithSplitScreenBounds(Rect destinationBoundsOut) {
if (enterSplit && mSplitScreenOptional.isPresent()) { if (!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; return false;
} }
LegacySplitScreenController legacySplitScreen = mLegacySplitScreenOptional.get(); LegacySplitScreenController legacySplitScreen = mSplitScreenOptional.get();
if (!legacySplitScreen.isDividerVisible()) { if (!legacySplitScreen.isDividerVisible()) {
// fail early if system is not in split screen mode // fail early if system is not in split screen mode
return false; return false;

View File

@@ -95,11 +95,6 @@ public class PhonePipMenuController implements PipMenuController {
* Called when the PIP requested to show the menu. * Called when the PIP requested to show the menu.
*/ */
void onPipShowMenu(); void onPipShowMenu();
/**
* Called when the PIP requested to enter Split.
*/
void onEnterSplit();
} }
private final Matrix mMoveTransform = new Matrix(); private final Matrix mMoveTransform = new Matrix();
@@ -463,10 +458,6 @@ public class PhonePipMenuController implements PipMenuController {
mListeners.forEach(Listener::onPipDismiss); mListeners.forEach(Listener::onPipDismiss);
} }
void onEnterSplit() {
mListeners.forEach(Listener::onEnterSplit);
}
/** /**
* @return the best set of actions to show in the PiP menu. * @return the best set of actions to show in the PiP menu.
*/ */

View File

@@ -151,7 +151,7 @@ public class PipAccessibilityInteractionConnection {
result = true; result = true;
break; break;
case AccessibilityNodeInfo.ACTION_EXPAND: case AccessibilityNodeInfo.ACTION_EXPAND:
mMotionHelper.expandLeavePip(false /* skipAnimation */); mMotionHelper.expandLeavePip();
result = true; result = true;
break; break;
default: default:

View File

@@ -482,8 +482,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb
false /* fromShelfAdjustment */, false /* fromShelfAdjustment */,
wct /* windowContainerTransaction */); wct /* windowContainerTransaction */);
if (wct != null) { if (wct != null) {
mPipTaskOrganizer.applyFinishBoundsResize(wct, TRANSITION_DIRECTION_SAME, mPipTaskOrganizer.applyFinishBoundsResize(wct, TRANSITION_DIRECTION_SAME);
false /* wasPipTopLeft */);
} }
}; };

View File

@@ -18,6 +18,8 @@ package com.android.wm.shell.pip.phone;
import android.content.Context; import android.content.Context;
import android.graphics.Rect; import android.graphics.Rect;
import android.util.Log;
import android.view.Gravity;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.FrameLayout; import android.widget.FrameLayout;
@@ -32,7 +34,6 @@ public class PipMenuIconsAlgorithm {
protected ViewGroup mViewRoot; protected ViewGroup mViewRoot;
protected ViewGroup mTopEndContainer; protected ViewGroup mTopEndContainer;
protected View mDragHandle; protected View mDragHandle;
protected View mEnterSplitButton;
protected View mSettingsButton; protected View mSettingsButton;
protected View mDismissButton; protected View mDismissButton;
@@ -43,13 +44,14 @@ public class PipMenuIconsAlgorithm {
* Bind the necessary views. * Bind the necessary views.
*/ */
public void bindViews(ViewGroup viewRoot, ViewGroup topEndContainer, View dragHandle, public void bindViews(ViewGroup viewRoot, ViewGroup topEndContainer, View dragHandle,
View enterSplitButton, View settingsButton, View dismissButton) { View settingsButton, View dismissButton) {
mViewRoot = viewRoot; mViewRoot = viewRoot;
mTopEndContainer = topEndContainer; mTopEndContainer = topEndContainer;
mDragHandle = dragHandle; mDragHandle = dragHandle;
mEnterSplitButton = enterSplitButton;
mSettingsButton = settingsButton; mSettingsButton = settingsButton;
mDismissButton = dismissButton; mDismissButton = dismissButton;
bindInitialViewState();
} }
/** /**
@@ -70,4 +72,22 @@ public class PipMenuIconsAlgorithm {
v.setLayoutParams(params); 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);
}
} }

View File

@@ -99,7 +99,7 @@ public class PipMenuView extends FrameLayout {
private static final float MENU_BACKGROUND_ALPHA = 0.3f; private static final float MENU_BACKGROUND_ALPHA = 0.3f;
private static final float DISABLED_ACTION_ALPHA = 0.54f; private static final float DISABLED_ACTION_ALPHA = 0.54f;
private static final boolean ENABLE_ENTER_SPLIT = false; private static final boolean ENABLE_RESIZE_HANDLE = false;
private int mMenuState; private int mMenuState;
private boolean mAllowMenuTimeout = true; private boolean mAllowMenuTimeout = true;
@@ -139,7 +139,7 @@ public class PipMenuView extends FrameLayout {
protected View mViewRoot; protected View mViewRoot;
protected View mSettingsButton; protected View mSettingsButton;
protected View mDismissButton; protected View mDismissButton;
protected View mEnterSplitButton; protected View mResizeHandle;
protected View mTopEndContainer; protected View mTopEndContainer;
protected PipMenuIconsAlgorithm mPipMenuIconsAlgorithm; protected PipMenuIconsAlgorithm mPipMenuIconsAlgorithm;
@@ -177,23 +177,14 @@ public class PipMenuView extends FrameLayout {
} }
}); });
mEnterSplitButton = findViewById(R.id.enter_split); mResizeHandle = findViewById(R.id.resize_handle);
mEnterSplitButton.setAlpha(0); mResizeHandle.setAlpha(0);
mEnterSplitButton.setOnClickListener(v -> {
if (mMenuContainer.getAlpha() != 0) {
enterSplit();
}
});
findViewById(R.id.resize_handle).setAlpha(0);
mActionsGroup = findViewById(R.id.actions_group); mActionsGroup = findViewById(R.id.actions_group);
mBetweenActionPaddingLand = getResources().getDimensionPixelSize( mBetweenActionPaddingLand = getResources().getDimensionPixelSize(
R.dimen.pip_between_action_padding_land); R.dimen.pip_between_action_padding_land);
mPipMenuIconsAlgorithm = new PipMenuIconsAlgorithm(mContext); mPipMenuIconsAlgorithm = new PipMenuIconsAlgorithm(mContext);
mPipMenuIconsAlgorithm.bindViews((ViewGroup) mViewRoot, (ViewGroup) mTopEndContainer, mPipMenuIconsAlgorithm.bindViews((ViewGroup) mViewRoot, (ViewGroup) mTopEndContainer,
findViewById(R.id.resize_handle), mEnterSplitButton, mSettingsButton, mResizeHandle, mSettingsButton, mDismissButton);
mDismissButton);
mDismissFadeOutDurationMs = context.getResources() mDismissFadeOutDurationMs = context.getResources()
.getInteger(R.integer.config_pipExitAnimationDuration); .getInteger(R.integer.config_pipExitAnimationDuration);
@@ -277,13 +268,14 @@ public class PipMenuView extends FrameLayout {
mSettingsButton.getAlpha(), 1f); mSettingsButton.getAlpha(), 1f);
ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA, ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA,
mDismissButton.getAlpha(), 1f); mDismissButton.getAlpha(), 1f);
ObjectAnimator enterSplitAnim = ObjectAnimator.ofFloat(mEnterSplitButton, View.ALPHA, ObjectAnimator resizeAnim = ObjectAnimator.ofFloat(mResizeHandle, View.ALPHA,
mEnterSplitButton.getAlpha(), ENABLE_ENTER_SPLIT ? 1f : 0f); mResizeHandle.getAlpha(),
ENABLE_RESIZE_HANDLE && showResizeHandle ? 1f : 0f);
if (menuState == MENU_STATE_FULL) { if (menuState == MENU_STATE_FULL) {
mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim, mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim,
enterSplitAnim); resizeAnim);
} else { } else {
mMenuContainerAnimator.playTogether(enterSplitAnim); mMenuContainerAnimator.playTogether(resizeAnim);
} }
mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_IN); mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_IN);
mMenuContainerAnimator.setDuration(ANIMATION_HIDE_DURATION_MS); mMenuContainerAnimator.setDuration(ANIMATION_HIDE_DURATION_MS);
@@ -336,7 +328,7 @@ public class PipMenuView extends FrameLayout {
mMenuContainer.setAlpha(0f); mMenuContainer.setAlpha(0f);
mSettingsButton.setAlpha(0f); mSettingsButton.setAlpha(0f);
mDismissButton.setAlpha(0f); mDismissButton.setAlpha(0f);
mEnterSplitButton.setAlpha(0f); mResizeHandle.setAlpha(0f);
} }
void pokeMenu() { void pokeMenu() {
@@ -376,10 +368,9 @@ public class PipMenuView extends FrameLayout {
mSettingsButton.getAlpha(), 0f); mSettingsButton.getAlpha(), 0f);
ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA, ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA,
mDismissButton.getAlpha(), 0f); mDismissButton.getAlpha(), 0f);
ObjectAnimator enterSplitAnim = ObjectAnimator.ofFloat(mEnterSplitButton, View.ALPHA, ObjectAnimator resizeAnim = ObjectAnimator.ofFloat(mResizeHandle, View.ALPHA,
mEnterSplitButton.getAlpha(), 0f); mResizeHandle.getAlpha(), 0f);
mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim, mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim, resizeAnim);
enterSplitAnim);
mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_OUT); mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_OUT);
mMenuContainerAnimator.setDuration(getFadeOutDuration(animationType)); mMenuContainerAnimator.setDuration(getFadeOutDuration(animationType));
mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() { mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() {
@@ -531,14 +522,6 @@ 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() { private void showSettings() {
final Pair<ComponentName, Integer> topPipActivityInfo = final Pair<ComponentName, Integer> topPipActivityInfo =
PipUtils.getTopPipActivity(mContext); PipUtils.getTopPipActivity(mContext);

View File

@@ -338,29 +338,22 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
* Resizes the pinned stack back to unknown windowing mode, which could be freeform or * Resizes the pinned stack back to unknown windowing mode, which could be freeform or
* * fullscreen depending on the display area's windowing mode. * * fullscreen depending on the display area's windowing mode.
*/ */
void expandLeavePip(boolean skipAnimation) { void expandLeavePip() {
expandLeavePip(skipAnimation, false /* enterSplit */); expandLeavePip(false /* skipAnimation */);
}
/**
* 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 * Resizes the pinned stack back to unknown windowing mode, which could be freeform or
* fullscreen depending on the display area's windowing mode. * fullscreen depending on the display area's windowing mode.
*/ */
private void expandLeavePip(boolean skipAnimation, boolean enterSplit) { void expandLeavePip(boolean skipAnimation) {
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "exitPip: skipAnimation=" + skipAnimation Log.d(TAG, "exitPip: skipAnimation=" + skipAnimation
+ " callers=\n" + Debug.getCallers(5, " ")); + " callers=\n" + Debug.getCallers(5, " "));
} }
cancelPhysicsAnimation(); cancelPhysicsAnimation();
mMenuController.hideMenu(ANIM_TYPE_NONE, false /* resize */); mMenuController.hideMenu(ANIM_TYPE_NONE, false /* resize */);
mPipTaskOrganizer.exitPip(skipAnimation ? 0 : LEAVE_PIP_DURATION, enterSplit); mPipTaskOrganizer.exitPip(skipAnimation ? 0 : LEAVE_PIP_DURATION);
} }
/** /**

View File

@@ -139,12 +139,7 @@ public class PipTouchHandler {
@Override @Override
public void onPipExpand() { public void onPipExpand() {
mMotionHelper.expandLeavePip(false /* skipAnimation */); mMotionHelper.expandLeavePip();
}
@Override
public void onEnterSplit() {
mMotionHelper.expandIntoSplit();
} }
@Override @Override
@@ -904,7 +899,7 @@ public class PipTouchHandler {
// Expand to fullscreen if this is a double tap // Expand to fullscreen if this is a double tap
// the PiP should be frozen until the transition ends // the PiP should be frozen until the transition ends
setTouchEnabled(false); setTouchEnabled(false);
mMotionHelper.expandLeavePip(false /* skipAnimation */); mMotionHelper.expandLeavePip();
} }
} else if (mMenuState != MENU_STATE_FULL) { } else if (mMenuState != MENU_STATE_FULL) {
if (mPipBoundsState.isStashed()) { if (mPipBoundsState.isStashed()) {

View File

@@ -219,7 +219,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
public void movePipToFullscreen() { public void movePipToFullscreen() {
if (DEBUG) Log.d(TAG, "movePipToFullscreen(), state=" + stateToName(mState)); if (DEBUG) Log.d(TAG, "movePipToFullscreen(), state=" + stateToName(mState));
mPipTaskOrganizer.exitPip(mResizeAnimationDuration, false /* requestEnterSplit */); mPipTaskOrganizer.exitPip(mResizeAnimationDuration);
onPipDisappeared(); onPipDisappeared();
} }

View File

@@ -202,25 +202,11 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
return moveToSideStage(task, sideStagePosition); 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, public boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
@SplitPosition int sideStagePosition) { @SplitPosition int sideStagePosition) {
return mStageCoordinator.moveToSideStage(task, 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) { public boolean removeFromSideStage(int taskId) {
return mStageCoordinator.removeFromSideStage(taskId); return mStageCoordinator.removeFromSideStage(taskId);
} }
@@ -238,11 +224,6 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT); 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, @ExitReason int exitReason) { public void exitSplitScreen(int toTopTaskId, @ExitReason int exitReason) {
mStageCoordinator.exitSplitScreen(toTopTaskId, exitReason); mStageCoordinator.exitSplitScreen(toTopTaskId, exitReason);
} }

View File

@@ -280,11 +280,6 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
boolean moveToSideStage(ActivityManager.RunningTaskInfo task, boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
@SplitPosition int sideStagePosition) { @SplitPosition int sideStagePosition) {
final WindowContainerTransaction wct = new WindowContainerTransaction(); 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(); final WindowContainerTransaction evictWct = new WindowContainerTransaction();
setSideStagePosition(sideStagePosition, wct); setSideStagePosition(sideStagePosition, wct);
mSideStage.evictAllChildren(evictWct); mSideStage.evictAllChildren(evictWct);

View File

@@ -50,7 +50,6 @@ import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController; import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
import com.android.wm.shell.pip.phone.PhonePipMenuController; import com.android.wm.shell.pip.phone.PhonePipMenuController;
import com.android.wm.shell.splitscreen.SplitScreenController;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -76,8 +75,7 @@ public class PipTaskOrganizerTest extends ShellTestCase {
@Mock private PipTransitionController mMockPipTransitionController; @Mock private PipTransitionController mMockPipTransitionController;
@Mock private PipSurfaceTransactionHelper mMockPipSurfaceTransactionHelper; @Mock private PipSurfaceTransactionHelper mMockPipSurfaceTransactionHelper;
@Mock private PipUiEventLogger mMockPipUiEventLogger; @Mock private PipUiEventLogger mMockPipUiEventLogger;
@Mock private Optional<LegacySplitScreenController> mMockOptionalLegacySplitScreen; @Mock private Optional<LegacySplitScreenController> mMockOptionalSplitScreen;
@Mock private Optional<SplitScreenController> mMockOptionalSplitScreen;
@Mock private ShellTaskOrganizer mMockShellTaskOrganizer; @Mock private ShellTaskOrganizer mMockShellTaskOrganizer;
private TestShellExecutor mMainExecutor; private TestShellExecutor mMainExecutor;
private PipBoundsState mPipBoundsState; private PipBoundsState mPipBoundsState;
@@ -101,9 +99,8 @@ public class PipTaskOrganizerTest extends ShellTestCase {
mMockSyncTransactionQueue, mPipTransitionState, mPipBoundsState, mMockSyncTransactionQueue, mPipTransitionState, mPipBoundsState,
mPipBoundsAlgorithm, mMockPhonePipMenuController, mPipBoundsAlgorithm, mMockPhonePipMenuController,
mMockPipAnimationController, mMockPipSurfaceTransactionHelper, mMockPipAnimationController, mMockPipSurfaceTransactionHelper,
mMockPipTransitionController, mMockOptionalLegacySplitScreen, mMockPipTransitionController, mMockOptionalSplitScreen, mMockDisplayController,
mMockOptionalSplitScreen, mMockDisplayController, mMockPipUiEventLogger, mMockPipUiEventLogger, mMockShellTaskOrganizer, mMainExecutor));
mMockShellTaskOrganizer, mMainExecutor));
mMainExecutor.flushAll(); mMainExecutor.flushAll();
preparePipTaskOrg(); preparePipTaskOrg();
} }