Add corner radius for PiP window

Per UI/UX, the radius is fixed to 8dp, configurable in SystemUI
resources. Also included in this CL:
- deprecated scheduleFinishEnterPip with a more meaningful transition
direction @IntDef
- consolidate the parameter orders in PipTaskOrganizer,
    Sf.Transtion > from / to bounds > direction > duration > others

Screenshot
- https://screenshot.googleplex.com/y67xOhM7Hxt.png
- https://screenshot.googleplex.com/EUvw63Y8ckY.png

Bug: 137390622
Test: Enter/expand/collapse PiP
Test: atest PipAnimationControllerTest
Test: atest PinnedStackTests
Change-Id: I87231746b34c36eba6aaec77b61c9249e835fd47
This commit is contained in:
Hongwei Wang
2020-03-03 17:41:02 -08:00
parent 381b9c1781
commit df8bb00371
4 changed files with 168 additions and 112 deletions

View File

@@ -983,6 +983,9 @@
<!-- The touchable/draggable edge size for PIP resize. -->
<dimen name="pip_resize_edge_size">30dp</dimen>
<!-- The corner radius for PiP window. -->
<dimen name="pip_corner_radius">8dp</dimen>
<dimen name="default_gear_space">18dp</dimen>
<dimen name="cell_overlay_padding">18dp</dimen>

View File

