Move IME & shelf visibility/height into PipBoundsState
Bug: 169373982 Test: com.android.wm.shell.pip Change-Id: I411d857c57e2dc593c3506318f5ce1ab6d625b08
This commit is contained in:
@@ -59,11 +59,6 @@ public class PipBoundsHandler {
|
||||
private int mDefaultMinSize;
|
||||
private Point mScreenEdgeInsets;
|
||||
|
||||
private boolean mIsImeShowing;
|
||||
private int mImeHeight;
|
||||
private boolean mIsShelfShowing;
|
||||
private int mShelfHeight;
|
||||
|
||||
public PipBoundsHandler(Context context, @NonNull PipBoundsState pipBoundsState) {
|
||||
mPipBoundsState = pipBoundsState;
|
||||
mSnapAlgorithm = new PipSnapAlgorithm(context);
|
||||
@@ -100,29 +95,6 @@ public class PipBoundsHandler {
|
||||
com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets both shelf visibility and its height if applicable.
|
||||
* @return {@code true} if the internal shelf state is changed, {@code false} otherwise.
|
||||
*/
|
||||
public boolean setShelfHeight(boolean shelfVisible, int shelfHeight) {
|
||||
final boolean shelfShowing = shelfVisible && shelfHeight > 0;
|
||||
if (shelfShowing == mIsShelfShowing && shelfHeight == mShelfHeight) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mIsShelfShowing = shelfVisible;
|
||||
mShelfHeight = shelfHeight;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Responds to IPinnedStackListener on IME visibility change.
|
||||
*/
|
||||
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
|
||||
mIsImeShowing = imeVisible;
|
||||
mImeHeight = imeHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Responds to IPinnedStackListener on movement bounds change.
|
||||
* Note that both inset and normal bounds will be calculated here rather than in the caller.
|
||||
@@ -360,8 +332,10 @@ public class PipBoundsHandler {
|
||||
mDefaultMinSize, displayInfo.logicalWidth, displayInfo.logicalHeight);
|
||||
}
|
||||
Gravity.apply(mDefaultStackGravity, defaultSize.getWidth(), defaultSize.getHeight(),
|
||||
insetBounds, 0, Math.max(mIsImeShowing ? mImeHeight : 0,
|
||||
mIsShelfShowing ? mShelfHeight : 0), defaultBounds);
|
||||
insetBounds, 0, Math.max(
|
||||
mPipBoundsState.isImeShowing() ? mPipBoundsState.getImeHeight() : 0,
|
||||
mPipBoundsState.isShelfShowing()
|
||||
? mPipBoundsState.getShelfHeight() : 0), defaultBounds);
|
||||
}
|
||||
return defaultBounds;
|
||||
}
|
||||
@@ -396,7 +370,8 @@ public class PipBoundsHandler {
|
||||
|
||||
// Apply the movement bounds adjustments based on the current state.
|
||||
mSnapAlgorithm.getMovementBounds(stackBounds, movementBounds, movementBounds,
|
||||
(adjustForIme && mIsImeShowing) ? mImeHeight : 0);
|
||||
(adjustForIme && mPipBoundsState.isImeShowing())
|
||||
? mPipBoundsState.getImeHeight() : 0);
|
||||
return movementBounds;
|
||||
}
|
||||
|
||||
@@ -437,10 +412,6 @@ public class PipBoundsHandler {
|
||||
pw.println(innerPrefix + "mMinAspectRatio=" + mMinAspectRatio);
|
||||
pw.println(innerPrefix + "mMaxAspectRatio=" + mMaxAspectRatio);
|
||||
pw.println(innerPrefix + "mDefaultStackGravity=" + mDefaultStackGravity);
|
||||
pw.println(innerPrefix + "mIsImeShowing=" + mIsImeShowing);
|
||||
pw.println(innerPrefix + "mImeHeight=" + mImeHeight);
|
||||
pw.println(innerPrefix + "mIsShelfShowing=" + mIsShelfShowing);
|
||||
pw.println(innerPrefix + "mShelfHeight=" + mShelfHeight);
|
||||
pw.println(innerPrefix + "mSnapAlgorithm" + mSnapAlgorithm);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import java.io.PrintWriter;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
/**
|
||||
* Singleton source of truth for the current state of PIP bounds.
|
||||
@@ -66,8 +67,13 @@ public final class PipBoundsState {
|
||||
/** The preferred minimum (and default) size specified by apps. */
|
||||
private Size mOverrideMinSize;
|
||||
private final @NonNull AnimatingBoundsState mAnimatingBoundsState = new AnimatingBoundsState();
|
||||
private boolean mIsImeShowing;
|
||||
private int mImeHeight;
|
||||
private boolean mIsShelfShowing;
|
||||
private int mShelfHeight;
|
||||
|
||||
private Runnable mOnMinimalSizeChangeCallback;
|
||||
private BiConsumer<Boolean, Integer> mOnShelfVisibilityChangeCallback;
|
||||
|
||||
public PipBoundsState(Context context) {
|
||||
mContext = context;
|
||||
@@ -245,6 +251,46 @@ public final class PipBoundsState {
|
||||
return mAnimatingBoundsState;
|
||||
}
|
||||
|
||||
/** Set whether the IME is currently showing and its height. */
|
||||
public void setImeVisibility(boolean imeShowing, int imeHeight) {
|
||||
mIsImeShowing = imeShowing;
|
||||
mImeHeight = imeHeight;
|
||||
}
|
||||
|
||||
/** Returns whether the IME is currently showing. */
|
||||
public boolean isImeShowing() {
|
||||
return mIsImeShowing;
|
||||
}
|
||||
|
||||
/** Returns the IME height. */
|
||||
public int getImeHeight() {
|
||||
return mImeHeight;
|
||||
}
|
||||
|
||||
/** Set whether the shelf is showing and its height. */
|
||||
public void setShelfVisibility(boolean showing, int height) {
|
||||
final boolean shelfShowing = showing && height > 0;
|
||||
if (shelfShowing == mIsShelfShowing && height == mShelfHeight) {
|
||||
return;
|
||||
}
|
||||
|
||||
mIsShelfShowing = showing;
|
||||
mShelfHeight = height;
|
||||
if (mOnShelfVisibilityChangeCallback != null) {
|
||||
mOnShelfVisibilityChangeCallback.accept(mIsShelfShowing, mShelfHeight);
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns whether the shelf is currently showing. */
|
||||
public boolean isShelfShowing() {
|
||||
return mIsShelfShowing;
|
||||
}
|
||||
|
||||
/** Returns the shelf height. */
|
||||
public int getShelfHeight() {
|
||||
return mShelfHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback when the minimal size of PIP that is set by the app changes.
|
||||
*/
|
||||
@@ -252,6 +298,12 @@ public final class PipBoundsState {
|
||||
mOnMinimalSizeChangeCallback = onMinimalSizeChangeCallback;
|
||||
}
|
||||
|
||||
/** Set a callback to be notified when the shelf visibility changes. */
|
||||
public void setOnShelfVisibilityChangeCallback(
|
||||
BiConsumer<Boolean, Integer> onShelfVisibilityChangeCallback) {
|
||||
mOnShelfVisibilityChangeCallback = onShelfVisibilityChangeCallback;
|
||||
}
|
||||
|
||||
/** Source of truth for the current animation bounds of PIP. */
|
||||
public static class AnimatingBoundsState {
|
||||
/** The bounds used when PIP is being dragged or animated. */
|
||||
@@ -345,6 +397,10 @@ public final class PipBoundsState {
|
||||
pw.println(innerPrefix + "mStashOffset=" + mStashOffset);
|
||||
pw.println(innerPrefix + "mMinEdgeSize=" + mMinEdgeSize);
|
||||
pw.println(innerPrefix + "mOverrideMinSize=" + mOverrideMinSize);
|
||||
pw.println(innerPrefix + "mIsImeShowing=" + mIsImeShowing);
|
||||
pw.println(innerPrefix + "mImeHeight=" + mImeHeight);
|
||||
pw.println(innerPrefix + "mIsShelfShowing=" + mIsShelfShowing);
|
||||
pw.println(innerPrefix + "mShelfHeight=" + mShelfHeight);
|
||||
if (mPipReentryState == null) {
|
||||
pw.println(innerPrefix + "mPipReentryState=null");
|
||||
} else {
|
||||
|
||||
@@ -125,8 +125,8 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
|
||||
// not during the fixed rotation. In fixed rotation case, app is about to enter PiP
|
||||
// and we need the offsets preserved to calculate the destination bounds.
|
||||
if (!mIsInFixedRotation) {
|
||||
mPipBoundsHandler.setShelfHeight(false, 0);
|
||||
mPipBoundsHandler.onImeVisibilityChanged(false, 0);
|
||||
mPipBoundsState.setShelfVisibility(false /* showing */, 0 /* height */);
|
||||
mPipBoundsState.setImeVisibility(false /* showing */, 0 /* height */);
|
||||
mTouchHandler.onShelfVisibilityChanged(false, 0);
|
||||
mTouchHandler.onImeVisibilityChanged(false, 0);
|
||||
}
|
||||
@@ -168,7 +168,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
|
||||
@Override
|
||||
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
|
||||
mMainExecutor.execute(() -> {
|
||||
mPipBoundsHandler.onImeVisibilityChanged(imeVisible, imeHeight);
|
||||
mPipBoundsState.setImeVisibility(imeVisible, imeHeight);
|
||||
mTouchHandler.onImeVisibilityChanged(imeVisible, imeHeight);
|
||||
});
|
||||
}
|
||||
@@ -247,6 +247,12 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
|
||||
mPipBoundsState = pipBoundsState;
|
||||
mPipTaskOrganizer = pipTaskOrganizer;
|
||||
mMainExecutor = mainExecutor;
|
||||
mMediaController = pipMediaController;
|
||||
mMenuController = pipMenuActivityController;
|
||||
mTouchHandler = pipTouchHandler;
|
||||
mAppOpsListener = pipAppOpsListener;
|
||||
mPipInputConsumer = new PipInputConsumer(WindowManagerGlobal.getWindowManagerService(),
|
||||
INPUT_CONSUMER_PIP);
|
||||
mPipTaskOrganizer.registerPipTransitionCallback(this);
|
||||
mPipTaskOrganizer.registerOnDisplayIdChangeCallback((int displayId) -> {
|
||||
final DisplayInfo newDisplayInfo = new DisplayInfo();
|
||||
@@ -263,17 +269,17 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
|
||||
false /* fromImeAdjustment */, false /* fromShelfAdjustment */,
|
||||
null /* wct */);
|
||||
});
|
||||
mMediaController = pipMediaController;
|
||||
mMenuController = pipMenuActivityController;
|
||||
mPipInputConsumer = new PipInputConsumer(WindowManagerGlobal.getWindowManagerService(),
|
||||
INPUT_CONSUMER_PIP);
|
||||
mTouchHandler = pipTouchHandler;
|
||||
mPipBoundsState.setOnShelfVisibilityChangeCallback((isShowing, height) -> {
|
||||
mTouchHandler.onShelfVisibilityChanged(isShowing, height);
|
||||
updateMovementBounds(mPipBoundsState.getBounds(),
|
||||
false /* fromRotation */, false /* fromImeAdjustment */,
|
||||
true /* fromShelfAdjustment */, null /* windowContainerTransaction */);
|
||||
});
|
||||
if (mTouchHandler != null) {
|
||||
// Register the listener for input consumer touch events. Only for Phone
|
||||
mPipInputConsumer.setInputListener(mTouchHandler::handleTouchEvent);
|
||||
mPipInputConsumer.setRegistrationListener(mTouchHandler::onRegistrationChanged);
|
||||
}
|
||||
mAppOpsListener = pipAppOpsListener;
|
||||
displayController.addDisplayChangingController(mRotationController);
|
||||
displayController.addDisplayWindowListener(mFixedRotationListener);
|
||||
|
||||
@@ -413,13 +419,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
|
||||
|
||||
private void setShelfHeightLocked(boolean visible, int height) {
|
||||
final int shelfHeight = visible ? height : 0;
|
||||
final boolean changed = mPipBoundsHandler.setShelfHeight(visible, shelfHeight);
|
||||
if (changed) {
|
||||
mTouchHandler.onShelfVisibilityChanged(visible, shelfHeight);
|
||||
updateMovementBounds(mPipBoundsState.getBounds(),
|
||||
false /* fromRotation */, false /* fromImeAdjustment */,
|
||||
true /* fromShelfAdjustment */, null /* windowContainerTransaction */);
|
||||
}
|
||||
mPipBoundsState.setShelfVisibility(visible, shelfHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -184,7 +184,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
|
||||
@Override
|
||||
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
|
||||
mHandler.post(() -> {
|
||||
mPipBoundsHandler.onImeVisibilityChanged(imeVisible, imeHeight);
|
||||
mPipBoundsState.setImeVisibility(imeVisible, imeHeight);
|
||||
if (mState == STATE_PIP) {
|
||||
if (mImeVisible != imeVisible) {
|
||||
if (imeVisible) {
|
||||
|
||||
@@ -242,7 +242,7 @@ public class PipBoundsHandlerTest extends ShellTestCase {
|
||||
mPipBoundsState.setAspectRatio(DEFAULT_ASPECT_RATIO);
|
||||
final Rect oldPosition = mPipBoundsHandler.getEntryDestinationBounds();
|
||||
|
||||
mPipBoundsHandler.setShelfHeight(true, shelfHeight);
|
||||
mPipBoundsState.setShelfVisibility(true, shelfHeight);
|
||||
final Rect newPosition = mPipBoundsHandler.getEntryDestinationBounds();
|
||||
|
||||
oldPosition.offset(0, -shelfHeight);
|
||||
@@ -255,7 +255,7 @@ public class PipBoundsHandlerTest extends ShellTestCase {
|
||||
mPipBoundsState.setAspectRatio(DEFAULT_ASPECT_RATIO);
|
||||
final Rect oldPosition = mPipBoundsHandler.getEntryDestinationBounds();
|
||||
|
||||
mPipBoundsHandler.onImeVisibilityChanged(true, imeHeight);
|
||||
mPipBoundsState.setImeVisibility(true, imeHeight);
|
||||
final Rect newPosition = mPipBoundsHandler.getEntryDestinationBounds();
|
||||
|
||||
oldPosition.offset(0, -imeHeight);
|
||||
|
||||
@@ -19,6 +19,9 @@ package com.android.wm.shell.pip;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.graphics.Rect;
|
||||
@@ -34,6 +37,8 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
/**
|
||||
* Tests for {@link PipBoundsState}.
|
||||
*/
|
||||
@@ -109,4 +114,25 @@ public class PipBoundsStateTest extends ShellTestCase {
|
||||
|
||||
assertNull(mPipBoundsState.getReentryState());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetShelfVisibility_changed_callbackInvoked() {
|
||||
final BiConsumer<Boolean, Integer> callback = mock(BiConsumer.class);
|
||||
mPipBoundsState.setOnShelfVisibilityChangeCallback(callback);
|
||||
|
||||
mPipBoundsState.setShelfVisibility(true, 100);
|
||||
|
||||
verify(callback).accept(true, 100);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetShelfVisibility_notChanged_callbackNotInvoked() {
|
||||
final BiConsumer<Boolean, Integer> callback = mock(BiConsumer.class);
|
||||
mPipBoundsState.setShelfVisibility(true, 100);
|
||||
mPipBoundsState.setOnShelfVisibilityChangeCallback(callback);
|
||||
|
||||
mPipBoundsState.setShelfVisibility(true, 100);
|
||||
|
||||
verify(callback, never()).accept(true, 100);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user