diff options
| author | 2021-09-29 18:32:24 +0800 | |
|---|---|---|
| committer | 2021-10-01 08:30:13 +0800 | |
| commit | ae9155a47bdb9f1cb58466decc8749b092dc1ea9 (patch) | |
| tree | 001d0e9e59dbe93a7a493d2f58cf2b6587d3b683 | |
| parent | d8dac94e0d2c7bec9408d22f531f09ed5e12c76d (diff) | |
Change the activity reparent to animate at TaskFragment level.
Before, we are animating at activity level, but that wouldn't work after
we set the TaskFragment window crop. Now, we animate the change
transition on the TaskFragment level instead.
Bug: 196173550
Test: atest WmTests:AppTransitionTests
#testActivityRecordReparentToTaskFragment
Change-Id: Ie777dc8bf438300f59f8a2565cd999c6a29561d8
5 files changed, 30 insertions, 16 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index db44dd8f70d1..c1fcf71b38d2 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -1411,9 +1411,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A this.task = newTask; if (shouldStartChangeTransition(newParent, oldParent)) { - // 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()); + // Animate change transition on TaskFragment level to get the correct window crop. + newParent.initializeChangeTransition(getBounds(), getSurfaceControl()); } super.onParentChanged(newParent, oldParent); diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java index 82377b34d22a..3fc785a25454 100644 --- a/services/core/java/com/android/server/wm/AppTransitionController.java +++ b/services/core/java/com/android/server/wm/AppTransitionController.java @@ -343,9 +343,6 @@ public class AppTransitionController { switch (changingType) { case TYPE_TASK: return TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE; - case TYPE_ACTIVITY: - // ActivityRecord is put in a change transition only when it is reparented - // to an organized TaskFragment. See ActivityRecord#shouldStartChangeTransition. case TYPE_TASK_FRAGMENT: return TRANSIT_OLD_TASK_FRAGMENT_CHANGE; default: diff --git a/services/core/java/com/android/server/wm/SurfaceFreezer.java b/services/core/java/com/android/server/wm/SurfaceFreezer.java index 9c4f6f574487..89986cefb207 100644 --- a/services/core/java/com/android/server/wm/SurfaceFreezer.java +++ b/services/core/java/com/android/server/wm/SurfaceFreezer.java @@ -72,8 +72,11 @@ class SurfaceFreezer { * * @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. + * @param freezeTarget The surface to take snapshot from. If {@code null}, we will take a + * snapshot from the {@link #mAnimatable} surface. */ - void freeze(SurfaceControl.Transaction t, Rect startBounds, Point relativePosition) { + void freeze(SurfaceControl.Transaction t, Rect startBounds, Point relativePosition, + @Nullable SurfaceControl freezeTarget) { mFreezeBounds.set(startBounds); mLeash = SurfaceAnimator.createAnimationLeash(mAnimatable, mAnimatable.getSurfaceControl(), @@ -82,7 +85,7 @@ class SurfaceFreezer { mWmService.mTransactionFactory); mAnimatable.onAnimationLeashCreated(t, mLeash); - SurfaceControl freezeTarget = mAnimatable.getFreezeSnapshotTarget(); + freezeTarget = freezeTarget != null ? freezeTarget : mAnimatable.getFreezeSnapshotTarget(); if (freezeTarget != null) { SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer = createSnapshotBuffer( freezeTarget, startBounds); diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 0bc3712d7946..38e20555f236 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -2620,23 +2620,27 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< * For now, this will only be called for the following cases: * 1. {@link Task} is changing windowing mode between fullscreen and freeform. * 2. {@link TaskFragment} is organized and is changing window bounds. - * 3. {@link ActivityRecord} is reparented into an organized {@link TaskFragment}. + * 3. {@link ActivityRecord} is reparented into an organized {@link TaskFragment}. (The + * transition will happen on the {@link TaskFragment} for this case). * - * This shouldn't be called on other {@link WindowContainer} unless there is a valid use case. + * 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. + * @param freezeTarget The surface to take snapshot from. If {@code null}, we will take a + * snapshot from {@link #getFreezeSnapshotTarget()}. */ - void initializeChangeTransition(Rect startBounds, Rect parentBounds) { + void initializeChangeTransition(Rect startBounds, @Nullable SurfaceControl freezeTarget) { mDisplayContent.prepareAppTransition(TRANSIT_CHANGE); mDisplayContent.mChangingContainers.add(this); + // Calculate the relative position in parent container. + final Rect parentBounds = getParent().getBounds(); mTmpPoint.set(startBounds.left - parentBounds.left, startBounds.top - parentBounds.top); - mSurfaceFreezer.freeze(getSyncTransaction(), startBounds, mTmpPoint); + mSurfaceFreezer.freeze(getSyncTransaction(), startBounds, mTmpPoint, freezeTarget); } void initializeChangeTransition(Rect startBounds) { - initializeChangeTransition(startBounds, getParent().getBounds()); + initializeChangeTransition(startBounds, null /* freezeTarget */); } ArraySet<WindowContainer> getAnimationSources() { diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java index 405d714256ab..fb8bc7be38ce 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java @@ -35,6 +35,8 @@ import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentat import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.server.wm.WindowContainer.POSITION_TOP; import static org.junit.Assert.assertEquals; @@ -42,6 +44,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; import android.graphics.Rect; import android.os.Binder; @@ -54,6 +57,7 @@ import android.view.IRemoteAnimationFinishedCallback; import android.view.IRemoteAnimationRunner; import android.view.RemoteAnimationAdapter; import android.view.RemoteAnimationTarget; +import android.view.SurfaceControl; import android.view.WindowManager; import android.window.ITaskFragmentOrganizer; import android.window.TaskFragmentOrganizer; @@ -397,7 +401,9 @@ public class AppTransitionTests extends WindowTestsBase { @Test public void testActivityRecordReparentToTaskFragment() { final ActivityRecord activity = createActivityRecord(mDc); + final SurfaceControl activityLeash = mock(SurfaceControl.class); activity.setVisibility(true); + activity.setSurfaceControl(activityLeash); final Task task = activity.getTask(); // Add a TaskFragment of half of the Task size. @@ -412,15 +418,20 @@ public class AppTransitionTests extends WindowTestsBase { final Rect taskBounds = new Rect(); task.getBounds(taskBounds); taskFragment.setBounds(0, 0, taskBounds.right / 2, taskBounds.bottom); + spyOn(taskFragment); assertTrue(mDc.mChangingContainers.isEmpty()); assertFalse(mDc.mAppTransition.isTransitionSet()); // Schedule app transition when reparent activity to a TaskFragment of different size. + final Rect startBounds = new Rect(activity.getBounds()); activity.reparent(taskFragment, POSITION_TOP); - assertTrue(mDc.mChangingContainers.contains(activity)); + // It should transit at TaskFragment level with snapshot on the activity surface. + verify(taskFragment).initializeChangeTransition(activity.getBounds(), activityLeash); + assertTrue(mDc.mChangingContainers.contains(taskFragment)); assertTrue(mDc.mAppTransition.containsTransitRequest(TRANSIT_CHANGE)); + assertEquals(startBounds, taskFragment.mSurfaceFreezer.mFreezeBounds); } private class TestRemoteAnimationRunner implements IRemoteAnimationRunner { |