Merge "Fix RTL TV PiP position"

This commit is contained in:
Jacqueline Bronger
2022-12-19 17:32:11 +00:00
committed by Android (Google) Code Review
5 changed files with 473 additions and 147 deletions

View File

@@ -22,7 +22,6 @@ import static android.view.KeyEvent.KEYCODE_DPAD_RIGHT;
import static android.view.KeyEvent.KEYCODE_DPAD_UP;
import static com.android.wm.shell.pip.tv.TvPipBoundsState.ORIENTATION_HORIZONTAL;
import static com.android.wm.shell.pip.tv.TvPipBoundsState.ORIENTATION_UNDETERMINED;
import static com.android.wm.shell.pip.tv.TvPipBoundsState.ORIENTATION_VERTICAL;
import android.content.Context;
@@ -63,7 +62,8 @@ public class TvPipBoundsAlgorithm extends PipBoundsAlgorithm {
@NonNull TvPipBoundsState tvPipBoundsState,
@NonNull PipSnapAlgorithm pipSnapAlgorithm) {
super(context, tvPipBoundsState, pipSnapAlgorithm,
new PipKeepClearAlgorithm() {});
new PipKeepClearAlgorithm() {
});
this.mTvPipBoundsState = tvPipBoundsState;
this.mKeepClearAlgorithm = new TvPipKeepClearAlgorithm();
reloadResources(context);
@@ -98,7 +98,7 @@ public class TvPipBoundsAlgorithm extends PipBoundsAlgorithm {
&& mTvPipBoundsState.getDesiredTvExpandedAspectRatio() != 0
&& !mTvPipBoundsState.isTvPipManuallyCollapsed();
if (isPipExpanded) {
updateGravityOnExpandToggled(Gravity.NO_GRAVITY, true);
updateGravityOnExpansionToggled(/* expanding= */ true);
}
mTvPipBoundsState.setTvPipExpanded(isPipExpanded);
return adjustBoundsForTemporaryDecor(getTvPipPlacement().getBounds());
@@ -172,135 +172,85 @@ public class TvPipBoundsAlgorithm extends PipBoundsAlgorithm {
return placement;
}
/**
* @return previous gravity if it is to be saved, or {@link Gravity#NO_GRAVITY} if not.
*/
int updateGravityOnExpandToggled(int previousGravity, boolean expanding) {
void updateGravityOnExpansionToggled(boolean expanding) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: updateGravityOnExpandToggled(), expanding: %b"
+ ", mOrientation: %d, previous gravity: %s",
TAG, expanding, mTvPipBoundsState.getTvFixedPipOrientation(),
Gravity.toString(previousGravity));
"%s: updateGravity, expanding: %b, fixedExpandedOrientation: %d",
TAG, expanding, mTvPipBoundsState.getTvFixedPipOrientation());
if (!mTvPipBoundsState.isTvExpandedPipSupported()) {
return Gravity.NO_GRAVITY;
}
int currentX = mTvPipBoundsState.getTvPipGravity() & Gravity.HORIZONTAL_GRAVITY_MASK;
int currentY = mTvPipBoundsState.getTvPipGravity() & Gravity.VERTICAL_GRAVITY_MASK;
int previousCollapsedX = mTvPipBoundsState.getTvPipPreviousCollapsedGravity()
& Gravity.HORIZONTAL_GRAVITY_MASK;
int previousCollapsedY = mTvPipBoundsState.getTvPipPreviousCollapsedGravity()
& Gravity.VERTICAL_GRAVITY_MASK;
if (expanding && mTvPipBoundsState.getTvFixedPipOrientation() == ORIENTATION_UNDETERMINED) {
float expandedRatio = mTvPipBoundsState.getDesiredTvExpandedAspectRatio();
if (expandedRatio == 0) {
return Gravity.NO_GRAVITY;
}
if (expandedRatio < 1) {
mTvPipBoundsState.setTvFixedPipOrientation(ORIENTATION_VERTICAL);
} else {
mTvPipBoundsState.setTvFixedPipOrientation(ORIENTATION_HORIZONTAL);
}
}
int gravityToSave = Gravity.NO_GRAVITY;
int currentGravity = mTvPipBoundsState.getTvPipGravity();
int updatedGravity;
if (expanding) {
// save collapsed gravity
gravityToSave = mTvPipBoundsState.getTvPipGravity();
// Save collapsed gravity.
mTvPipBoundsState.setTvPipPreviousCollapsedGravity(mTvPipBoundsState.getTvPipGravity());
if (mTvPipBoundsState.getTvFixedPipOrientation() == ORIENTATION_HORIZONTAL) {
updatedGravity =
Gravity.CENTER_HORIZONTAL | (currentGravity
& Gravity.VERTICAL_GRAVITY_MASK);
updatedGravity = Gravity.CENTER_HORIZONTAL | currentY;
} else {
updatedGravity =
Gravity.CENTER_VERTICAL | (currentGravity
& Gravity.HORIZONTAL_GRAVITY_MASK);
updatedGravity = currentX | Gravity.CENTER_VERTICAL;
}
} else {
if (previousGravity != Gravity.NO_GRAVITY) {
// The pip hasn't been moved since expanding,
// go back to previous collapsed position.
updatedGravity = previousGravity;
// Collapse to the edge that the user moved to before.
if (mTvPipBoundsState.getTvFixedPipOrientation() == ORIENTATION_HORIZONTAL) {
updatedGravity = previousCollapsedX | currentY;
} else {
if (mTvPipBoundsState.getTvFixedPipOrientation() == ORIENTATION_HORIZONTAL) {
updatedGravity =
Gravity.RIGHT | (currentGravity & Gravity.VERTICAL_GRAVITY_MASK);
} else {
updatedGravity =
Gravity.BOTTOM | (currentGravity & Gravity.HORIZONTAL_GRAVITY_MASK);
}
updatedGravity = currentX | previousCollapsedY;
}
}
mTvPipBoundsState.setTvPipGravity(updatedGravity);
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: new gravity: %s", TAG, Gravity.toString(updatedGravity));
return gravityToSave;
}
/**
* @return true if gravity changed
* @return true if the gravity changed
*/
boolean updateGravity(int keycode) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: updateGravity, keycode: %d", TAG, keycode);
// Check if position change is valid
// Check if position change is valid.
if (mTvPipBoundsState.isTvPipExpanded()) {
int mOrientation = mTvPipBoundsState.getTvFixedPipOrientation();
if (mOrientation == ORIENTATION_VERTICAL
int fixedOrientation = mTvPipBoundsState.getTvFixedPipOrientation();
if (fixedOrientation == ORIENTATION_VERTICAL
&& (keycode == KEYCODE_DPAD_UP || keycode == KEYCODE_DPAD_DOWN)
|| mOrientation == ORIENTATION_HORIZONTAL
|| fixedOrientation == ORIENTATION_HORIZONTAL
&& (keycode == KEYCODE_DPAD_RIGHT || keycode == KEYCODE_DPAD_LEFT)) {
return false;
}
}
int currentGravity = mTvPipBoundsState.getTvPipGravity();
int updatedGravity;
// First axis
int updatedX = mTvPipBoundsState.getTvPipGravity() & Gravity.HORIZONTAL_GRAVITY_MASK;
int updatedY = mTvPipBoundsState.getTvPipGravity() & Gravity.VERTICAL_GRAVITY_MASK;
switch (keycode) {
case KEYCODE_DPAD_UP:
updatedGravity = Gravity.TOP;
updatedY = Gravity.TOP;
break;
case KEYCODE_DPAD_DOWN:
updatedGravity = Gravity.BOTTOM;
updatedY = Gravity.BOTTOM;
break;
case KEYCODE_DPAD_LEFT:
updatedGravity = Gravity.LEFT;
updatedX = Gravity.LEFT;
break;
case KEYCODE_DPAD_RIGHT:
updatedGravity = Gravity.RIGHT;
updatedX = Gravity.RIGHT;
break;
default:
updatedGravity = currentGravity;
// NOOP - unsupported keycode
}
// Second axis
switch (keycode) {
case KEYCODE_DPAD_UP:
case KEYCODE_DPAD_DOWN:
if (mTvPipBoundsState.isTvPipExpanded()) {
updatedGravity |= Gravity.CENTER_HORIZONTAL;
} else {
updatedGravity |= (currentGravity & Gravity.HORIZONTAL_GRAVITY_MASK);
}
break;
case KEYCODE_DPAD_LEFT:
case KEYCODE_DPAD_RIGHT:
if (mTvPipBoundsState.isTvPipExpanded()) {
updatedGravity |= Gravity.CENTER_VERTICAL;
} else {
updatedGravity |= (currentGravity & Gravity.VERTICAL_GRAVITY_MASK);
}
break;
default:
break;
}
int updatedGravity = updatedX | updatedY;
if (updatedGravity != currentGravity) {
if (updatedGravity != mTvPipBoundsState.getTvPipGravity()) {
mTvPipBoundsState.setTvPipGravity(updatedGravity);
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: new gravity: %s", TAG, Gravity.toString(updatedGravity));
"%s: updateGravity, new gravity: %s", TAG, Gravity.toString(updatedGravity));
return true;
}
return false;

View File

@@ -27,6 +27,7 @@ import android.content.pm.PackageManager;
import android.graphics.Insets;
import android.util.Size;
import android.view.Gravity;
import android.view.View;
import com.android.wm.shell.pip.PipBoundsAlgorithm;
import com.android.wm.shell.pip.PipBoundsState;
@@ -52,24 +53,61 @@ public class TvPipBoundsState extends PipBoundsState {
public @interface Orientation {
}
public static final int DEFAULT_TV_GRAVITY = Gravity.BOTTOM | Gravity.RIGHT;
private final Context mContext;
private int mDefaultGravity;
private int mTvPipGravity;
private int mPreviousCollapsedGravity;
private boolean mIsRtl;
private final boolean mIsTvExpandedPipSupported;
private boolean mIsTvPipExpanded;
private boolean mTvPipManuallyCollapsed;
private float mDesiredTvExpandedAspectRatio;
private @Orientation int mTvFixedPipOrientation;
private int mTvPipGravity;
private @Nullable Size mTvExpandedSize;
private @NonNull Insets mPipMenuPermanentDecorInsets = Insets.NONE;
private @NonNull Insets mPipMenuTemporaryDecorInsets = Insets.NONE;
@Orientation
private int mTvFixedPipOrientation;
@Nullable
private Size mTvExpandedSize;
@NonNull
private Insets mPipMenuPermanentDecorInsets = Insets.NONE;
@NonNull
private Insets mPipMenuTemporaryDecorInsets = Insets.NONE;
public TvPipBoundsState(@NonNull Context context) {
super(context);
mContext = context;
updateDefaultGravity();
mPreviousCollapsedGravity = mDefaultGravity;
mIsTvExpandedPipSupported = context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_EXPANDED_PICTURE_IN_PICTURE);
}
public int getDefaultGravity() {
return mDefaultGravity;
}
private void updateDefaultGravity() {
boolean isRtl = mContext.getResources().getConfiguration().getLayoutDirection()
== View.LAYOUT_DIRECTION_RTL;
mDefaultGravity = Gravity.BOTTOM | (isRtl ? Gravity.LEFT : Gravity.RIGHT);
if (mIsRtl != isRtl) {
int prevGravityX = mPreviousCollapsedGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
int prevGravityY = mPreviousCollapsedGravity & Gravity.VERTICAL_GRAVITY_MASK;
if ((prevGravityX & Gravity.RIGHT) == Gravity.RIGHT) {
mPreviousCollapsedGravity = Gravity.LEFT | prevGravityY;
} else if ((prevGravityX & Gravity.LEFT) == Gravity.LEFT) {
mPreviousCollapsedGravity = Gravity.RIGHT | prevGravityY;
}
}
mIsRtl = isRtl;
}
@Override
public void onConfigurationChanged() {
updateDefaultGravity();
}
/**
* Initialize states when first entering PiP.
*/
@@ -86,7 +124,8 @@ public class TvPipBoundsState extends PipBoundsState {
/** Resets the TV PiP state for a new activity. */
public void resetTvPipState() {
mTvFixedPipOrientation = ORIENTATION_UNDETERMINED;
mTvPipGravity = DEFAULT_TV_GRAVITY;
mTvPipGravity = mDefaultGravity;
mPreviousCollapsedGravity = mDefaultGravity;
mTvPipManuallyCollapsed = false;
}
@@ -102,16 +141,23 @@ public class TvPipBoundsState extends PipBoundsState {
}
/** Set the PiP aspect ratio for the expanded PiP (TV) that is desired by the app. */
public void setDesiredTvExpandedAspectRatio(float aspectRatio, boolean override) {
public void setDesiredTvExpandedAspectRatio(float expandedAspectRatio, boolean override) {
if (override || mTvFixedPipOrientation == ORIENTATION_UNDETERMINED) {
mDesiredTvExpandedAspectRatio = aspectRatio;
resetTvPipState();
mDesiredTvExpandedAspectRatio = expandedAspectRatio;
if (expandedAspectRatio != 0) {
if (expandedAspectRatio > 1) {
mTvFixedPipOrientation = ORIENTATION_HORIZONTAL;
} else {
mTvFixedPipOrientation = ORIENTATION_VERTICAL;
}
}
return;
}
if ((aspectRatio > 1 && mTvFixedPipOrientation == ORIENTATION_HORIZONTAL)
|| (aspectRatio <= 1 && mTvFixedPipOrientation == ORIENTATION_VERTICAL)
|| aspectRatio == 0) {
mDesiredTvExpandedAspectRatio = aspectRatio;
if ((expandedAspectRatio > 1 && mTvFixedPipOrientation == ORIENTATION_HORIZONTAL)
|| (expandedAspectRatio <= 1 && mTvFixedPipOrientation == ORIENTATION_VERTICAL)
|| expandedAspectRatio == 0) {
mDesiredTvExpandedAspectRatio = expandedAspectRatio;
}
}
@@ -123,11 +169,6 @@ public class TvPipBoundsState extends PipBoundsState {
return mDesiredTvExpandedAspectRatio;
}
/** Sets the orientation the expanded TV PiP activity has been fixed to. */
public void setTvFixedPipOrientation(@Orientation int orientation) {
mTvFixedPipOrientation = orientation;
}
/** Returns the fixed orientation of the expanded PiP on TV. */
@Orientation
public int getTvFixedPipOrientation() {
@@ -144,6 +185,14 @@ public class TvPipBoundsState extends PipBoundsState {
return mTvPipGravity;
}
public void setTvPipPreviousCollapsedGravity(int gravity) {
mPreviousCollapsedGravity = gravity;
}
public int getTvPipPreviousCollapsedGravity() {
return mPreviousCollapsedGravity;
}
/** Sets whether the TV PiP is currently expanded. */
public void setTvPipExpanded(boolean expanded) {
mIsTvPipExpanded = expanded;
@@ -173,7 +222,8 @@ public class TvPipBoundsState extends PipBoundsState {
mPipMenuPermanentDecorInsets = permanentInsets;
}
public @NonNull Insets getPipMenuPermanentDecorInsets() {
@NonNull
public Insets getPipMenuPermanentDecorInsets() {
return mPipMenuPermanentDecorInsets;
}
@@ -181,7 +231,8 @@ public class TvPipBoundsState extends PipBoundsState {
mPipMenuTemporaryDecorInsets = temporaryDecorInsets;
}
public @NonNull Insets getPipMenuTemporaryDecorInsets() {
@NonNull
public Insets getPipMenuTemporaryDecorInsets() {
return mPipMenuTemporaryDecorInsets;
}
}

View File

@@ -18,6 +18,8 @@ package com.android.wm.shell.pip.tv;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.view.KeyEvent.KEYCODE_DPAD_LEFT;
import static android.view.KeyEvent.KEYCODE_DPAD_RIGHT;
import android.annotation.IntDef;
import android.app.ActivityManager;
@@ -137,7 +139,6 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
@State
private int mState = STATE_NO_PIP;
private int mPreviousGravity = TvPipBoundsState.DEFAULT_TV_GRAVITY;
private int mPinnedTaskId = NONEXISTENT_TASK_ID;
// How long the shell will wait for the app to close the PiP if a custom action is set.
@@ -214,6 +215,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
mTvPipBoundsState = tvPipBoundsState;
mTvPipBoundsState.setDisplayId(context.getDisplayId());
mTvPipBoundsState.setDisplayLayout(new DisplayLayout(context, context.getDisplay()));
mTvPipBoundsAlgorithm = tvPipBoundsAlgorithm;
mTvPipBoundsController = tvPipBoundsController;
mTvPipBoundsController.setListener(this);
@@ -243,7 +245,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
private void onInit() {
mPipTransitionController.registerPipTransitionCallback(this);
loadConfigurations();
reloadResources();
registerPipParamsChangedListener(mPipParamsChangedForwarder);
registerTaskStackListenerCallback(mTaskStackListener);
@@ -266,9 +268,38 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: onConfigurationChanged(), state=%s", TAG, stateToName(mState));
loadConfigurations();
int previousDefaultGravityX = mTvPipBoundsState.getDefaultGravity()
& Gravity.HORIZONTAL_GRAVITY_MASK;
reloadResources();
mPipNotificationController.onConfigurationChanged();
mTvPipBoundsAlgorithm.onConfigurationChanged(mContext);
mTvPipBoundsState.onConfigurationChanged();
int defaultGravityX = mTvPipBoundsState.getDefaultGravity()
& Gravity.HORIZONTAL_GRAVITY_MASK;
if (isPipShown() && previousDefaultGravityX != defaultGravityX) {
movePipToOppositeSide();
}
}
private void reloadResources() {
final Resources res = mContext.getResources();
mResizeAnimationDuration = res.getInteger(R.integer.config_pipResizeAnimationDuration);
mPipForceCloseDelay = res.getInteger(R.integer.config_pipForceCloseDelay);
mEduTextWindowExitAnimationDuration =
res.getInteger(R.integer.pip_edu_text_window_exit_animation_duration);
}
private void movePipToOppositeSide() {
ProtoLog.i(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: movePipToOppositeSide", TAG);
if ((mTvPipBoundsState.getTvPipGravity() & Gravity.RIGHT) == Gravity.RIGHT) {
movePip(KEYCODE_DPAD_LEFT);
} else if ((mTvPipBoundsState.getTvPipGravity() & Gravity.LEFT) == Gravity.LEFT) {
movePip(KEYCODE_DPAD_RIGHT);
}
}
/**
@@ -332,11 +363,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: togglePipExpansion()", TAG);
boolean expanding = !mTvPipBoundsState.isTvPipExpanded();
int saveGravity = mTvPipBoundsAlgorithm
.updateGravityOnExpandToggled(mPreviousGravity, expanding);
if (saveGravity != Gravity.NO_GRAVITY) {
mPreviousGravity = saveGravity;
}
mTvPipBoundsAlgorithm.updateGravityOnExpansionToggled(expanding);
mTvPipBoundsState.setTvPipManuallyCollapsed(!expanding);
mTvPipBoundsState.setTvPipExpanded(expanding);
@@ -347,7 +374,6 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
public void movePip(int keycode) {
if (mTvPipBoundsAlgorithm.updateGravity(keycode)) {
mTvPipMenuController.updateGravity(mTvPipBoundsState.getTvPipGravity());
mPreviousGravity = Gravity.NO_GRAVITY;
updatePinnedStackBounds();
} else {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
@@ -355,15 +381,6 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
}
}
@Override
public int getPipGravity() {
return mTvPipBoundsState.getTvPipGravity();
}
public int getOrientation() {
return mTvPipBoundsState.getTvFixedPipOrientation();
}
@Override
public void onKeepClearAreasChanged(int displayId, Set<Rect> restricted,
Set<Rect> unrestricted) {
@@ -516,14 +533,6 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
mState = state;
}
private void loadConfigurations() {
final Resources res = mContext.getResources();
mResizeAnimationDuration = res.getInteger(R.integer.config_pipResizeAnimationDuration);
mPipForceCloseDelay = res.getInteger(R.integer.config_pipForceCloseDelay);
mEduTextWindowExitAnimationDuration =
res.getInteger(R.integer.pip_edu_text_window_exit_animation_duration);
}
private void registerTaskStackListenerCallback(TaskStackListenerImpl taskStackListener) {
taskStackListener.addListener(new TaskStackListenerCallback() {
@Override
@@ -596,11 +605,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
// 2) PiP is expanded, but expanded PiP was disabled
// --> collapse PiP
if (mTvPipBoundsState.isTvPipExpanded() && ratio == 0) {
int saveGravity = mTvPipBoundsAlgorithm
.updateGravityOnExpandToggled(mPreviousGravity, false);
if (saveGravity != Gravity.NO_GRAVITY) {
mPreviousGravity = saveGravity;
}
mTvPipBoundsAlgorithm.updateGravityOnExpansionToggled(/* expanding= */ false);
mTvPipBoundsState.setTvPipExpanded(false);
updatePinnedStackBounds();
}
@@ -610,11 +615,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
if (!mTvPipBoundsState.isTvPipExpanded() && ratio != 0
&& !mTvPipBoundsState.isTvPipManuallyCollapsed()) {
mTvPipBoundsAlgorithm.updateExpandedPipSize();
int saveGravity = mTvPipBoundsAlgorithm
.updateGravityOnExpandToggled(mPreviousGravity, true);
if (saveGravity != Gravity.NO_GRAVITY) {
mPreviousGravity = saveGravity;
}
mTvPipBoundsAlgorithm.updateGravityOnExpansionToggled(/* expanding= */ true);
mTvPipBoundsState.setTvPipExpanded(true);
updatePinnedStackBounds();
}

View File

@@ -199,7 +199,7 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis
"%s: showMovementMenuOnly()", TAG);
setInMoveMode(true);
if (mMenuIsOpen) {
mPipMenuView.showMoveMenu(mDelegate.getPipGravity());
mPipMenuView.showMoveMenu(mTvPipBoundsState.getTvPipGravity());
} else {
mCloseAfterExitMoveMenu = true;
showMenuInternal();
@@ -222,7 +222,7 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis
mMenuIsOpen = true;
grantPipMenuFocus(true);
if (mInMoveMode) {
mPipMenuView.showMoveMenu(mDelegate.getPipGravity());
mPipMenuView.showMoveMenu(mTvPipBoundsState.getTvPipGravity());
} else {
mPipMenuView.showButtonsMenu(/* exitingMoveMode= */ false);
}
@@ -236,7 +236,9 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis
}
void updateGravity(int gravity) {
mPipMenuView.showMovementHints(gravity);
if (mInMoveMode) {
mPipMenuView.showMovementHints(gravity);
}
}
private Rect calculateMenuSurfaceBounds(Rect pipBounds) {
@@ -500,8 +502,6 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis
void onInMoveModeChanged();
int getPipGravity();
void onMenuClosed();
void closeEduText();

View File

@@ -0,0 +1,324 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.wm.shell.pip.tv;
import static android.view.KeyEvent.KEYCODE_DPAD_DOWN;
import static android.view.KeyEvent.KEYCODE_DPAD_LEFT;
import static android.view.KeyEvent.KEYCODE_DPAD_RIGHT;
import static android.view.KeyEvent.KEYCODE_DPAD_UP;
import static org.junit.Assert.assertEquals;
import android.view.Gravity;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.pip.PipSnapAlgorithm;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Locale;
public class TvPipGravityTest extends ShellTestCase {
private static final float VERTICAL_EXPANDED_ASPECT_RATIO = 1f / 3;
private static final float HORIZONTAL_EXPANDED_ASPECT_RATIO = 3f;
@Mock
private PipSnapAlgorithm mMockPipSnapAlgorithm;
private TvPipBoundsState mTvPipBoundsState;
private TvPipBoundsAlgorithm mTvPipBoundsAlgorithm;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mTvPipBoundsState = new TvPipBoundsState(mContext);
mTvPipBoundsAlgorithm = new TvPipBoundsAlgorithm(mContext, mTvPipBoundsState,
mMockPipSnapAlgorithm);
setRTL(false);
}
private void checkGravity(int gravityActual, int gravityExpected) {
assertEquals(gravityExpected, gravityActual);
}
private void setRTL(boolean isRtl) {
mContext.getResources().getConfiguration().setLayoutDirection(
isRtl ? new Locale("ar") : Locale.ENGLISH);
mTvPipBoundsState.onConfigurationChanged();
mTvPipBoundsAlgorithm.onConfigurationChanged(mContext);
}
private void assertGravityAfterExpansion(int gravityFrom, int gravityTo) {
mTvPipBoundsState.setTvPipExpanded(false);
mTvPipBoundsState.setTvPipGravity(gravityFrom);
mTvPipBoundsAlgorithm.updateGravityOnExpansionToggled(true);
checkGravity(mTvPipBoundsState.getTvPipGravity(), gravityTo);
}
private void assertGravityAfterCollapse(int gravityFrom, int gravityTo) {
mTvPipBoundsState.setTvPipExpanded(true);
mTvPipBoundsState.setTvPipGravity(gravityFrom);
mTvPipBoundsAlgorithm.updateGravityOnExpansionToggled(false);
checkGravity(mTvPipBoundsState.getTvPipGravity(), gravityTo);
}
private void assertGravityAfterExpandAndCollapse(int gravityStartAndEnd) {
mTvPipBoundsState.setTvPipGravity(gravityStartAndEnd);
mTvPipBoundsAlgorithm.updateGravityOnExpansionToggled(true);
mTvPipBoundsAlgorithm.updateGravityOnExpansionToggled(false);
checkGravity(mTvPipBoundsState.getTvPipGravity(), gravityStartAndEnd);
}
@Test
public void regularPip_defaultGravity() {
checkGravity(mTvPipBoundsState.getDefaultGravity(), Gravity.RIGHT | Gravity.BOTTOM);
}
@Test
public void regularPip_defaultGravity_RTL() {
setRTL(true);
checkGravity(mTvPipBoundsState.getDefaultGravity(), Gravity.LEFT | Gravity.BOTTOM);
}
@Test
public void updateGravity_expand_vertical() {
// Vertical expanded PiP.
mTvPipBoundsState.setDesiredTvExpandedAspectRatio(VERTICAL_EXPANDED_ASPECT_RATIO, true);
assertGravityAfterExpansion(Gravity.BOTTOM | Gravity.RIGHT,
Gravity.CENTER_VERTICAL | Gravity.RIGHT);
assertGravityAfterExpansion(Gravity.TOP | Gravity.RIGHT,
Gravity.CENTER_VERTICAL | Gravity.RIGHT);
assertGravityAfterExpansion(Gravity.BOTTOM | Gravity.LEFT,
Gravity.CENTER_VERTICAL | Gravity.LEFT);
assertGravityAfterExpansion(Gravity.TOP | Gravity.LEFT,
Gravity.CENTER_VERTICAL | Gravity.LEFT);
}
@Test
public void updateGravity_expand_horizontal() {
// Horizontal expanded PiP.
mTvPipBoundsState.setDesiredTvExpandedAspectRatio(HORIZONTAL_EXPANDED_ASPECT_RATIO, true);
assertGravityAfterExpansion(Gravity.BOTTOM | Gravity.RIGHT,
Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
assertGravityAfterExpansion(Gravity.TOP | Gravity.RIGHT,
Gravity.TOP | Gravity.CENTER_HORIZONTAL);
assertGravityAfterExpansion(Gravity.BOTTOM | Gravity.LEFT,
Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
assertGravityAfterExpansion(Gravity.TOP | Gravity.LEFT,
Gravity.TOP | Gravity.CENTER_HORIZONTAL);
}
@Test
public void updateGravity_collapse() {
// Vertical expansion
mTvPipBoundsState.setDesiredTvExpandedAspectRatio(VERTICAL_EXPANDED_ASPECT_RATIO, true);
assertGravityAfterCollapse(Gravity.CENTER_VERTICAL | Gravity.RIGHT,
Gravity.BOTTOM | Gravity.RIGHT);
assertGravityAfterCollapse(Gravity.CENTER_VERTICAL | Gravity.LEFT,
Gravity.BOTTOM | Gravity.LEFT);
// Horizontal expansion
mTvPipBoundsState.setDesiredTvExpandedAspectRatio(HORIZONTAL_EXPANDED_ASPECT_RATIO, true);
assertGravityAfterCollapse(Gravity.TOP | Gravity.CENTER_HORIZONTAL,
Gravity.TOP | Gravity.RIGHT);
assertGravityAfterCollapse(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL,
Gravity.BOTTOM | Gravity.RIGHT);
}
@Test
public void updateGravity_collapse_RTL() {
setRTL(true);
// Horizontal expansion
mTvPipBoundsState.setDesiredTvExpandedAspectRatio(HORIZONTAL_EXPANDED_ASPECT_RATIO, true);
assertGravityAfterCollapse(Gravity.TOP | Gravity.CENTER_HORIZONTAL,
Gravity.TOP | Gravity.LEFT);
assertGravityAfterCollapse(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL,
Gravity.BOTTOM | Gravity.LEFT);
}
@Test
public void updateGravity_expand_collapse() {
// Vertical expanded PiP.
mTvPipBoundsState.setDesiredTvExpandedAspectRatio(VERTICAL_EXPANDED_ASPECT_RATIO, true);
assertGravityAfterExpandAndCollapse(Gravity.BOTTOM | Gravity.RIGHT);
assertGravityAfterExpandAndCollapse(Gravity.BOTTOM | Gravity.LEFT);
assertGravityAfterExpandAndCollapse(Gravity.TOP | Gravity.LEFT);
assertGravityAfterExpandAndCollapse(Gravity.TOP | Gravity.RIGHT);
// Horizontal expanded PiP.
mTvPipBoundsState.setDesiredTvExpandedAspectRatio(HORIZONTAL_EXPANDED_ASPECT_RATIO, true);
assertGravityAfterExpandAndCollapse(Gravity.BOTTOM | Gravity.RIGHT);
assertGravityAfterExpandAndCollapse(Gravity.BOTTOM | Gravity.LEFT);
assertGravityAfterExpandAndCollapse(Gravity.TOP | Gravity.LEFT);
assertGravityAfterExpandAndCollapse(Gravity.TOP | Gravity.RIGHT);
}
@Test
public void updateGravity_expand_move_collapse() {
// Vertical expanded PiP.
mTvPipBoundsState.setDesiredTvExpandedAspectRatio(VERTICAL_EXPANDED_ASPECT_RATIO, true);
expandMoveCollapseCheck(Gravity.TOP | Gravity.RIGHT, KEYCODE_DPAD_LEFT,
Gravity.TOP | Gravity.LEFT);
// Horizontal expanded PiP.
mTvPipBoundsState.setDesiredTvExpandedAspectRatio(HORIZONTAL_EXPANDED_ASPECT_RATIO, true);
expandMoveCollapseCheck(Gravity.BOTTOM | Gravity.LEFT, KEYCODE_DPAD_UP,
Gravity.TOP | Gravity.LEFT);
}
private void expandMoveCollapseCheck(int gravityFrom, int keycode, int gravityTo) {
// Expand
mTvPipBoundsState.setTvPipExpanded(false);
mTvPipBoundsState.setTvPipGravity(gravityFrom);
mTvPipBoundsAlgorithm.updateGravityOnExpansionToggled(true);
// Move
mTvPipBoundsAlgorithm.updateGravity(keycode);
// Collapse
mTvPipBoundsState.setTvPipExpanded(true);
mTvPipBoundsAlgorithm.updateGravityOnExpansionToggled(false);
checkGravity(mTvPipBoundsState.getTvPipGravity(), gravityTo);
}
private void moveAndCheckGravity(int keycode, int gravityEnd, boolean expectChange) {
assertEquals(expectChange, mTvPipBoundsAlgorithm.updateGravity(keycode));
checkGravity(mTvPipBoundsState.getTvPipGravity(), gravityEnd);
}
@Test
public void updateGravity_move_regular_valid() {
mTvPipBoundsState.setTvPipGravity(Gravity.BOTTOM | Gravity.RIGHT);
// clockwise
moveAndCheckGravity(KEYCODE_DPAD_LEFT, Gravity.BOTTOM | Gravity.LEFT, true);
moveAndCheckGravity(KEYCODE_DPAD_UP, Gravity.TOP | Gravity.LEFT, true);
moveAndCheckGravity(KEYCODE_DPAD_RIGHT, Gravity.TOP | Gravity.RIGHT, true);
moveAndCheckGravity(KEYCODE_DPAD_DOWN, Gravity.BOTTOM | Gravity.RIGHT, true);
// anti-clockwise
moveAndCheckGravity(KEYCODE_DPAD_UP, Gravity.TOP | Gravity.RIGHT, true);
moveAndCheckGravity(KEYCODE_DPAD_LEFT, Gravity.TOP | Gravity.LEFT, true);
moveAndCheckGravity(KEYCODE_DPAD_DOWN, Gravity.BOTTOM | Gravity.LEFT, true);
moveAndCheckGravity(KEYCODE_DPAD_RIGHT, Gravity.BOTTOM | Gravity.RIGHT, true);
}
@Test
public void updateGravity_move_expanded_valid() {
mTvPipBoundsState.setTvPipExpanded(true);
// Vertical expanded PiP.
mTvPipBoundsState.setDesiredTvExpandedAspectRatio(VERTICAL_EXPANDED_ASPECT_RATIO, true);
mTvPipBoundsState.setTvPipGravity(Gravity.CENTER_VERTICAL | Gravity.RIGHT);
moveAndCheckGravity(KEYCODE_DPAD_LEFT, Gravity.CENTER_VERTICAL | Gravity.LEFT, true);
moveAndCheckGravity(KEYCODE_DPAD_RIGHT, Gravity.CENTER_VERTICAL | Gravity.RIGHT, true);
// Horizontal expanded PiP.
mTvPipBoundsState.setDesiredTvExpandedAspectRatio(HORIZONTAL_EXPANDED_ASPECT_RATIO, true);
mTvPipBoundsState.setTvPipGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
moveAndCheckGravity(KEYCODE_DPAD_UP, Gravity.TOP | Gravity.CENTER_HORIZONTAL, true);
moveAndCheckGravity(KEYCODE_DPAD_DOWN, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, true);
}
@Test
public void updateGravity_move_regular_invalid() {
int gravity = Gravity.BOTTOM | Gravity.RIGHT;
mTvPipBoundsState.setTvPipGravity(gravity);
moveAndCheckGravity(KEYCODE_DPAD_DOWN, gravity, false);
moveAndCheckGravity(KEYCODE_DPAD_RIGHT, gravity, false);
gravity = Gravity.BOTTOM | Gravity.LEFT;
mTvPipBoundsState.setTvPipGravity(gravity);
moveAndCheckGravity(KEYCODE_DPAD_DOWN, gravity, false);
moveAndCheckGravity(KEYCODE_DPAD_LEFT, gravity, false);
gravity = Gravity.TOP | Gravity.LEFT;
mTvPipBoundsState.setTvPipGravity(gravity);
moveAndCheckGravity(KEYCODE_DPAD_UP, gravity, false);
moveAndCheckGravity(KEYCODE_DPAD_LEFT, gravity, false);
gravity = Gravity.TOP | Gravity.RIGHT;
mTvPipBoundsState.setTvPipGravity(gravity);
moveAndCheckGravity(KEYCODE_DPAD_UP, gravity, false);
moveAndCheckGravity(KEYCODE_DPAD_RIGHT, gravity, false);
}
@Test
public void updateGravity_move_expanded_invalid() {
mTvPipBoundsState.setTvPipExpanded(true);
// Vertical expanded PiP.
mTvPipBoundsState.setDesiredTvExpandedAspectRatio(VERTICAL_EXPANDED_ASPECT_RATIO, true);
mTvPipBoundsState.setTvPipGravity(Gravity.CENTER_VERTICAL | Gravity.RIGHT);
moveAndCheckGravity(KEYCODE_DPAD_RIGHT, Gravity.CENTER_VERTICAL | Gravity.RIGHT, false);
moveAndCheckGravity(KEYCODE_DPAD_UP, Gravity.CENTER_VERTICAL | Gravity.RIGHT, false);
moveAndCheckGravity(KEYCODE_DPAD_DOWN, Gravity.CENTER_VERTICAL | Gravity.RIGHT, false);
mTvPipBoundsState.setTvPipGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
moveAndCheckGravity(KEYCODE_DPAD_LEFT, Gravity.CENTER_VERTICAL | Gravity.LEFT, false);
moveAndCheckGravity(KEYCODE_DPAD_UP, Gravity.CENTER_VERTICAL | Gravity.LEFT, false);
moveAndCheckGravity(KEYCODE_DPAD_DOWN, Gravity.CENTER_VERTICAL | Gravity.LEFT, false);
// Horizontal expanded PiP.
mTvPipBoundsState.setDesiredTvExpandedAspectRatio(HORIZONTAL_EXPANDED_ASPECT_RATIO, true);
mTvPipBoundsState.setTvPipGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
moveAndCheckGravity(KEYCODE_DPAD_DOWN, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, false);
moveAndCheckGravity(KEYCODE_DPAD_LEFT, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, false);
moveAndCheckGravity(KEYCODE_DPAD_RIGHT, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, false);
mTvPipBoundsState.setTvPipGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
moveAndCheckGravity(KEYCODE_DPAD_UP, Gravity.TOP | Gravity.CENTER_HORIZONTAL, false);
moveAndCheckGravity(KEYCODE_DPAD_LEFT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, false);
moveAndCheckGravity(KEYCODE_DPAD_RIGHT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, false);
}
@Test
public void previousCollapsedGravity_defaultValue() {
assertEquals(mTvPipBoundsState.getTvPipPreviousCollapsedGravity(),
mTvPipBoundsState.getDefaultGravity());
setRTL(true);
assertEquals(mTvPipBoundsState.getTvPipPreviousCollapsedGravity(),
mTvPipBoundsState.getDefaultGravity());
}
@Test
public void previousCollapsedGravity_changes_on_RTL() {
mTvPipBoundsState.setTvPipPreviousCollapsedGravity(Gravity.TOP | Gravity.LEFT);
setRTL(true);
assertEquals(mTvPipBoundsState.getTvPipPreviousCollapsedGravity(),
Gravity.TOP | Gravity.RIGHT);
setRTL(false);
assertEquals(mTvPipBoundsState.getTvPipPreviousCollapsedGravity(),
Gravity.TOP | Gravity.LEFT);
mTvPipBoundsState.setTvPipPreviousCollapsedGravity(Gravity.BOTTOM | Gravity.RIGHT);
setRTL(true);
assertEquals(mTvPipBoundsState.getTvPipPreviousCollapsedGravity(),
Gravity.BOTTOM | Gravity.LEFT);
setRTL(false);
assertEquals(mTvPipBoundsState.getTvPipPreviousCollapsedGravity(),
Gravity.BOTTOM | Gravity.RIGHT);
}
}