Settle auto PiP transaction in WindowContainerTransaction
At the end of autoEnterPip transition, followings happen in sequence
- Transition finishes in Launcher side, which operates on the
animation leash
- RecentsAnimationController.TaskAnimationAdapter#onCleanup has the final
chance to set the Task leash
- PipTaskOrganizer gets onTaskAppeared callback and commits Task into
pinned mode
What's been changed here
- Transition in Launcher no longer in charge of settle the final transaction
- RecentsAnimationController.TaskAnimationAdapter#onCleanup sets the
Task leash to be in sync with the final state in Launcher side
- PipTaskOrganizer commits the final leash transaction together with
WindowContainerTransaction that enters PiP
Known issue: transition from landscape is not polished
Video: http://rcll/aaaaaabFQoRHlzixHdtY/hT5SXvaCy28P4UtfuoKiDw
Bug: 181342797
Test: see video
Change-Id: Ieabd6991ea5174099714ec22970198bebde1e336
diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl
index ddb49786..10721ad 100644
--- a/core/java/android/view/IRecentsAnimationController.aidl
+++ b/core/java/android/view/IRecentsAnimationController.aidl
@@ -43,8 +43,11 @@
* accordingly. This should be called before `finish`
* @param taskId for which the leash should be updated
* @param destinationBounds bounds of the final PiP window
+ * @param windowCrop bounds to crop as part of final transform.
+ * @param float9 An array of 9 floats to be used as matrix transform.
*/
- void setFinishTaskBounds(int taskId, in Rect destinationBounds);
+ void setFinishTaskBounds(int taskId, in Rect destinationBounds, in Rect windowCrop,
+ in float[] float9);
/**
* Notifies to the system that the animation into Recents should end, and all leashes associated
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 9ec7c0d..36dc4e4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -41,6 +41,7 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.PictureInPictureParams;
@@ -423,12 +424,16 @@
if (mInSwipePipToHomeTransition) {
final Rect destinationBounds = mPipBoundsState.getBounds();
+ final SurfaceControl.Transaction tx =
+ mSurfaceControlTransactionFactory.getTransaction();
+ mSurfaceTransactionHelper.resetScale(tx, mLeash, destinationBounds);
+ mSurfaceTransactionHelper.crop(tx, mLeash, destinationBounds);
// animation is finished in the Launcher and here we directly apply the final touch.
applyEnterPipSyncTransaction(destinationBounds, () -> {
// ensure menu's settled in its final bounds first
finishResizeForMenu(destinationBounds);
sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
- });
+ }, tx);
mInSwipePipToHomeTransition = false;
return;
}
@@ -490,16 +495,20 @@
// mState is set right after the animation is kicked off to block any resize
// requests such as offsetPip that may have been called prior to the transition.
mState = State.ENTERING_PIP;
- });
+ }, null /* boundsChangeTransaction */);
}
- private void applyEnterPipSyncTransaction(Rect destinationBounds, Runnable runnable) {
+ private void applyEnterPipSyncTransaction(Rect destinationBounds, Runnable runnable,
+ @Nullable SurfaceControl.Transaction boundsChangeTransaction) {
// PiP menu is attached late in the process here to avoid any artifacts on the leash
// caused by addShellRoot when in gesture navigation mode.
mPipMenuController.attach(mLeash);
final WindowContainerTransaction wct = new WindowContainerTransaction();
wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
wct.setBounds(mToken, destinationBounds);
+ if (boundsChangeTransaction != null) {
+ wct.setBoundsChangeTransaction(mToken, boundsChangeTransaction);
+ }
wct.scheduleFinishEnterPip(mToken, destinationBounds);
mSyncTransactionQueue.queue(wct);
if (runnable != null) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java
index 72e4061..f50c3c92 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java
@@ -20,7 +20,6 @@
import android.graphics.Rect;
import android.graphics.RectF;
import android.view.Choreographer;
-import android.view.Surface;
import android.view.SurfaceControl;
/**
@@ -91,24 +90,6 @@
.setPosition(leash, positionX, positionY);
}
- public void reset(SurfaceControl.Transaction tx, SurfaceControl leash, Rect destinationBounds,
- @Surface.Rotation int rotation) {
- resetScale(tx, leash, destinationBounds);
- if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {
- final int degree = (rotation == Surface.ROTATION_90) ? -90 : 90;
- mTmpTransform.setRotate(degree, 0, 0);
- tx.setMatrix(leash, mTmpTransform, mTmpFloat9);
- }
- resetCornerRadius(tx, leash);
- crop(tx, leash, destinationBounds);
- }
-
- public void resetScale(SurfaceControl.Transaction tx, SurfaceControl leash,
- Rect destinationBounds) {
- tx.setMatrix(leash, Matrix.IDENTITY_MATRIX, mTmpFloat9)
- .setPosition(leash, destinationBounds.left, destinationBounds.top);
- }
-
public void resetCornerRadius(SurfaceControl.Transaction tx, SurfaceControl leash) {
tx.setCornerRadius(leash, 0);
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
index c2d52a7..bf0d29a 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
@@ -76,10 +76,14 @@
* accordingly. This should be called before `finish`
* @param taskId Task id of the Activity in PiP mode.
* @param destinationBounds Bounds of the PiP window on home.
+ * @param windowCrop bounds to crop as part of final transform.
+ * @param float9 An array of 9 floats to be used as matrix transform.
*/
- public void setFinishTaskBounds(int taskId, Rect destinationBounds) {
+ public void setFinishTaskBounds(int taskId, Rect destinationBounds, Rect windowCrop,
+ float[] float9) {
try {
- mAnimationController.setFinishTaskBounds(taskId, destinationBounds);
+ mAnimationController.setFinishTaskBounds(taskId, destinationBounds, windowCrop,
+ float9);
} catch (RemoteException e) {
Log.d(TAG, "Failed to set finish task bounds", e);
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
index 7ba9069..06155bc 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
@@ -137,8 +137,11 @@
mWrapped.hideCurrentInputMethod();
}
- @Override public void setFinishTaskBounds(int taskId, Rect destinationBounds) {
- if (mWrapped != null) mWrapped.setFinishTaskBounds(taskId, destinationBounds);
+ @Override public void setFinishTaskBounds(int taskId, Rect destinationBounds,
+ Rect windowCrop, float[] float9) {
+ if (mWrapped != null) {
+ mWrapped.setFinishTaskBounds(taskId, destinationBounds, windowCrop, float9);
+ }
}
@Override public void finish(boolean toHome, boolean sendUserLeaveHint) {
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 914e456..64ff108 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -20,6 +20,10 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.graphics.Matrix.MSCALE_X;
+import static android.graphics.Matrix.MSCALE_Y;
+import static android.graphics.Matrix.MSKEW_X;
+import static android.graphics.Matrix.MSKEW_Y;
import static android.view.RemoteAnimationTarget.MODE_CLOSING;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
@@ -229,7 +233,8 @@
}
@Override
- public void setFinishTaskBounds(int taskId, Rect destinationBounds) {
+ public void setFinishTaskBounds(int taskId, Rect destinationBounds, Rect windowCrop,
+ float[] float9) {
ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
"setFinishTaskBounds(%d): bounds=%s", taskId, destinationBounds);
final long token = Binder.clearCallingIdentity();
@@ -239,6 +244,8 @@
final TaskAnimationAdapter taskAdapter = mPendingAnimations.get(i);
if (taskAdapter.mTask.mTaskId == taskId) {
taskAdapter.mFinishBounds.set(destinationBounds);
+ taskAdapter.mFinishWindowCrop.set(windowCrop);
+ taskAdapter.mFinishTransform = float9;
break;
}
}
@@ -1084,6 +1091,9 @@
private final Rect mLocalBounds = new Rect();
// The bounds of the target when animation is finished
private final Rect mFinishBounds = new Rect();
+ // Bounds and transform for the final transaction.
+ private final Rect mFinishWindowCrop = new Rect();
+ private float[] mFinishTransform;
TaskAnimationAdapter(Task task, boolean isRecentTaskInvisible) {
mTask = task;
@@ -1120,13 +1130,31 @@
void onCleanup() {
if (!mFinishBounds.isEmpty()) {
- // Apply any pending bounds changes
- final SurfaceControl taskSurface = mTask.getSurfaceControl();
- mTask.getPendingTransaction()
- .setPosition(taskSurface, mFinishBounds.left, mFinishBounds.top)
- .setWindowCrop(taskSurface, mFinishBounds.width(), mFinishBounds.height())
+ final SurfaceControl taskSurface = mTask.mSurfaceControl;
+ final Transaction pendingTransaction = mTask.getPendingTransaction();
+ if (mFinishTransform != null) {
+ pendingTransaction
+ .setMatrix(taskSurface,
+ mFinishTransform[MSCALE_X], mFinishTransform[MSKEW_Y],
+ mFinishTransform[MSKEW_X], mFinishTransform[MSCALE_Y]);
+ }
+ float left = mFinishBounds.left;
+ float top = mFinishBounds.top;
+ if (!mFinishWindowCrop.isEmpty()) {
+ pendingTransaction.setWindowCrop(taskSurface, mFinishWindowCrop);
+ if (mFinishTransform != null) {
+ // adjust the position for insets.
+ left -= mFinishWindowCrop.left * mFinishTransform[MSCALE_X];
+ top -= mFinishWindowCrop.top * mFinishTransform[MSCALE_Y];
+ }
+ }
+ pendingTransaction
+ .setPosition(taskSurface, left, top)
.apply();
mTask.mLastRecentsAnimationBounds.set(mFinishBounds);
+ // reset the variables
+ mFinishTransform = null;
+ mFinishWindowCrop.setEmpty();
mFinishBounds.setEmpty();
} else if (!mTask.isAttached()) {
// Apply the task's pending transaction in case it is detached and its transaction