@@ -37,7 +37,6 @@ public class PipAnimationController {
private static final float FRACTION_START = 0f;
private static final float FRACTION_END = 1f;
public static final int DURATION_NONE = 0;
public static final int DURATION_DEFAULT_MS = 425;
public static final int ANIM_TYPE_BOUNDS = 0;
public static final int ANIM_TYPE_ALPHA = 1;
@@ -49,6 +48,20 @@ public class PipAnimationController {
@Retention(RetentionPolicy.SOURCE)
public @interface AnimationType {}
static final int TRANSITION_DIRECTION_NONE = 0;
static final int TRANSITION_DIRECTION_SAME = 1;
static final int TRANSITION_DIRECTION_TO_PIP = 2;
static final int TRANSITION_DIRECTION_TO_FULLSCREEN = 3;
@IntDef(prefix = { "TRANSITION_DIRECTION_" }, value = {
TRANSITION_DIRECTION_NONE,
TRANSITION_DIRECTION_SAME,
TRANSITION_DIRECTION_TO_PIP,
TRANSITION_DIRECTION_TO_FULLSCREEN
})
@Retention(RetentionPolicy.SOURCE)
@interface TransitionDirection {}
private final Interpolator mFastOutSlowInInterpolator;
private PipTransitionAnimator mCurrentAnimator;
@@ -58,30 +71,28 @@ public class PipAnimationController {
com.android.internal.R.interpolator.fast_out_slow_in);
}
PipTransitionAnimator getAnimator(SurfaceControl leash, boolean scheduleFinishPip,
@SuppressWarnings("unchecked")
PipTransitionAnimator getAnimator(SurfaceControl leash,
Rect destinationBounds, float alphaStart, float alphaEnd) {
if (mCurrentAnimator == null) {
mCurrentAnimator = setupPipTransitionAnimator(
PipTransitionAnimator.ofAlpha(leash, scheduleFinishPip, destinationBounds,
alphaStart, alphaEnd));
PipTransitionAnimator.ofAlpha(leash, destinationBounds, alphaStart, alphaEnd));
} else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_ALPHA
&& mCurrentAnimator.isRunning()) {
mCurrentAnimator.updateEndValue(alphaEnd);
} else {
mCurrentAnimator.cancel();
mCurrentAnimator = setupPipTransitionAnimator(
PipTransitionAnimator.ofAlpha(leash, scheduleFinishPip, destinationBounds,
alphaStart, alphaEnd));
PipTransitionAnimator.ofAlpha(leash, destinationBounds, alphaStart, alphaEnd));
}
return mCurrentAnimator;
}
PipTransitionAnimator getAnimator(SurfaceControl leash, boolean scheduleFinishPip,
Rect startBounds, Rect endBounds) {
@SuppressWarnings("unchecked")
PipTransitionAnimator getAnimator(SurfaceControl leash, Rect startBounds, Rect endBounds) {
if (mCurrentAnimator == null) {
mCurrentAnimator = setupPipTransitionAnimator(
PipTransitionAnimator.ofBounds(leash, scheduleFinishPip,
startBounds, endBounds));
PipTransitionAnimator.ofBounds(leash, startBounds, endBounds));
} else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_BOUNDS
&& mCurrentAnimator.isRunning()) {
mCurrentAnimator.setDestinationBounds(endBounds);
@@ -90,8 +101,7 @@ public class PipAnimationController {
} else {
mCurrentAnimator.cancel();
mCurrentAnimator = setupPipTransitionAnimator(
PipTransitionAnimator.ofBounds(leash, scheduleFinishPip,
startBounds, endBounds));
PipTransitionAnimator.ofBounds(leash, startBounds, endBounds));
}
return mCurrentAnimator;
}
@@ -134,7 +144,6 @@ public class PipAnimationController {
public abstract static class PipTransitionAnimator<T> extends ValueAnimator implements
ValueAnimator.AnimatorUpdateListener,
ValueAnimator.AnimatorListener {
private final boolean mScheduleFinishPip;
private final SurfaceControl mLeash;
private final @AnimationType int mAnimationType;
private final Rect mDestinationBounds = new Rect();
@@ -144,11 +153,11 @@ public class PipAnimationController {
private T mCurrentValue;
private PipAnimationCallback mPipAnimationCallback;
private SurfaceControlTransactionFactory mSurfaceControlTransactionFactory;
private @TransitionDirection int mTransitionDirection;
private int mCornerRadius;
private PipTransitionAnimator(SurfaceControl leash, boolean scheduleFinishPip,
@AnimationType int animationType, Rect destinationBounds,
T startValue, T endValue) {
mScheduleFinishPip = scheduleFinishPip;
private PipTransitionAnimator(SurfaceControl leash, @AnimationType int animationType,
Rect destinationBounds, T startValue, T endValue) {
mLeash = leash;
mAnimationType = animationType;
mDestinationBounds.set(destinationBounds);
@@ -157,6 +166,7 @@ public class PipAnimationController {
addListener(this);
addUpdateListener(this);
mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
mTransitionDirection = TRANSITION_DIRECTION_NONE;
}
@Override
@@ -202,8 +212,15 @@ public class PipAnimationController {
return this;
}
boolean shouldScheduleFinishPip() {
return mScheduleFinishPip;
@TransitionDirection int getTransitionDirection() {
return mTransitionDirection;
}
PipTransitionAnimator<T> setTransitionDirection(@TransitionDirection int direction) {
if (direction != TRANSITION_DIRECTION_SAME) {
mTransitionDirection = direction;
}
return this;
}
T getStartValue() {
@@ -226,6 +243,19 @@ public class PipAnimationController {
mCurrentValue = value;
}
int getCornerRadius() {
return mCornerRadius;
}
PipTransitionAnimator<T> setCornerRadius(int cornerRadius) {
mCornerRadius = cornerRadius;
return this;
}
boolean shouldApplyCornerRadius() {
return mTransitionDirection != TRANSITION_DIRECTION_TO_FULLSCREEN;
}
/**
* Updates the {@link #mEndValue}.
*
@@ -251,9 +281,9 @@ public class PipAnimationController {
abstract void applySurfaceControlTransaction(SurfaceControl leash,
SurfaceControl.Transaction tx, float fraction);
static PipTransitionAnimator<Float> ofAlpha(SurfaceControl leash, boolean scheduleFinishPip,
static PipTransitionAnimator<Float> ofAlpha(SurfaceControl leash,
Rect destinationBounds, float startValue, float endValue) {
return new PipTransitionAnimator<Float>(leash, scheduleFinishPip, ANIM_TYPE_ALPHA,
return new PipTransitionAnimator<Float>(leash, ANIM_TYPE_ALPHA,
destinationBounds, startValue, endValue) {
@Override
void applySurfaceControlTransaction(SurfaceControl leash,
@@ -266,16 +296,18 @@ public class PipAnimationController {
final Rect bounds = getDestinationBounds();
tx.setPosition(leash, bounds.left, bounds.top)
.setWindowCrop(leash, bounds.width(), bounds.height());
tx.setCornerRadius(leash,
shouldApplyCornerRadius() ? getCornerRadius() : 0);
}
tx.apply();
}
};
}
static PipTransitionAnimator<Rect> ofBounds(SurfaceControl leash, boolean scheduleFinishPip,
static PipTransitionAnimator<Rect> ofBounds(SurfaceControl leash,
Rect startValue, Rect endValue) {
// construct new Rect instances in case they are recycled
return new PipTransitionAnimator<Rect>(leash, scheduleFinishPip, ANIM_TYPE_BOUNDS,
return new PipTransitionAnimator<Rect>(leash, ANIM_TYPE_BOUNDS,
endValue, new Rect(startValue), new Rect(endValue)) {
private final Rect mTmpRect = new Rect();
@@ -299,6 +331,8 @@ public class PipAnimationController {
if (Float.compare(fraction, FRACTION_START) == 0) {
// Ensure the start condition
tx.setAlpha(leash, 1f);
tx.setCornerRadius(leash,
shouldApplyCornerRadius() ? getCornerRadius() : 0);
}
tx.apply();
}

View File

@@ -19,6 +19,10 @@ package com.android.systemui.pip;
import static com.android.systemui.pip.PipAnimationController.ANIM_TYPE_ALPHA;
import static com.android.systemui.pip.PipAnimationController.ANIM_TYPE_BOUNDS;
import static com.android.systemui.pip.PipAnimationController.DURATION_DEFAULT_MS;
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_NONE;
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_SAME;
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_FULLSCREEN;
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -30,7 +34,6 @@ import android.content.Context;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
import android.view.DisplayInfo;
@@ -40,6 +43,7 @@ import android.view.SurfaceControl;
import android.view.WindowContainerTransaction;
import com.android.internal.os.SomeArgs;
import com.android.systemui.R;
import com.android.systemui.pip.phone.PipUpdateThread;
import java.util.ArrayList;
@@ -74,6 +78,7 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
private final List<PipTransitionCallback> mPipTransitionCallbacks = new ArrayList<>();
private final Rect mDisplayBounds = new Rect();
private final Rect mLastReportedBounds = new Rect();
private final int mCornerRadius;
// These callbacks are called on the update thread
private final PipAnimationController.PipAnimationCallback mPipAnimationCallback =
@@ -97,7 +102,7 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
callback.onPipTransitionFinished();
}
});
finishResize(animator.getDestinationBounds(), tx, animator.shouldScheduleFinishPip());
finishResize(tx, animator.getDestinationBounds(), animator.getTransitionDirection());
}
@Override
@@ -111,57 +116,53 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
}
};
private Handler.Callback mUpdateCallbacks = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
SomeArgs args = (SomeArgs) msg.obj;
Consumer<Rect> updateBoundsCallback = (Consumer<Rect>) args.arg1;
switch (msg.what) {
case MSG_RESIZE_IMMEDIATE: {
Rect toBounds = (Rect) args.arg2;
resizePip(toBounds);
if (updateBoundsCallback != null) {
updateBoundsCallback.accept(toBounds);
}
break;
}
case MSG_RESIZE_ANIMATE: {
Rect currentBounds = (Rect) args.arg2;
Rect toBounds = (Rect) args.arg3;
boolean scheduleFinishPip = args.argi1 != 0;
int duration = args.argi2;
animateResizePip(scheduleFinishPip, currentBounds, toBounds, duration);
if (updateBoundsCallback != null) {
updateBoundsCallback.accept(toBounds);
}
break;
}
case MSG_OFFSET_ANIMATE: {
Rect originalBounds = (Rect) args.arg2;
final int offset = args.argi1;
final int duration = args.argi2;
offsetPip(originalBounds, 0 /* xOffset */, offset, duration);
Rect toBounds = new Rect(originalBounds);
toBounds.offset(0, offset);
if (updateBoundsCallback != null) {
updateBoundsCallback.accept(toBounds);
}
break;
}
case MSG_FINISH_RESIZE: {
SurfaceControl.Transaction tx = (SurfaceControl.Transaction) args.arg2;
Rect toBounds = (Rect) args.arg3;
boolean scheduleFinishPip = args.argi1 != 0;
finishResize(toBounds, tx, scheduleFinishPip);
if (updateBoundsCallback != null) {
updateBoundsCallback.accept(toBounds);
}
break;
@SuppressWarnings("unchecked")
private Handler.Callback mUpdateCallbacks = (msg) -> {
SomeArgs args = (SomeArgs) msg.obj;
Consumer<Rect> updateBoundsCallback = (Consumer<Rect>) args.arg1;
switch (msg.what) {
case MSG_RESIZE_IMMEDIATE: {
Rect toBounds = (Rect) args.arg2;
resizePip(toBounds);
if (updateBoundsCallback != null) {
updateBoundsCallback.accept(toBounds);
}
break;
}
case MSG_RESIZE_ANIMATE: {
Rect currentBounds = (Rect) args.arg2;
Rect toBounds = (Rect) args.arg3;
int duration = args.argi2;
animateResizePip(currentBounds, toBounds, args.argi1 /* direction */, duration);
if (updateBoundsCallback != null) {
updateBoundsCallback.accept(toBounds);
}
break;
}
case MSG_OFFSET_ANIMATE: {
Rect originalBounds = (Rect) args.arg2;
final int offset = args.argi1;
final int duration = args.argi2;
offsetPip(originalBounds, 0 /* xOffset */, offset, duration);
Rect toBounds = new Rect(originalBounds);
toBounds.offset(0, offset);
if (updateBoundsCallback != null) {
updateBoundsCallback.accept(toBounds);
}
break;
}
case MSG_FINISH_RESIZE: {
SurfaceControl.Transaction tx = (SurfaceControl.Transaction) args.arg2;
Rect toBounds = (Rect) args.arg3;
finishResize(tx, toBounds, args.argi1 /* direction */);
if (updateBoundsCallback != null) {
updateBoundsCallback.accept(toBounds);
}
break;
}
args.recycle();
return true;
}
args.recycle();
return true;
};
private ActivityManager.RunningTaskInfo mTaskInfo;
@@ -176,6 +177,7 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
mTaskOrganizerController = ActivityTaskManager.getTaskOrganizerController();
mPipBoundsHandler = boundsHandler;
mPipAnimationController = new PipAnimationController(context);
mCornerRadius = context.getResources().getDimensionPixelSize(R.dimen.pip_corner_radius);
}
public Handler getUpdateHandler() {
@@ -191,7 +193,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
/**
* Sets the preferred animation type for one time.
* This is typically used to set the animation type to {@link #ANIM_TYPE_ALPHA}.
* This is typically used to set the animation type to
* {@link PipAnimationController#ANIM_TYPE_ALPHA}.
*/
public void setOneShotAnimationType(@PipAnimationController.AnimationType int animationType) {
mOneShotAnimationType = animationType;
@@ -200,13 +203,14 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
/**
* Updates the display dimension with given {@link DisplayInfo}
*/
@SuppressWarnings("unchecked")
public void onDisplayInfoChanged(DisplayInfo displayInfo) {
final Rect newDisplayBounds = new Rect(0, 0,
displayInfo.logicalWidth, displayInfo.logicalHeight);
if (!mDisplayBounds.equals(newDisplayBounds)) {
// Updates the exiting PiP animation in case the screen rotation changes in the middle.
// It's a legit case that PiP window is in portrait mode on home screen and
// the application requests landscape onces back to fullscreen mode.
// the application requests landscape once back to fullscreen mode.
final PipAnimationController.PipTransitionAnimator animator =
mPipAnimationController.getCurrentAnimator();
if (animator != null
@@ -250,12 +254,13 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
}
if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds();
scheduleAnimateResizePip(true /* scheduleFinishPip */,
currentBounds, destinationBounds, DURATION_DEFAULT_MS, null);
scheduleAnimateResizePip(currentBounds, destinationBounds,
TRANSITION_DIRECTION_TO_PIP, DURATION_DEFAULT_MS, null);
} else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
mUpdateHandler.post(() -> mPipAnimationController
.getAnimator(mLeash, true /* scheduleFinishPip */,
destinationBounds, 0f, 1f)
.getAnimator(mLeash, destinationBounds, 0f, 1f)
.setTransitionDirection(TRANSITION_DIRECTION_TO_PIP)
.setCornerRadius(mCornerRadius)
.setPipAnimationCallback(mPipAnimationCallback)
.setDuration(DURATION_DEFAULT_MS)
.start());
@@ -272,7 +277,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
Log.wtf(TAG, "Unrecognized token: " + token);
return;
}
scheduleAnimateResizePip(mDisplayBounds, DURATION_DEFAULT_MS, null);
scheduleAnimateResizePip(mLastReportedBounds, mDisplayBounds,
TRANSITION_DIRECTION_TO_FULLSCREEN, DURATION_DEFAULT_MS, null);
mInPip = false;
}
@@ -310,12 +316,12 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
*/
public void scheduleAnimateResizePip(Rect toBounds, int duration,
Consumer<Rect> updateBoundsCallback) {
scheduleAnimateResizePip(false /* scheduleFinishPip */,
mLastReportedBounds, toBounds, duration, updateBoundsCallback);
scheduleAnimateResizePip(mLastReportedBounds, toBounds,
TRANSITION_DIRECTION_NONE, duration, updateBoundsCallback);
}
private void scheduleAnimateResizePip(boolean scheduleFinishPip,
Rect currentBounds, Rect destinationBounds, int durationMs,
private void scheduleAnimateResizePip(Rect currentBounds, Rect destinationBounds,
@PipAnimationController.TransitionDirection int direction, int durationMs,
Consumer<Rect> updateBoundsCallback) {
Objects.requireNonNull(mToken, "Requires valid IWindowContainer");
if (!mInPip) {
@@ -326,7 +332,7 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
args.arg1 = updateBoundsCallback;
args.arg2 = currentBounds;
args.arg3 = destinationBounds;
args.argi1 = scheduleFinishPip ? 1 : 0;
args.argi1 = direction;
args.argi2 = durationMs;
mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_RESIZE_ANIMATE, args));
}
@@ -351,25 +357,25 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
Objects.requireNonNull(mToken, "Requires valid IWindowContainer");
SurfaceControl.Transaction tx = new SurfaceControl.Transaction()
.setPosition(mLeash, destinationBounds.left, destinationBounds.top)
.setWindowCrop(mLeash, destinationBounds.width(), destinationBounds.height());
scheduleFinishResizePip(tx, destinationBounds, false /* scheduleFinishPip */,
null);
.setWindowCrop(mLeash, destinationBounds.width(), destinationBounds.height())
.setCornerRadius(mLeash, mInPip ? mCornerRadius : 0);
scheduleFinishResizePip(tx, destinationBounds, TRANSITION_DIRECTION_NONE, null);
}
private void scheduleFinishResizePip(SurfaceControl.Transaction tx,
Rect destinationBounds, boolean scheduleFinishPip,
Rect destinationBounds, @PipAnimationController.TransitionDirection int direction,
Consumer<Rect> updateBoundsCallback) {
Objects.requireNonNull(mToken, "Requires valid IWindowContainer");
SomeArgs args = SomeArgs.obtain();
args.arg1 = updateBoundsCallback;
args.arg2 = tx;
args.arg3 = destinationBounds;
args.argi1 = scheduleFinishPip ? 1 : 0;
args.argi1 = direction;
mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_FINISH_RESIZE, args));
}
/**
* Offset the PiP window, animate if the given duration is not {@link #DURATION_NONE}
* Offset the PiP window by a given offset on Y-axis, triggered also from screen rotation.
*/
public void scheduleOffsetPip(Rect originalBounds, int offset, int duration,
Consumer<Rect> updateBoundsCallback) {
@@ -398,8 +404,7 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
}
final Rect destinationBounds = new Rect(originalBounds);
destinationBounds.offset(xOffset, yOffset);
animateResizePip(false /* scheduleFinishPip*/, originalBounds, destinationBounds,
durationMs);
animateResizePip(originalBounds, destinationBounds, TRANSITION_DIRECTION_SAME, durationMs);
}
private void resizePip(Rect destinationBounds) {
@@ -416,11 +421,12 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
new SurfaceControl.Transaction()
.setPosition(mLeash, destinationBounds.left, destinationBounds.top)
.setWindowCrop(mLeash, destinationBounds.width(), destinationBounds.height())
.setCornerRadius(mLeash, mInPip ? mCornerRadius : 0)
.apply();
}
private void finishResize(Rect destinationBounds, SurfaceControl.Transaction tx,
boolean shouldScheduleFinishPip) {
private void finishResize(SurfaceControl.Transaction tx, Rect destinationBounds,
@PipAnimationController.TransitionDirection int direction) {
if (Looper.myLooper() != mUpdateHandler.getLooper()) {
throw new RuntimeException("Callers should call scheduleResizePip() instead of this "
+ "directly");
@@ -428,7 +434,7 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
mLastReportedBounds.set(destinationBounds);
try {
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (shouldScheduleFinishPip) {
if (direction == TRANSITION_DIRECTION_TO_PIP) {
wct.scheduleFinishEnterPip(mToken, destinationBounds);
} else {
wct.setBounds(mToken, destinationBounds);
@@ -440,8 +446,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
}
}
private void animateResizePip(boolean scheduleFinishPip, Rect currentBounds,
Rect destinationBounds, int durationMs) {
private void animateResizePip(Rect currentBounds, Rect destinationBounds,
@PipAnimationController.TransitionDirection int direction, int durationMs) {
if (Looper.myLooper() != mUpdateHandler.getLooper()) {
throw new RuntimeException("Callers should call scheduleAnimateResizePip() instead of "
+ "this directly");
@@ -452,7 +458,9 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
return;
}
mUpdateHandler.post(() -> mPipAnimationController
.getAnimator(mLeash, scheduleFinishPip, currentBounds, destinationBounds)
.getAnimator(mLeash, currentBounds, destinationBounds)
.setTransitionDirection(direction)
.setCornerRadius(mCornerRadius)
.setPipAnimationCallback(mPipAnimationCallback)
.setDuration(durationMs)
.start());

View File

@@ -16,9 +16,10 @@
package com.android.systemui.pip;
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_FULLSCREEN;
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
@@ -64,7 +65,7 @@ public class PipAnimationControllerTest extends SysuiTestCase {
@Test
public void getAnimator_withAlpha_returnFloatAnimator() {
final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
.getAnimator(mLeash, true /* scheduleFinishPip */, new Rect(), 0f, 1f);
.getAnimator(mLeash, new Rect(), 0f, 1f);
assertEquals("Expect ANIM_TYPE_ALPHA animation",
animator.getAnimationType(), PipAnimationController.ANIM_TYPE_ALPHA);
@@ -73,7 +74,7 @@ public class PipAnimationControllerTest extends SysuiTestCase {
@Test
public void getAnimator_withBounds_returnBoundsAnimator() {
final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
.getAnimator(mLeash, true /* scheduleFinishPip */, new Rect(), new Rect());
.getAnimator(mLeash, new Rect(), new Rect());
assertEquals("Expect ANIM_TYPE_BOUNDS animation",
animator.getAnimationType(), PipAnimationController.ANIM_TYPE_BOUNDS);
@@ -85,12 +86,12 @@ public class PipAnimationControllerTest extends SysuiTestCase {
final Rect endValue1 = new Rect(100, 100, 200, 200);
final Rect endValue2 = new Rect(200, 200, 300, 300);
final PipAnimationController.PipTransitionAnimator oldAnimator = mPipAnimationController
.getAnimator(mLeash, true /* scheduleFinishPip */, startValue, endValue1);
.getAnimator(mLeash, startValue, endValue1);
oldAnimator.setSurfaceControlTransactionFactory(DummySurfaceControlTx::new);
oldAnimator.start();
final PipAnimationController.PipTransitionAnimator newAnimator = mPipAnimationController
.getAnimator(mLeash, true /* scheduleFinishPip */, startValue, endValue2);
.getAnimator(mLeash, startValue, endValue2);
assertEquals("getAnimator with same type returns same animator",
oldAnimator, newAnimator);
@@ -99,23 +100,28 @@ public class PipAnimationControllerTest extends SysuiTestCase {
}
@Test
public void getAnimator_scheduleFinishPip() {
public void getAnimator_setTransitionDirection() {
PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
.getAnimator(mLeash, true /* scheduleFinishPip */, new Rect(), 0f, 1f);
assertTrue("scheduleFinishPip is true", animator.shouldScheduleFinishPip());
.getAnimator(mLeash, new Rect(), 0f, 1f)
.setTransitionDirection(TRANSITION_DIRECTION_TO_PIP);
assertEquals("Transition to PiP mode",
animator.getTransitionDirection(), TRANSITION_DIRECTION_TO_PIP);
animator = mPipAnimationController
.getAnimator(mLeash, false /* scheduleFinishPip */, new Rect(), 0f, 1f);
assertFalse("scheduleFinishPip is false", animator.shouldScheduleFinishPip());
.getAnimator(mLeash, new Rect(), 0f, 1f)
.setTransitionDirection(TRANSITION_DIRECTION_TO_FULLSCREEN);
assertEquals("Transition to fullscreen mode",
animator.getTransitionDirection(), TRANSITION_DIRECTION_TO_FULLSCREEN);
}
@Test
@SuppressWarnings("unchecked")
public void pipTransitionAnimator_updateEndValue() {
final Rect startValue = new Rect(0, 0, 100, 100);
final Rect endValue1 = new Rect(100, 100, 200, 200);
final Rect endValue2 = new Rect(200, 200, 300, 300);
final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
.getAnimator(mLeash, true /* scheduleFinishPip */, startValue, endValue1);
.getAnimator(mLeash, startValue, endValue1);
animator.updateEndValue(endValue2);
@@ -127,7 +133,7 @@ public class PipAnimationControllerTest extends SysuiTestCase {
final Rect startValue = new Rect(0, 0, 100, 100);
final Rect endValue = new Rect(100, 100, 200, 200);
final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
.getAnimator(mLeash, true /* scheduleFinishPip */, startValue, endValue);
.getAnimator(mLeash, startValue, endValue);
animator.setSurfaceControlTransactionFactory(DummySurfaceControlTx::new);
animator.setPipAnimationCallback(mPipAnimationCallback);
@@ -166,6 +172,11 @@ public class PipAnimationControllerTest extends SysuiTestCase {
return this;
}
@Override
public SurfaceControl.Transaction setCornerRadius(SurfaceControl leash, float radius) {
return this;
}
@Override
public void apply() {}
}