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:
@@ -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>
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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() {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user