diff options
| author | 2021-09-28 09:48:18 +0000 | |
|---|---|---|
| committer | 2021-09-28 09:48:18 +0000 | |
| commit | 3dce047981dfd35b1d3301c1f79f90685208d239 (patch) | |
| tree | 5f4c115776037d81d5543a7d34f38bad67c67ea2 | |
| parent | 4f7274abe3334c7adb9b1d9711d193153891b689 (diff) | |
| parent | 17558b56807b7e3dbbfb1a42db04456e7a1219ba (diff) | |
Merge "Offset animation leash to the relative position" into sc-v2-dev
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), |