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. -->
|
<!-- The touchable/draggable edge size for PIP resize. -->
|
||||||
<dimen name="pip_resize_edge_size">30dp</dimen>
|
<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="default_gear_space">18dp</dimen>
|
||||||
<dimen name="cell_overlay_padding">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_START = 0f;
|
||||||
private static final float FRACTION_END = 1f;
|
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 DURATION_DEFAULT_MS = 425;
|
||||||
public static final int ANIM_TYPE_BOUNDS = 0;
|
public static final int ANIM_TYPE_BOUNDS = 0;
|
||||||
public static final int ANIM_TYPE_ALPHA = 1;
|
public static final int ANIM_TYPE_ALPHA = 1;
|
||||||
@@ -49,6 +48,20 @@ public class PipAnimationController {
|
|||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
public @interface AnimationType {}
|
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 final Interpolator mFastOutSlowInInterpolator;
|
||||||
|
|
||||||
private PipTransitionAnimator mCurrentAnimator;
|
private PipTransitionAnimator mCurrentAnimator;
|
||||||
@@ -58,30 +71,28 @@ public class PipAnimationController {
|
|||||||
com.android.internal.R.interpolator.fast_out_slow_in);
|
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) {
|
Rect destinationBounds, float alphaStart, float alphaEnd) {
|
||||||
if (mCurrentAnimator == null) {
|
if (mCurrentAnimator == null) {
|
||||||
mCurrentAnimator = setupPipTransitionAnimator(
|
mCurrentAnimator = setupPipTransitionAnimator(
|
||||||
PipTransitionAnimator.ofAlpha(leash, scheduleFinishPip, destinationBounds,
|
PipTransitionAnimator.ofAlpha(leash, destinationBounds, alphaStart, alphaEnd));
|
||||||
alphaStart, alphaEnd));
|
|
||||||
} else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_ALPHA
|
} else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_ALPHA
|
||||||
&& mCurrentAnimator.isRunning()) {
|
&& mCurrentAnimator.isRunning()) {
|
||||||
mCurrentAnimator.updateEndValue(alphaEnd);
|
mCurrentAnimator.updateEndValue(alphaEnd);
|
||||||
} else {
|
} else {
|
||||||
mCurrentAnimator.cancel();
|
mCurrentAnimator.cancel();
|
||||||
mCurrentAnimator = setupPipTransitionAnimator(
|
mCurrentAnimator = setupPipTransitionAnimator(
|
||||||
PipTransitionAnimator.ofAlpha(leash, scheduleFinishPip, destinationBounds,
|
PipTransitionAnimator.ofAlpha(leash, destinationBounds, alphaStart, alphaEnd));
|
||||||
alphaStart, alphaEnd));
|
|
||||||
}
|
}
|
||||||
return mCurrentAnimator;
|
return mCurrentAnimator;
|
||||||
}
|
}
|
||||||
|
|
||||||
PipTransitionAnimator getAnimator(SurfaceControl leash, boolean scheduleFinishPip,
|
@SuppressWarnings("unchecked")
|
||||||
Rect startBounds, Rect endBounds) {
|
PipTransitionAnimator getAnimator(SurfaceControl leash, Rect startBounds, Rect endBounds) {
|
||||||
if (mCurrentAnimator == null) {
|
if (mCurrentAnimator == null) {
|
||||||
mCurrentAnimator = setupPipTransitionAnimator(
|
mCurrentAnimator = setupPipTransitionAnimator(
|
||||||
PipTransitionAnimator.ofBounds(leash, scheduleFinishPip,
|
PipTransitionAnimator.ofBounds(leash, startBounds, endBounds));
|
||||||
startBounds, endBounds));
|
|
||||||
} else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_BOUNDS
|
} else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_BOUNDS
|
||||||
&& mCurrentAnimator.isRunning()) {
|
&& mCurrentAnimator.isRunning()) {
|
||||||
mCurrentAnimator.setDestinationBounds(endBounds);
|
mCurrentAnimator.setDestinationBounds(endBounds);
|
||||||
@@ -90,8 +101,7 @@ public class PipAnimationController {
|
|||||||
} else {
|
} else {
|
||||||
mCurrentAnimator.cancel();
|
mCurrentAnimator.cancel();
|
||||||
mCurrentAnimator = setupPipTransitionAnimator(
|
mCurrentAnimator = setupPipTransitionAnimator(
|
||||||
PipTransitionAnimator.ofBounds(leash, scheduleFinishPip,
|
PipTransitionAnimator.ofBounds(leash, startBounds, endBounds));
|
||||||
startBounds, endBounds));
|
|
||||||
}
|
}
|
||||||
return mCurrentAnimator;
|
return mCurrentAnimator;
|
||||||
}
|
}
|
||||||
@@ -134,7 +144,6 @@ public class PipAnimationController {
|
|||||||
public abstract static class PipTransitionAnimator<T> extends ValueAnimator implements
|
public abstract static class PipTransitionAnimator<T> extends ValueAnimator implements
|
||||||
ValueAnimator.AnimatorUpdateListener,
|
ValueAnimator.AnimatorUpdateListener,
|
||||||
ValueAnimator.AnimatorListener {
|
ValueAnimator.AnimatorListener {
|
||||||
private final boolean mScheduleFinishPip;
|
|
||||||
private final SurfaceControl mLeash;
|
private final SurfaceControl mLeash;
|
||||||
private final @AnimationType int mAnimationType;
|
private final @AnimationType int mAnimationType;
|
||||||
private final Rect mDestinationBounds = new Rect();
|
private final Rect mDestinationBounds = new Rect();
|
||||||
@@ -144,11 +153,11 @@ public class PipAnimationController {
|
|||||||
private T mCurrentValue;
|
private T mCurrentValue;
|
||||||
private PipAnimationCallback mPipAnimationCallback;
|
private PipAnimationCallback mPipAnimationCallback;
|
||||||
private SurfaceControlTransactionFactory mSurfaceControlTransactionFactory;
|
private SurfaceControlTransactionFactory mSurfaceControlTransactionFactory;
|
||||||
|
private @TransitionDirection int mTransitionDirection;
|
||||||
|
private int mCornerRadius;
|
||||||
|
|
||||||
private PipTransitionAnimator(SurfaceControl leash, boolean scheduleFinishPip,
|
private PipTransitionAnimator(SurfaceControl leash, @AnimationType int animationType,
|
||||||
@AnimationType int animationType, Rect destinationBounds,
|
Rect destinationBounds, T startValue, T endValue) {
|
||||||
T startValue, T endValue) {
|
|
||||||
mScheduleFinishPip = scheduleFinishPip;
|
|
||||||
mLeash = leash;
|
mLeash = leash;
|
||||||
mAnimationType = animationType;
|
mAnimationType = animationType;
|
||||||
mDestinationBounds.set(destinationBounds);
|
mDestinationBounds.set(destinationBounds);
|
||||||
@@ -157,6 +166,7 @@ public class PipAnimationController {
|
|||||||
addListener(this);
|
addListener(this);
|
||||||
addUpdateListener(this);
|
addUpdateListener(this);
|
||||||
mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
|
mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
|
||||||
|
mTransitionDirection = TRANSITION_DIRECTION_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -202,8 +212,15 @@ public class PipAnimationController {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean shouldScheduleFinishPip() {
|
@TransitionDirection int getTransitionDirection() {
|
||||||
return mScheduleFinishPip;
|
return mTransitionDirection;
|
||||||
|
}
|
||||||
|
|
||||||
|
PipTransitionAnimator<T> setTransitionDirection(@TransitionDirection int direction) {
|
||||||
|
if (direction != TRANSITION_DIRECTION_SAME) {
|
||||||
|
mTransitionDirection = direction;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
T getStartValue() {
|
T getStartValue() {
|
||||||
@@ -226,6 +243,19 @@ public class PipAnimationController {
|
|||||||
mCurrentValue = value;
|
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}.
|
* Updates the {@link #mEndValue}.
|
||||||
*
|
*
|
||||||
@@ -251,9 +281,9 @@ public class PipAnimationController {
|
|||||||
abstract void applySurfaceControlTransaction(SurfaceControl leash,
|
abstract void applySurfaceControlTransaction(SurfaceControl leash,
|
||||||
SurfaceControl.Transaction tx, float fraction);
|
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) {
|
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) {
|
destinationBounds, startValue, endValue) {
|
||||||
@Override
|
@Override
|
||||||
void applySurfaceControlTransaction(SurfaceControl leash,
|
void applySurfaceControlTransaction(SurfaceControl leash,
|
||||||
@@ -266,16 +296,18 @@ public class PipAnimationController {
|
|||||||
final Rect bounds = getDestinationBounds();
|
final Rect bounds = getDestinationBounds();
|
||||||
tx.setPosition(leash, bounds.left, bounds.top)
|
tx.setPosition(leash, bounds.left, bounds.top)
|
||||||
.setWindowCrop(leash, bounds.width(), bounds.height());
|
.setWindowCrop(leash, bounds.width(), bounds.height());
|
||||||
|
tx.setCornerRadius(leash,
|
||||||
|
shouldApplyCornerRadius() ? getCornerRadius() : 0);
|
||||||
}
|
}
|
||||||
tx.apply();
|
tx.apply();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static PipTransitionAnimator<Rect> ofBounds(SurfaceControl leash, boolean scheduleFinishPip,
|
static PipTransitionAnimator<Rect> ofBounds(SurfaceControl leash,
|
||||||
Rect startValue, Rect endValue) {
|
Rect startValue, Rect endValue) {
|
||||||
// construct new Rect instances in case they are recycled
|
// 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)) {
|
endValue, new Rect(startValue), new Rect(endValue)) {
|
||||||
private final Rect mTmpRect = new Rect();
|
private final Rect mTmpRect = new Rect();
|
||||||
|
|
||||||
@@ -299,6 +331,8 @@ public class PipAnimationController {
|
|||||||
if (Float.compare(fraction, FRACTION_START) == 0) {
|
if (Float.compare(fraction, FRACTION_START) == 0) {
|
||||||
// Ensure the start condition
|
// Ensure the start condition
|
||||||
tx.setAlpha(leash, 1f);
|
tx.setAlpha(leash, 1f);
|
||||||
|
tx.setCornerRadius(leash,
|
||||||
|
shouldApplyCornerRadius() ? getCornerRadius() : 0);
|
||||||
}
|
}
|
||||||
tx.apply();
|
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_ALPHA;
|
||||||
import static com.android.systemui.pip.PipAnimationController.ANIM_TYPE_BOUNDS;
|
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.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.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
@@ -30,7 +34,6 @@ import android.content.Context;
|
|||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Message;
|
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.DisplayInfo;
|
import android.view.DisplayInfo;
|
||||||
@@ -40,6 +43,7 @@ import android.view.SurfaceControl;
|
|||||||
import android.view.WindowContainerTransaction;
|
import android.view.WindowContainerTransaction;
|
||||||
|
|
||||||
import com.android.internal.os.SomeArgs;
|
import com.android.internal.os.SomeArgs;
|
||||||
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.pip.phone.PipUpdateThread;
|
import com.android.systemui.pip.phone.PipUpdateThread;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -74,6 +78,7 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
private final List<PipTransitionCallback> mPipTransitionCallbacks = new ArrayList<>();
|
private final List<PipTransitionCallback> mPipTransitionCallbacks = new ArrayList<>();
|
||||||
private final Rect mDisplayBounds = new Rect();
|
private final Rect mDisplayBounds = new Rect();
|
||||||
private final Rect mLastReportedBounds = new Rect();
|
private final Rect mLastReportedBounds = new Rect();
|
||||||
|
private final int mCornerRadius;
|
||||||
|
|
||||||
// These callbacks are called on the update thread
|
// These callbacks are called on the update thread
|
||||||
private final PipAnimationController.PipAnimationCallback mPipAnimationCallback =
|
private final PipAnimationController.PipAnimationCallback mPipAnimationCallback =
|
||||||
@@ -97,7 +102,7 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
callback.onPipTransitionFinished();
|
callback.onPipTransitionFinished();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
finishResize(animator.getDestinationBounds(), tx, animator.shouldScheduleFinishPip());
|
finishResize(tx, animator.getDestinationBounds(), animator.getTransitionDirection());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -111,57 +116,53 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private Handler.Callback mUpdateCallbacks = new Handler.Callback() {
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
private Handler.Callback mUpdateCallbacks = (msg) -> {
|
||||||
public boolean handleMessage(Message msg) {
|
SomeArgs args = (SomeArgs) msg.obj;
|
||||||
SomeArgs args = (SomeArgs) msg.obj;
|
Consumer<Rect> updateBoundsCallback = (Consumer<Rect>) args.arg1;
|
||||||
Consumer<Rect> updateBoundsCallback = (Consumer<Rect>) args.arg1;
|
switch (msg.what) {
|
||||||
switch (msg.what) {
|
case MSG_RESIZE_IMMEDIATE: {
|
||||||
case MSG_RESIZE_IMMEDIATE: {
|
Rect toBounds = (Rect) args.arg2;
|
||||||
Rect toBounds = (Rect) args.arg2;
|
resizePip(toBounds);
|
||||||
resizePip(toBounds);
|
if (updateBoundsCallback != null) {
|
||||||
if (updateBoundsCallback != null) {
|
updateBoundsCallback.accept(toBounds);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
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;
|
private ActivityManager.RunningTaskInfo mTaskInfo;
|
||||||
@@ -176,6 +177,7 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
mTaskOrganizerController = ActivityTaskManager.getTaskOrganizerController();
|
mTaskOrganizerController = ActivityTaskManager.getTaskOrganizerController();
|
||||||
mPipBoundsHandler = boundsHandler;
|
mPipBoundsHandler = boundsHandler;
|
||||||
mPipAnimationController = new PipAnimationController(context);
|
mPipAnimationController = new PipAnimationController(context);
|
||||||
|
mCornerRadius = context.getResources().getDimensionPixelSize(R.dimen.pip_corner_radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Handler getUpdateHandler() {
|
public Handler getUpdateHandler() {
|
||||||
@@ -191,7 +193,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the preferred animation type for one time.
|
* 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) {
|
public void setOneShotAnimationType(@PipAnimationController.AnimationType int animationType) {
|
||||||
mOneShotAnimationType = animationType;
|
mOneShotAnimationType = animationType;
|
||||||
@@ -200,13 +203,14 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
/**
|
/**
|
||||||
* Updates the display dimension with given {@link DisplayInfo}
|
* Updates the display dimension with given {@link DisplayInfo}
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public void onDisplayInfoChanged(DisplayInfo displayInfo) {
|
public void onDisplayInfoChanged(DisplayInfo displayInfo) {
|
||||||
final Rect newDisplayBounds = new Rect(0, 0,
|
final Rect newDisplayBounds = new Rect(0, 0,
|
||||||
displayInfo.logicalWidth, displayInfo.logicalHeight);
|
displayInfo.logicalWidth, displayInfo.logicalHeight);
|
||||||
if (!mDisplayBounds.equals(newDisplayBounds)) {
|
if (!mDisplayBounds.equals(newDisplayBounds)) {
|
||||||
// Updates the exiting PiP animation in case the screen rotation changes in the middle.
|
// 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
|
// 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 =
|
final PipAnimationController.PipTransitionAnimator animator =
|
||||||
mPipAnimationController.getCurrentAnimator();
|
mPipAnimationController.getCurrentAnimator();
|
||||||
if (animator != null
|
if (animator != null
|
||||||
@@ -250,12 +254,13 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
}
|
}
|
||||||
if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
|
if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
|
||||||
final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds();
|
final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds();
|
||||||
scheduleAnimateResizePip(true /* scheduleFinishPip */,
|
scheduleAnimateResizePip(currentBounds, destinationBounds,
|
||||||
currentBounds, destinationBounds, DURATION_DEFAULT_MS, null);
|
TRANSITION_DIRECTION_TO_PIP, DURATION_DEFAULT_MS, null);
|
||||||
} else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
|
} else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
|
||||||
mUpdateHandler.post(() -> mPipAnimationController
|
mUpdateHandler.post(() -> mPipAnimationController
|
||||||
.getAnimator(mLeash, true /* scheduleFinishPip */,
|
.getAnimator(mLeash, destinationBounds, 0f, 1f)
|
||||||
destinationBounds, 0f, 1f)
|
.setTransitionDirection(TRANSITION_DIRECTION_TO_PIP)
|
||||||
|
.setCornerRadius(mCornerRadius)
|
||||||
.setPipAnimationCallback(mPipAnimationCallback)
|
.setPipAnimationCallback(mPipAnimationCallback)
|
||||||
.setDuration(DURATION_DEFAULT_MS)
|
.setDuration(DURATION_DEFAULT_MS)
|
||||||
.start());
|
.start());
|
||||||
@@ -272,7 +277,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
Log.wtf(TAG, "Unrecognized token: " + token);
|
Log.wtf(TAG, "Unrecognized token: " + token);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
scheduleAnimateResizePip(mDisplayBounds, DURATION_DEFAULT_MS, null);
|
scheduleAnimateResizePip(mLastReportedBounds, mDisplayBounds,
|
||||||
|
TRANSITION_DIRECTION_TO_FULLSCREEN, DURATION_DEFAULT_MS, null);
|
||||||
mInPip = false;
|
mInPip = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,12 +316,12 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
*/
|
*/
|
||||||
public void scheduleAnimateResizePip(Rect toBounds, int duration,
|
public void scheduleAnimateResizePip(Rect toBounds, int duration,
|
||||||
Consumer<Rect> updateBoundsCallback) {
|
Consumer<Rect> updateBoundsCallback) {
|
||||||
scheduleAnimateResizePip(false /* scheduleFinishPip */,
|
scheduleAnimateResizePip(mLastReportedBounds, toBounds,
|
||||||
mLastReportedBounds, toBounds, duration, updateBoundsCallback);
|
TRANSITION_DIRECTION_NONE, duration, updateBoundsCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scheduleAnimateResizePip(boolean scheduleFinishPip,
|
private void scheduleAnimateResizePip(Rect currentBounds, Rect destinationBounds,
|
||||||
Rect currentBounds, Rect destinationBounds, int durationMs,
|
@PipAnimationController.TransitionDirection int direction, int durationMs,
|
||||||
Consumer<Rect> updateBoundsCallback) {
|
Consumer<Rect> updateBoundsCallback) {
|
||||||
Objects.requireNonNull(mToken, "Requires valid IWindowContainer");
|
Objects.requireNonNull(mToken, "Requires valid IWindowContainer");
|
||||||
if (!mInPip) {
|
if (!mInPip) {
|
||||||
@@ -326,7 +332,7 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
args.arg1 = updateBoundsCallback;
|
args.arg1 = updateBoundsCallback;
|
||||||
args.arg2 = currentBounds;
|
args.arg2 = currentBounds;
|
||||||
args.arg3 = destinationBounds;
|
args.arg3 = destinationBounds;
|
||||||
args.argi1 = scheduleFinishPip ? 1 : 0;
|
args.argi1 = direction;
|
||||||
args.argi2 = durationMs;
|
args.argi2 = durationMs;
|
||||||
mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_RESIZE_ANIMATE, args));
|
mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_RESIZE_ANIMATE, args));
|
||||||
}
|
}
|
||||||
@@ -351,25 +357,25 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
Objects.requireNonNull(mToken, "Requires valid IWindowContainer");
|
Objects.requireNonNull(mToken, "Requires valid IWindowContainer");
|
||||||
SurfaceControl.Transaction tx = new SurfaceControl.Transaction()
|
SurfaceControl.Transaction tx = new SurfaceControl.Transaction()
|
||||||
.setPosition(mLeash, destinationBounds.left, destinationBounds.top)
|
.setPosition(mLeash, destinationBounds.left, destinationBounds.top)
|
||||||
.setWindowCrop(mLeash, destinationBounds.width(), destinationBounds.height());
|
.setWindowCrop(mLeash, destinationBounds.width(), destinationBounds.height())
|
||||||
scheduleFinishResizePip(tx, destinationBounds, false /* scheduleFinishPip */,
|
.setCornerRadius(mLeash, mInPip ? mCornerRadius : 0);
|
||||||
null);
|
scheduleFinishResizePip(tx, destinationBounds, TRANSITION_DIRECTION_NONE, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scheduleFinishResizePip(SurfaceControl.Transaction tx,
|
private void scheduleFinishResizePip(SurfaceControl.Transaction tx,
|
||||||
Rect destinationBounds, boolean scheduleFinishPip,
|
Rect destinationBounds, @PipAnimationController.TransitionDirection int direction,
|
||||||
Consumer<Rect> updateBoundsCallback) {
|
Consumer<Rect> updateBoundsCallback) {
|
||||||
Objects.requireNonNull(mToken, "Requires valid IWindowContainer");
|
Objects.requireNonNull(mToken, "Requires valid IWindowContainer");
|
||||||
SomeArgs args = SomeArgs.obtain();
|
SomeArgs args = SomeArgs.obtain();
|
||||||
args.arg1 = updateBoundsCallback;
|
args.arg1 = updateBoundsCallback;
|
||||||
args.arg2 = tx;
|
args.arg2 = tx;
|
||||||
args.arg3 = destinationBounds;
|
args.arg3 = destinationBounds;
|
||||||
args.argi1 = scheduleFinishPip ? 1 : 0;
|
args.argi1 = direction;
|
||||||
mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_FINISH_RESIZE, args));
|
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,
|
public void scheduleOffsetPip(Rect originalBounds, int offset, int duration,
|
||||||
Consumer<Rect> updateBoundsCallback) {
|
Consumer<Rect> updateBoundsCallback) {
|
||||||
@@ -398,8 +404,7 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
}
|
}
|
||||||
final Rect destinationBounds = new Rect(originalBounds);
|
final Rect destinationBounds = new Rect(originalBounds);
|
||||||
destinationBounds.offset(xOffset, yOffset);
|
destinationBounds.offset(xOffset, yOffset);
|
||||||
animateResizePip(false /* scheduleFinishPip*/, originalBounds, destinationBounds,
|
animateResizePip(originalBounds, destinationBounds, TRANSITION_DIRECTION_SAME, durationMs);
|
||||||
durationMs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resizePip(Rect destinationBounds) {
|
private void resizePip(Rect destinationBounds) {
|
||||||
@@ -416,11 +421,12 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
new SurfaceControl.Transaction()
|
new SurfaceControl.Transaction()
|
||||||
.setPosition(mLeash, destinationBounds.left, destinationBounds.top)
|
.setPosition(mLeash, destinationBounds.left, destinationBounds.top)
|
||||||
.setWindowCrop(mLeash, destinationBounds.width(), destinationBounds.height())
|
.setWindowCrop(mLeash, destinationBounds.width(), destinationBounds.height())
|
||||||
|
.setCornerRadius(mLeash, mInPip ? mCornerRadius : 0)
|
||||||
.apply();
|
.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void finishResize(Rect destinationBounds, SurfaceControl.Transaction tx,
|
private void finishResize(SurfaceControl.Transaction tx, Rect destinationBounds,
|
||||||
boolean shouldScheduleFinishPip) {
|
@PipAnimationController.TransitionDirection int direction) {
|
||||||
if (Looper.myLooper() != mUpdateHandler.getLooper()) {
|
if (Looper.myLooper() != mUpdateHandler.getLooper()) {
|
||||||
throw new RuntimeException("Callers should call scheduleResizePip() instead of this "
|
throw new RuntimeException("Callers should call scheduleResizePip() instead of this "
|
||||||
+ "directly");
|
+ "directly");
|
||||||
@@ -428,7 +434,7 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
mLastReportedBounds.set(destinationBounds);
|
mLastReportedBounds.set(destinationBounds);
|
||||||
try {
|
try {
|
||||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||||
if (shouldScheduleFinishPip) {
|
if (direction == TRANSITION_DIRECTION_TO_PIP) {
|
||||||
wct.scheduleFinishEnterPip(mToken, destinationBounds);
|
wct.scheduleFinishEnterPip(mToken, destinationBounds);
|
||||||
} else {
|
} else {
|
||||||
wct.setBounds(mToken, destinationBounds);
|
wct.setBounds(mToken, destinationBounds);
|
||||||
@@ -440,8 +446,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void animateResizePip(boolean scheduleFinishPip, Rect currentBounds,
|
private void animateResizePip(Rect currentBounds, Rect destinationBounds,
|
||||||
Rect destinationBounds, int durationMs) {
|
@PipAnimationController.TransitionDirection int direction, int durationMs) {
|
||||||
if (Looper.myLooper() != mUpdateHandler.getLooper()) {
|
if (Looper.myLooper() != mUpdateHandler.getLooper()) {
|
||||||
throw new RuntimeException("Callers should call scheduleAnimateResizePip() instead of "
|
throw new RuntimeException("Callers should call scheduleAnimateResizePip() instead of "
|
||||||
+ "this directly");
|
+ "this directly");
|
||||||
@@ -452,7 +458,9 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mUpdateHandler.post(() -> mPipAnimationController
|
mUpdateHandler.post(() -> mPipAnimationController
|
||||||
.getAnimator(mLeash, scheduleFinishPip, currentBounds, destinationBounds)
|
.getAnimator(mLeash, currentBounds, destinationBounds)
|
||||||
|
.setTransitionDirection(direction)
|
||||||
|
.setCornerRadius(mCornerRadius)
|
||||||
.setPipAnimationCallback(mPipAnimationCallback)
|
.setPipAnimationCallback(mPipAnimationCallback)
|
||||||
.setDuration(durationMs)
|
.setDuration(durationMs)
|
||||||
.start());
|
.start());
|
||||||
|
|||||||
@@ -16,9 +16,10 @@
|
|||||||
|
|
||||||
package com.android.systemui.pip;
|
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.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
@@ -64,7 +65,7 @@ public class PipAnimationControllerTest extends SysuiTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void getAnimator_withAlpha_returnFloatAnimator() {
|
public void getAnimator_withAlpha_returnFloatAnimator() {
|
||||||
final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
|
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",
|
assertEquals("Expect ANIM_TYPE_ALPHA animation",
|
||||||
animator.getAnimationType(), PipAnimationController.ANIM_TYPE_ALPHA);
|
animator.getAnimationType(), PipAnimationController.ANIM_TYPE_ALPHA);
|
||||||
@@ -73,7 +74,7 @@ public class PipAnimationControllerTest extends SysuiTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void getAnimator_withBounds_returnBoundsAnimator() {
|
public void getAnimator_withBounds_returnBoundsAnimator() {
|
||||||
final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
|
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",
|
assertEquals("Expect ANIM_TYPE_BOUNDS animation",
|
||||||
animator.getAnimationType(), PipAnimationController.ANIM_TYPE_BOUNDS);
|
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 endValue1 = new Rect(100, 100, 200, 200);
|
||||||
final Rect endValue2 = new Rect(200, 200, 300, 300);
|
final Rect endValue2 = new Rect(200, 200, 300, 300);
|
||||||
final PipAnimationController.PipTransitionAnimator oldAnimator = mPipAnimationController
|
final PipAnimationController.PipTransitionAnimator oldAnimator = mPipAnimationController
|
||||||
.getAnimator(mLeash, true /* scheduleFinishPip */, startValue, endValue1);
|
.getAnimator(mLeash, startValue, endValue1);
|
||||||
oldAnimator.setSurfaceControlTransactionFactory(DummySurfaceControlTx::new);
|
oldAnimator.setSurfaceControlTransactionFactory(DummySurfaceControlTx::new);
|
||||||
oldAnimator.start();
|
oldAnimator.start();
|
||||||
|
|
||||||
final PipAnimationController.PipTransitionAnimator newAnimator = mPipAnimationController
|
final PipAnimationController.PipTransitionAnimator newAnimator = mPipAnimationController
|
||||||
.getAnimator(mLeash, true /* scheduleFinishPip */, startValue, endValue2);
|
.getAnimator(mLeash, startValue, endValue2);
|
||||||
|
|
||||||
assertEquals("getAnimator with same type returns same animator",
|
assertEquals("getAnimator with same type returns same animator",
|
||||||
oldAnimator, newAnimator);
|
oldAnimator, newAnimator);
|
||||||
@@ -99,23 +100,28 @@ public class PipAnimationControllerTest extends SysuiTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getAnimator_scheduleFinishPip() {
|
public void getAnimator_setTransitionDirection() {
|
||||||
PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
|
PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
|
||||||
.getAnimator(mLeash, true /* scheduleFinishPip */, new Rect(), 0f, 1f);
|
.getAnimator(mLeash, new Rect(), 0f, 1f)
|
||||||
assertTrue("scheduleFinishPip is true", animator.shouldScheduleFinishPip());
|
.setTransitionDirection(TRANSITION_DIRECTION_TO_PIP);
|
||||||
|
assertEquals("Transition to PiP mode",
|
||||||
|
animator.getTransitionDirection(), TRANSITION_DIRECTION_TO_PIP);
|
||||||
|
|
||||||
animator = mPipAnimationController
|
animator = mPipAnimationController
|
||||||
.getAnimator(mLeash, false /* scheduleFinishPip */, new Rect(), 0f, 1f);
|
.getAnimator(mLeash, new Rect(), 0f, 1f)
|
||||||
assertFalse("scheduleFinishPip is false", animator.shouldScheduleFinishPip());
|
.setTransitionDirection(TRANSITION_DIRECTION_TO_FULLSCREEN);
|
||||||
|
assertEquals("Transition to fullscreen mode",
|
||||||
|
animator.getTransitionDirection(), TRANSITION_DIRECTION_TO_FULLSCREEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public void pipTransitionAnimator_updateEndValue() {
|
public void pipTransitionAnimator_updateEndValue() {
|
||||||
final Rect startValue = new Rect(0, 0, 100, 100);
|
final Rect startValue = new Rect(0, 0, 100, 100);
|
||||||
final Rect endValue1 = new Rect(100, 100, 200, 200);
|
final Rect endValue1 = new Rect(100, 100, 200, 200);
|
||||||
final Rect endValue2 = new Rect(200, 200, 300, 300);
|
final Rect endValue2 = new Rect(200, 200, 300, 300);
|
||||||
final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
|
final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
|
||||||
.getAnimator(mLeash, true /* scheduleFinishPip */, startValue, endValue1);
|
.getAnimator(mLeash, startValue, endValue1);
|
||||||
|
|
||||||
animator.updateEndValue(endValue2);
|
animator.updateEndValue(endValue2);
|
||||||
|
|
||||||
@@ -127,7 +133,7 @@ public class PipAnimationControllerTest extends SysuiTestCase {
|
|||||||
final Rect startValue = new Rect(0, 0, 100, 100);
|
final Rect startValue = new Rect(0, 0, 100, 100);
|
||||||
final Rect endValue = new Rect(100, 100, 200, 200);
|
final Rect endValue = new Rect(100, 100, 200, 200);
|
||||||
final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
|
final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
|
||||||
.getAnimator(mLeash, true /* scheduleFinishPip */, startValue, endValue);
|
.getAnimator(mLeash, startValue, endValue);
|
||||||
animator.setSurfaceControlTransactionFactory(DummySurfaceControlTx::new);
|
animator.setSurfaceControlTransactionFactory(DummySurfaceControlTx::new);
|
||||||
|
|
||||||
animator.setPipAnimationCallback(mPipAnimationCallback);
|
animator.setPipAnimationCallback(mPipAnimationCallback);
|
||||||
@@ -166,6 +172,11 @@ public class PipAnimationControllerTest extends SysuiTestCase {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SurfaceControl.Transaction setCornerRadius(SurfaceControl leash, float radius) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void apply() {}
|
public void apply() {}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user