Implement PIP Leash resizing.
This CL does a couple of things: - Break apart resizePinnedStack into animateResizeStack and resizeStackIntermediate, in which the latter is expected to only do maniuplation on the leash itself but don't send any WindowContainerTransaction until #finishResize is called. - Break apart the coupling where the duration signifies whether we only do manipulation on the leash, or send over a WCT. Now we can choose to either resize leash only, or animate correctly an entire resize with animation = 0. - Have PipResizeGestureHandler call on #finishResize and resizePipStackIntermediate during MOVE and UP events, respectively Bug: 147361175 Test: Manually. Resize PIP. Change-Id: Id3953904a7d626880855eab043abfb8d8a8d9b11
This commit is contained in:
@@ -18,7 +18,7 @@ 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_NONE;
|
||||
import static com.android.systemui.pip.PipAnimationController.DURATION_DEFAULT_MS;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
@@ -87,19 +87,7 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
||||
}
|
||||
});
|
||||
final Rect destinationBounds = animator.getDestinationBounds();
|
||||
mLastReportedBounds.set(destinationBounds);
|
||||
try {
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
if (animator.shouldScheduleFinishPip()) {
|
||||
wct.scheduleFinishEnterPip(wc, destinationBounds);
|
||||
} else {
|
||||
wct.setBounds(wc, destinationBounds);
|
||||
}
|
||||
wct.setBoundsChangeTransaction(wc, tx);
|
||||
mTaskOrganizerController.applyContainerTransaction(wct, null /* ITaskOrganizer */);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to apply container transaction", e);
|
||||
}
|
||||
finishResizeInternal(destinationBounds, wc, tx, animator.shouldScheduleFinishPip());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -124,15 +112,6 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
||||
mPipAnimationController = new PipAnimationController(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize the PiP window, animate if the given duration is not {@link #DURATION_NONE}
|
||||
*/
|
||||
public void resizePinnedStack(Rect destinationBounds, int durationMs) {
|
||||
Objects.requireNonNull(mTaskInfo, "Requires valid IWindowContainer");
|
||||
resizePinnedStackInternal(mTaskInfo.token, false /* scheduleFinishPip */,
|
||||
mLastReportedBounds, destinationBounds, durationMs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Offset the PiP window, animate if the given duration is not {@link #DURATION_NONE}
|
||||
*/
|
||||
@@ -143,7 +122,7 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
||||
}
|
||||
final Rect destinationBounds = new Rect(originalBounds);
|
||||
destinationBounds.offset(xOffset, yOffset);
|
||||
resizePinnedStackInternal(mTaskInfo.token, false /* scheduleFinishPip*/,
|
||||
animateResizePipInternal(mTaskInfo.token, false /* scheduleFinishPip*/,
|
||||
originalBounds, destinationBounds, durationMs);
|
||||
}
|
||||
|
||||
@@ -208,15 +187,14 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
||||
mTaskInfo = info;
|
||||
if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
|
||||
final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds();
|
||||
resizePinnedStackInternal(mTaskInfo.token, true /* scheduleFinishPip */,
|
||||
currentBounds, destinationBounds,
|
||||
PipAnimationController.DURATION_DEFAULT_MS);
|
||||
animateResizePipInternal(mTaskInfo.token, true /* scheduleFinishPip */,
|
||||
currentBounds, destinationBounds, DURATION_DEFAULT_MS);
|
||||
} else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
|
||||
mMainHandler.post(() -> mPipAnimationController
|
||||
.getAnimator(mTaskInfo.token, true /* scheduleFinishPip */,
|
||||
destinationBounds, 0f, 1f)
|
||||
.setPipAnimationCallback(mPipAnimationCallback)
|
||||
.setDuration(PipAnimationController.DURATION_DEFAULT_MS)
|
||||
.setDuration(DURATION_DEFAULT_MS)
|
||||
.start());
|
||||
mOneShotAnimationType = ANIM_TYPE_BOUNDS;
|
||||
} else {
|
||||
@@ -231,9 +209,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
||||
Log.wtf(TAG, "Unrecognized token: " + token);
|
||||
return;
|
||||
}
|
||||
resizePinnedStackInternal(token, false /* scheduleFinishPip */,
|
||||
mLastReportedBounds, mDisplayBounds,
|
||||
PipAnimationController.DURATION_DEFAULT_MS);
|
||||
animateResizePipInternal(token, false /* scheduleFinishPip */,
|
||||
mLastReportedBounds, mDisplayBounds, DURATION_DEFAULT_MS);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -245,11 +222,22 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
||||
final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
|
||||
getAspectRatioOrDefault(info.pictureInPictureParams), null /* bounds */);
|
||||
Objects.requireNonNull(destinationBounds, "Missing destination bounds");
|
||||
resizePinnedStack(destinationBounds, PipAnimationController.DURATION_DEFAULT_MS);
|
||||
animateResizePip(destinationBounds, DURATION_DEFAULT_MS);
|
||||
}
|
||||
|
||||
private void resizePinnedStackInternal(IWindowContainer wc, boolean scheduleFinishPip,
|
||||
Rect currentBounds, Rect destinationBounds, int animationDurationMs) {
|
||||
|
||||
/**
|
||||
* Directly perform manipulation/resize on the leash. This will not perform any
|
||||
* {@link WindowContainerTransaction} until {@link #finishResize} is called.
|
||||
*/
|
||||
public void resizePip(Rect destinationBounds) {
|
||||
Objects.requireNonNull(mTaskInfo, "Requires valid IWindowContainer");
|
||||
resizePipInternal(mTaskInfo.token, destinationBounds);
|
||||
}
|
||||
|
||||
private void resizePipInternal(IWindowContainer wc,
|
||||
Rect destinationBounds) {
|
||||
Objects.requireNonNull(mTaskInfo, "Requires valid IWindowContainer");
|
||||
try {
|
||||
// Could happen when dismissPip
|
||||
if (wc == null || wc.getLeash() == null) {
|
||||
@@ -257,20 +245,10 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
||||
return;
|
||||
}
|
||||
final SurfaceControl leash = wc.getLeash();
|
||||
if (animationDurationMs == DURATION_NONE) {
|
||||
// Directly resize if no animation duration is set. When fling, wait for final
|
||||
// callback to issue the proper WindowContainerTransaction with destination bounds.
|
||||
new SurfaceControl.Transaction()
|
||||
.setPosition(leash, destinationBounds.left, destinationBounds.top)
|
||||
.setWindowCrop(leash, destinationBounds.width(), destinationBounds.height())
|
||||
.apply();
|
||||
} else {
|
||||
mMainHandler.post(() -> mPipAnimationController
|
||||
.getAnimator(wc, scheduleFinishPip, currentBounds, destinationBounds)
|
||||
.setPipAnimationCallback(mPipAnimationCallback)
|
||||
.setDuration(animationDurationMs)
|
||||
.start());
|
||||
}
|
||||
new SurfaceControl.Transaction()
|
||||
.setPosition(leash, destinationBounds.left, destinationBounds.top)
|
||||
.setWindowCrop(leash, destinationBounds.width(), destinationBounds.height())
|
||||
.apply();
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Abort animation, invalid window container", e);
|
||||
} catch (Exception e) {
|
||||
@@ -278,6 +256,73 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish a intermediate resize operation. This is expected to be called after
|
||||
* {@link #resizePip}.
|
||||
*/
|
||||
public void finishResize(Rect destinationBounds) {
|
||||
try {
|
||||
final IWindowContainer wc = mTaskInfo.token;
|
||||
SurfaceControl.Transaction tx = new SurfaceControl.Transaction()
|
||||
.setPosition(wc.getLeash(), destinationBounds.left,
|
||||
destinationBounds.top)
|
||||
.setWindowCrop(wc.getLeash(), destinationBounds.width(),
|
||||
destinationBounds.height());
|
||||
finishResizeInternal(destinationBounds, wc, tx, false);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to obtain leash");
|
||||
}
|
||||
}
|
||||
|
||||
private void finishResizeInternal(Rect destinationBounds, IWindowContainer wc,
|
||||
SurfaceControl.Transaction tx, boolean shouldScheduleFinishPip) {
|
||||
mLastReportedBounds.set(destinationBounds);
|
||||
try {
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
if (shouldScheduleFinishPip) {
|
||||
wct.scheduleFinishEnterPip(wc, destinationBounds);
|
||||
} else {
|
||||
wct.setBounds(wc, destinationBounds);
|
||||
}
|
||||
wct.setBoundsChangeTransaction(mTaskInfo.token, tx);
|
||||
mTaskOrganizerController.applyContainerTransaction(wct, null /* ITaskOrganizer */);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to apply container transaction", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Animates resizing of the pinned stack given the duration.
|
||||
*/
|
||||
public void animateResizePip(Rect destinationBounds, int durationMs) {
|
||||
Objects.requireNonNull(mTaskInfo, "Requires valid IWindowContainer");
|
||||
animateResizePipInternal(mTaskInfo.token, false, mLastReportedBounds,
|
||||
destinationBounds, durationMs);
|
||||
}
|
||||
|
||||
private void animateResizePipInternal(IWindowContainer wc, boolean scheduleFinishPip,
|
||||
Rect currentBounds, Rect destinationBounds, int durationMs) {
|
||||
try {
|
||||
// Could happen when dismissPip
|
||||
if (wc == null || wc.getLeash() == null) {
|
||||
Log.w(TAG, "Abort animation, invalid leash");
|
||||
return;
|
||||
}
|
||||
final SurfaceControl leash = wc.getLeash();
|
||||
|
||||
mMainHandler.post(() -> mPipAnimationController
|
||||
.getAnimator(wc, scheduleFinishPip, currentBounds, destinationBounds)
|
||||
.setPipAnimationCallback(mPipAnimationCallback)
|
||||
.setDuration(durationMs)
|
||||
.start());
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Abort animation, invalid window container", e);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Should not reach here, terrible thing happened", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private float getAspectRatioOrDefault(@Nullable PictureInPictureParams params) {
|
||||
return params == null
|
||||
? mPipBoundsHandler.getDefaultAspectRatio()
|
||||
|
||||
@@ -38,7 +38,6 @@ import androidx.dynamicanimation.animation.SpringForce;
|
||||
|
||||
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
|
||||
import com.android.internal.os.SomeArgs;
|
||||
import com.android.systemui.pip.PipAnimationController;
|
||||
import com.android.systemui.pip.PipSnapAlgorithm;
|
||||
import com.android.systemui.pip.PipTaskOrganizer;
|
||||
import com.android.systemui.shared.system.WindowManagerWrapper;
|
||||
@@ -546,7 +545,7 @@ public class PipMotionHelper implements Handler.Callback, PipAppOpsListener.Call
|
||||
case MSG_RESIZE_IMMEDIATE: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
Rect toBounds = (Rect) args.arg1;
|
||||
mPipTaskOrganizer.resizePinnedStack(toBounds, PipAnimationController.DURATION_NONE);
|
||||
mPipTaskOrganizer.resizePip(toBounds);
|
||||
mBounds.set(toBounds);
|
||||
return true;
|
||||
}
|
||||
@@ -564,7 +563,7 @@ public class PipMotionHelper implements Handler.Callback, PipAppOpsListener.Call
|
||||
return true;
|
||||
}
|
||||
|
||||
mPipTaskOrganizer.resizePinnedStack(toBounds, duration);
|
||||
mPipTaskOrganizer.animateResizePip(toBounds, duration);
|
||||
mBounds.set(toBounds);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Could not animate resize pinned stack to bounds: " + toBounds, e);
|
||||
|
||||
@@ -41,6 +41,7 @@ import android.view.MotionEvent;
|
||||
import com.android.internal.policy.TaskResizingAlgorithm;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.pip.PipBoundsHandler;
|
||||
import com.android.systemui.pip.PipTaskOrganizer;
|
||||
import com.android.systemui.util.DeviceConfigProxy;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
@@ -75,12 +76,13 @@ public class PipResizeGestureHandler {
|
||||
|
||||
private InputMonitor mInputMonitor;
|
||||
private InputEventReceiver mInputEventReceiver;
|
||||
private PipTaskOrganizer mPipTaskOrganizer;
|
||||
|
||||
private int mCtrlType;
|
||||
|
||||
public PipResizeGestureHandler(Context context, PipBoundsHandler pipBoundsHandler,
|
||||
PipTouchHandler pipTouchHandler, PipMotionHelper motionHelper,
|
||||
DeviceConfigProxy deviceConfig) {
|
||||
DeviceConfigProxy deviceConfig, PipTaskOrganizer pipTaskOrganizer) {
|
||||
final Resources res = context.getResources();
|
||||
context.getDisplay().getMetrics(mDisplayMetrics);
|
||||
mDisplayId = context.getDisplayId();
|
||||
@@ -88,6 +90,7 @@ public class PipResizeGestureHandler {
|
||||
mPipBoundsHandler = pipBoundsHandler;
|
||||
mPipTouchHandler = pipTouchHandler;
|
||||
mMotionHelper = motionHelper;
|
||||
mPipTaskOrganizer = pipTaskOrganizer;
|
||||
|
||||
context.getDisplay().getRealSize(mMaxSize);
|
||||
mDelta = res.getDimensionPixelSize(R.dimen.pip_resize_edge_size);
|
||||
@@ -205,12 +208,13 @@ public class PipResizeGestureHandler {
|
||||
mDownPoint.x, mDownPoint.y, currentPipBounds, mCtrlType, mMinSize.x,
|
||||
mMinSize.y, mMaxSize, true, true));
|
||||
mPipBoundsHandler.transformBoundsToAspectRatio(mLastResizeBounds);
|
||||
//TODO: Actually do resize here.
|
||||
mPipTaskOrganizer.resizePip(mLastResizeBounds);
|
||||
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
mPipTaskOrganizer.finishResize(mLastResizeBounds);
|
||||
mLastResizeBounds.setEmpty();
|
||||
//TODO: Finish resize operation here.
|
||||
mCtrlType = CTRL_NONE;
|
||||
mAllowGesture = false;
|
||||
break;
|
||||
|
||||
@@ -191,7 +191,7 @@ public class PipTouchHandler {
|
||||
mMenuController, mSnapAlgorithm, mFlingAnimationUtils, floatingContentCoordinator);
|
||||
mPipResizeGestureHandler =
|
||||
new PipResizeGestureHandler(context, pipBoundsHandler, this, mMotionHelper,
|
||||
deviceConfig);
|
||||
deviceConfig, pipTaskOrganizer);
|
||||
mTouchState = new PipTouchState(ViewConfiguration.get(context), mHandler,
|
||||
() -> mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
|
||||
mMovementBounds, true /* allowMenuTimeout */, willResizeMenu()));
|
||||
|
||||
@@ -433,8 +433,8 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
|
||||
mCurrentPipBounds = mPipBounds;
|
||||
break;
|
||||
}
|
||||
mPipTaskOrganizer.resizePinnedStack(
|
||||
mCurrentPipBounds, PipAnimationController.DURATION_DEFAULT_MS);
|
||||
mPipTaskOrganizer.animateResizePip(mCurrentPipBounds,
|
||||
PipAnimationController.DURATION_DEFAULT_MS);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user