diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 91c849c4110f6..0598680f8c5d4 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -6683,6 +6683,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return task != null ? task.getBounds() : getBounds(); } + @Override + void getAnimationPosition(Point outPosition) { + // Always animate from zero because if the activity doesn't fill the task, the letterbox + // will fill the remaining area that should be included in the animation. + outPosition.set(0, 0); + } + @Override public void onConfigurationChanged(Configuration newParentConfig) { if (mCompatDisplayInsets != null) { diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 5d7ec127da464..7bfddd79f8a44 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -2120,6 +2120,11 @@ class WindowContainer extends ConfigurationContainer< return getBounds(); } + /** Gets the position relative to parent for animation. */ + void getAnimationPosition(Point outPosition) { + getRelativePosition(outPosition); + } + /** * Applies the app transition animation according the given the layout properties in the * window hierarchy. @@ -2178,9 +2183,9 @@ class WindowContainer extends ConfigurationContainer< // Separate position and size for use in animators. mTmpRect.set(getAnimationBounds(appStackClipMode)); - if (sHierarchicalAnimations) { - getRelativePosition(mTmpPoint); - } else { + getAnimationPosition(mTmpPoint); + if (!sHierarchicalAnimations) { + // Non-hierarchical animation uses position in global coordinates. mTmpPoint.set(mTmpRect.left, mTmpRect.top); } mTmpRect.offsetTo(0, 0); diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java index 8f18f648f8f0a..07050d9666d5b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java @@ -52,6 +52,7 @@ import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import android.content.res.Configuration; +import android.graphics.Point; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; import android.view.IWindowManager; @@ -432,20 +433,35 @@ public class AppWindowTokenTests extends WindowTestsBase { removeGlobalMinSizeRestriction(); final Rect stackBounds = new Rect(0, 0, 1000, 600); final Rect taskBounds = new Rect(100, 400, 600, 800); - mStack.setBounds(stackBounds); - mTask.setBounds(taskBounds); + // Set the bounds and windowing mode to window configuration directly, otherwise the + // testing setups may be discarded by configuration resolving. + mStack.getWindowConfiguration().setBounds(stackBounds); + mTask.getWindowConfiguration().setBounds(taskBounds); + mActivity.getWindowConfiguration().setBounds(taskBounds); // Check that anim bounds for freeform window match task bounds - mTask.setWindowingMode(WINDOWING_MODE_FREEFORM); + mTask.getWindowConfiguration().setWindowingMode(WINDOWING_MODE_FREEFORM); assertEquals(mTask.getBounds(), mActivity.getAnimationBounds(STACK_CLIP_NONE)); // STACK_CLIP_AFTER_ANIM should use task bounds since they will be clipped by // bounds animation layer. - mTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN); + mTask.getWindowConfiguration().setWindowingMode(WINDOWING_MODE_FULLSCREEN); assertEquals(mTask.getBounds(), mActivity.getAnimationBounds(STACK_CLIP_AFTER_ANIM)); + // Even the activity is smaller than task and it is not aligned to the top-left corner of + // task, the animation bounds the same as task and position should be zero because in real + // case the letterbox will fill the remaining area in task. + final Rect halfBounds = new Rect(taskBounds); + halfBounds.scale(0.5f); + mActivity.getWindowConfiguration().setBounds(halfBounds); + final Point animationPosition = new Point(); + mActivity.getAnimationPosition(animationPosition); + + assertEquals(taskBounds, mActivity.getAnimationBounds(STACK_CLIP_AFTER_ANIM)); + assertEquals(new Point(0, 0), animationPosition); + // STACK_CLIP_BEFORE_ANIM should use stack bounds since it won't be clipped later. - mTask.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); + mTask.getWindowConfiguration().setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); assertEquals(mStack.getBounds(), mActivity.getAnimationBounds(STACK_CLIP_BEFORE_ANIM)); }