summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Chris Li <lihongyu@google.com> 2021-09-28 09:48:18 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2021-09-28 09:48:18 +0000
commit3dce047981dfd35b1d3301c1f79f90685208d239 (patch)
tree5f4c115776037d81d5543a7d34f38bad67c67ea2
parent4f7274abe3334c7adb9b1d9711d193153891b689 (diff)
parent17558b56807b7e3dbbfb1a42db04456e7a1219ba (diff)
Merge "Offset animation leash to the relative position" into sc-v2-dev
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java4
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java6
-rw-r--r--services/core/java/com/android/server/wm/RemoteAnimationController.java43
-rw-r--r--services/core/java/com/android/server/wm/SurfaceFreezer.java6
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java13
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java61
6 files changed, 105 insertions, 28 deletions
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java
index 1e64782b161f..11a79b2f4a27 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java
@@ -121,9 +121,11 @@ class TaskFragmentAnimationSpec {
* the second one is for the end leash.
*/
Animation[] createChangeBoundsChangeAnimations(@NonNull RemoteAnimationTarget target) {
+ // Both start bounds and end bounds are in screen coordinates. We will post translate
+ // to the local coordinates in TaskFragmentAnimationAdapter#onAnimationUpdate
final Rect startBounds = target.startBounds;
final Rect parentBounds = target.taskInfo.configuration.windowConfiguration.getBounds();
- final Rect endBounds = target.localBounds;
+ final Rect endBounds = target.screenSpaceBounds;
float scaleX = ((float) startBounds.width()) / endBounds.width();
float scaleY = ((float) startBounds.height()) / endBounds.height();
// Start leash is a child of the end leash. Reverse the scale so that the start leash won't
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 19a968628248..195da18a88be 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1411,7 +1411,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
this.task = newTask;
if (shouldStartChangeTransition(newParent, oldParent)) {
- initializeChangeTransition(getBounds());
+ // The new parent and old parent may be in different position. Need to offset the
+ // animation surface to keep it in its original position.
+ initializeChangeTransition(getBounds(), newParent.getBounds());
}
super.onParentChanged(newParent, oldParent);
@@ -9276,7 +9278,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
record.getMode(), record.mAdapter.mCapturedLeash, !fillsParent(),
new Rect(), insets,
getPrefixOrderIndex(), record.mAdapter.mPosition, record.mAdapter.mLocalBounds,
- record.mAdapter.mRootTaskBounds, task.getWindowConfiguration(),
+ record.mAdapter.mEndBounds, task.getWindowConfiguration(),
false /*isNotInRecents*/,
record.mThumbnailAdapter != null ? record.mThumbnailAdapter.mCapturedLeash : null,
record.mStartBounds, task.getTaskInfo(), checkEnterPictureInPictureAppOpsState());
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index b90f937ca56e..16a45fe7cec7 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -65,7 +65,6 @@ class RemoteAnimationController implements DeathRecipient {
new ArrayList<>();
@VisibleForTesting
final ArrayList<NonAppWindowAnimationAdapter> mPendingNonAppAnimations = new ArrayList<>();
- private final Rect mTmpRect = new Rect();
private final Handler mHandler;
private final Runnable mTimeoutRunnable = () -> cancelAnimation("timeoutRunnable");
@@ -85,18 +84,18 @@ class RemoteAnimationController implements DeathRecipient {
* Creates an animation record for each individual {@link WindowContainer}.
*
* @param windowContainer The windows to animate.
- * @param position The position app bounds, in screen coordinates.
+ * @param position The position app bounds relative to its parent.
* @param localBounds The bounds of the app relative to its parent.
- * @param stackBounds The stack bounds of the app relative to position.
- * @param startBounds The stack bounds before the transition, in screen coordinates
+ * @param endBounds The end bounds after the transition, in screen coordinates.
+ * @param startBounds The start bounds before the transition, in screen coordinates.
* @return The record representing animation(s) to run on the app.
*/
RemoteAnimationRecord createRemoteAnimationRecord(WindowContainer windowContainer,
- Point position, Rect localBounds, Rect stackBounds, Rect startBounds) {
+ Point position, Rect localBounds, Rect endBounds, Rect startBounds) {
ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "createAnimationAdapter(): container=%s",
windowContainer);
final RemoteAnimationRecord adapters = new RemoteAnimationRecord(windowContainer, position,
- localBounds, stackBounds, startBounds);
+ localBounds, endBounds, startBounds);
mPendingAnimations.add(adapters);
return adapters;
}
@@ -405,16 +404,17 @@ class RemoteAnimationController implements DeathRecipient {
mStartBounds = new Rect(startBounds);
mAdapter = new RemoteAnimationAdapterWrapper(this, endPos, localBounds, endBounds,
mStartBounds);
- mTmpRect.set(startBounds);
- mTmpRect.offsetTo(0, 0);
if (mRemoteAnimationAdapter.getChangeNeedsSnapshot()) {
- mThumbnailAdapter =
- new RemoteAnimationAdapterWrapper(this, new Point(0, 0), localBounds,
- mTmpRect, new Rect());
+ final Rect thumbnailLocalBounds = new Rect(startBounds);
+ thumbnailLocalBounds.offsetTo(0, 0);
+ // Snapshot is located at (0,0) of the animation leash. It doesn't have size
+ // change, so the startBounds is its end bounds, and no start bounds for it.
+ mThumbnailAdapter = new RemoteAnimationAdapterWrapper(this, new Point(0, 0),
+ thumbnailLocalBounds, startBounds, new Rect());
}
} else {
mAdapter = new RemoteAnimationAdapterWrapper(this, endPos, localBounds, endBounds,
- new Rect(endPos.x, endPos.y, endBounds.right, endBounds.bottom));
+ new Rect());
mStartBounds = null;
}
}
@@ -458,15 +458,15 @@ class RemoteAnimationController implements DeathRecipient {
private @AnimationType int mAnimationType;
final Point mPosition = new Point();
final Rect mLocalBounds;
- final Rect mRootTaskBounds = new Rect();
+ final Rect mEndBounds = new Rect();
final Rect mStartBounds = new Rect();
RemoteAnimationAdapterWrapper(RemoteAnimationRecord record, Point position,
- Rect localBounds, Rect rootTaskBounds, Rect startBounds) {
+ Rect localBounds, Rect endBounds, Rect startBounds) {
mRecord = record;
mPosition.set(position.x, position.y);
mLocalBounds = localBounds;
- mRootTaskBounds.set(rootTaskBounds);
+ mEndBounds.set(endBounds);
mStartBounds.set(startBounds);
}
@@ -480,12 +480,17 @@ class RemoteAnimationController implements DeathRecipient {
@AnimationType int type, OnAnimationFinishedCallback finishCallback) {
ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "startAnimation");
- // Restore position and stack crop until client has a chance to modify it.
if (mStartBounds.isEmpty()) {
- t.setPosition(animationLeash, 0, 0);
- t.setWindowCrop(animationLeash, -1, -1);
+ // Restore position and stack crop until client has a chance to modify it.
+ t.setPosition(animationLeash, mPosition.x, mPosition.y);
+ t.setWindowCrop(animationLeash, mEndBounds.width(), mEndBounds.height());
} else {
- t.setPosition(animationLeash, mStartBounds.left, mStartBounds.top);
+ // Offset the change animation leash to the relative start position in parent.
+ // (mPosition) is the relative end position in parent container.
+ // (mStartBounds - mEndBounds) is the position difference between start and end.
+ // (mPosition + mStartBounds - mEndBounds) will be the relative start position.
+ t.setPosition(animationLeash, mPosition.x + mStartBounds.left - mEndBounds.left,
+ mPosition.y + mStartBounds.top - mEndBounds.top);
t.setWindowCrop(animationLeash, mStartBounds.width(), mStartBounds.height());
}
mCapturedLeash = animationLeash;
diff --git a/services/core/java/com/android/server/wm/SurfaceFreezer.java b/services/core/java/com/android/server/wm/SurfaceFreezer.java
index 0f562d77b988..9c4f6f574487 100644
--- a/services/core/java/com/android/server/wm/SurfaceFreezer.java
+++ b/services/core/java/com/android/server/wm/SurfaceFreezer.java
@@ -24,6 +24,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.GraphicBuffer;
import android.graphics.PixelFormat;
+import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.HardwareBuffer;
import android.view.Surface;
@@ -70,13 +71,14 @@ class SurfaceFreezer {
* above the target surface) and then taking a snapshot and placing it over the target surface.
*
* @param startBounds The original bounds (on screen) of the surface we are snapshotting.
+ * @param relativePosition The related position of the snapshot surface to its parent.
*/
- void freeze(SurfaceControl.Transaction t, Rect startBounds) {
+ void freeze(SurfaceControl.Transaction t, Rect startBounds, Point relativePosition) {
mFreezeBounds.set(startBounds);
mLeash = SurfaceAnimator.createAnimationLeash(mAnimatable, mAnimatable.getSurfaceControl(),
t, ANIMATION_TYPE_SCREEN_ROTATION, startBounds.width(), startBounds.height(),
- startBounds.left, startBounds.top, false /* hidden */,
+ relativePosition.x, relativePosition.y, false /* hidden */,
mWmService.mTransactionFactory);
mAnimatable.onAnimationLeashCreated(t, mLeash);
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index d51c5c778c15..2a8fa1086799 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -2623,11 +2623,20 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
* 3. {@link ActivityRecord} is reparented into an organized {@link TaskFragment}.
*
* This shouldn't be called on other {@link WindowContainer} unless there is a valid use case.
+ *
+ * @param startBounds The original bounds (on screen) of the surface we are snapshotting.
+ * @param parentBounds The parent bounds (on screen) to calculate the animation surface
+ * position.
*/
- void initializeChangeTransition(Rect startBounds) {
+ void initializeChangeTransition(Rect startBounds, Rect parentBounds) {
mDisplayContent.prepareAppTransition(TRANSIT_CHANGE);
mDisplayContent.mChangingContainers.add(this);
- mSurfaceFreezer.freeze(getSyncTransaction(), startBounds);
+ mTmpPoint.set(startBounds.left - parentBounds.left, startBounds.top - parentBounds.top);
+ mSurfaceFreezer.freeze(getSyncTransaction(), startBounds, mTmpPoint);
+ }
+
+ void initializeChangeTransition(Rect startBounds) {
+ initializeChangeTransition(startBounds, getParent().getBounds());
}
ArraySet<WindowContainer> getAnimationSources() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
index 89ae5ed9b425..08312ef0b865 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -341,7 +341,8 @@ public class RemoteAnimationControllerTest extends WindowTestsBase {
verify(mMockTransaction).setWindowCrop(
mMockLeash, app.startBounds.width(), app.startBounds.height());
verify(mMockTransaction).setPosition(mMockThumbnailLeash, 0, 0);
- verify(mMockTransaction).setWindowCrop(mMockThumbnailLeash, -1, -1);
+ verify(mMockTransaction).setWindowCrop(mMockThumbnailLeash, app.startBounds.width(),
+ app.startBounds.height());
finishedCaptor.getValue().onAnimationFinished();
verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_WINDOW_ANIMATION),
@@ -394,7 +395,63 @@ public class RemoteAnimationControllerTest extends WindowTestsBase {
verify(mMockTransaction).setWindowCrop(
mMockLeash, app.startBounds.width(), app.startBounds.height());
verify(mMockTransaction).setPosition(mMockThumbnailLeash, 0, 0);
- verify(mMockTransaction).setWindowCrop(mMockThumbnailLeash, -1, -1);
+ verify(mMockTransaction).setWindowCrop(mMockThumbnailLeash, app.startBounds.width(),
+ app.startBounds.height());
+
+ finishedCaptor.getValue().onAnimationFinished();
+ verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_WINDOW_ANIMATION),
+ eq(record.mAdapter));
+ verify(mThumbnailFinishedCallback).onAnimationFinished(
+ eq(ANIMATION_TYPE_WINDOW_ANIMATION), eq(record.mThumbnailAdapter));
+ } finally {
+ mDisplayContent.mChangingContainers.clear();
+ }
+ }
+
+ @Test
+ public void testChangeToDifferentPosition() throws Exception {
+ final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
+ mDisplayContent.mChangingContainers.add(win.mActivityRecord);
+ try {
+ final RemoteAnimationRecord record = mController.createRemoteAnimationRecord(
+ win.mActivityRecord, new Point(100, 100), null, new Rect(150, 150, 400, 400),
+ new Rect(50, 100, 150, 150));
+ assertNotNull(record.mThumbnailAdapter);
+ ((AnimationAdapter) record.mAdapter)
+ .startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION,
+ mFinishedCallback);
+ ((AnimationAdapter) record.mThumbnailAdapter).startAnimation(mMockThumbnailLeash,
+ mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION, mThumbnailFinishedCallback);
+ mController.goodToGo(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE);
+ mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
+ ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
+ final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
+ ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
+ final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
+ ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
+ final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
+ ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
+ verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE),
+ appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(),
+ finishedCaptor.capture());
+ assertEquals(1, appsCaptor.getValue().length);
+ final RemoteAnimationTarget app = appsCaptor.getValue()[0];
+ assertEquals(RemoteAnimationTarget.MODE_CHANGING, app.mode);
+ assertEquals(new Point(100, 100), app.position);
+ assertEquals(new Rect(150, 150, 400, 400), app.sourceContainerBounds);
+ assertEquals(new Rect(50, 100, 150, 150), app.startBounds);
+ assertEquals(mMockLeash, app.leash);
+ assertEquals(mMockThumbnailLeash, app.startLeash);
+ assertEquals(false, app.isTranslucent);
+ verify(mMockTransaction).setPosition(
+ mMockLeash, app.position.x + app.startBounds.left - app.screenSpaceBounds.left,
+ app.position.y + app.startBounds.top - app.screenSpaceBounds.top);
+ verify(mMockTransaction).setWindowCrop(
+ mMockLeash, app.startBounds.width(), app.startBounds.height());
+ verify(mMockTransaction).setPosition(mMockThumbnailLeash, 0, 0);
+ verify(mMockTransaction).setWindowCrop(mMockThumbnailLeash, app.startBounds.width(),
+ app.startBounds.height());
finishedCaptor.getValue().onAnimationFinished();
verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_WINDOW_ANIMATION),