Use TaskFragment bounds instead of TaskBounds for Activity animation
The animation bounds is used as the RemoteAnimationTarget#localBounds. It should be the TaskFragment bounds instead of Task bounds because the Activity may not fill the Task when it is in a TaskFragment. Also clean up ROOT_TASK_CLIP_BEFORE_ANIM which has no more use case. Bug: 196173550 Test: test with demo app Test: atest WmTests:ActivityRecordTests Change-Id: Iff58afdb0bbae95d3f6a5756de06c0d2dfff7c88
This commit is contained in:
@@ -223,7 +223,6 @@ import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
|
||||
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
|
||||
import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
|
||||
import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
|
||||
import static com.android.server.wm.WindowStateAnimator.ROOT_TASK_CLIP_BEFORE_ANIM;
|
||||
|
||||
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
|
||||
import static org.xmlpull.v1.XmlPullParser.END_TAG;
|
||||
@@ -8041,13 +8040,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
@VisibleForTesting
|
||||
@Override
|
||||
Rect getAnimationBounds(int appRootTaskClipMode) {
|
||||
if (appRootTaskClipMode == ROOT_TASK_CLIP_BEFORE_ANIM && getRootTask() != null) {
|
||||
// Using the root task bounds here effectively applies the clipping before animation.
|
||||
return getRootTask().getBounds();
|
||||
}
|
||||
// Use task-bounds if available so that activity-level letterbox (maxAspectRatio) is
|
||||
// Use TaskFragment-bounds if available so that activity-level letterbox (maxAspectRatio) is
|
||||
// included in the animation.
|
||||
return task != null ? task.getBounds() : getBounds();
|
||||
final TaskFragment taskFragment = getTaskFragment();
|
||||
return taskFragment != null ? taskFragment.getBounds() : getBounds();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -130,7 +130,6 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ROOT_TASK;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
|
||||
import static com.android.server.wm.WindowManagerService.dipToPixel;
|
||||
import static com.android.server.wm.WindowStateAnimator.ROOT_TASK_CLIP_BEFORE_ANIM;
|
||||
|
||||
import static java.lang.Integer.MAX_VALUE;
|
||||
|
||||
@@ -2984,16 +2983,6 @@ class Task extends TaskFragment {
|
||||
super.resetSurfacePositionForAnimationLeash(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
Rect getAnimationBounds(int appRootTaskClipMode) {
|
||||
// TODO(b/131661052): we should remove appRootTaskClipMode with hierarchical animations.
|
||||
if (appRootTaskClipMode == ROOT_TASK_CLIP_BEFORE_ANIM && getRootTask() != null) {
|
||||
// Using the root task bounds here effectively applies the clipping before animation.
|
||||
return getRootTask().getBounds();
|
||||
}
|
||||
return super.getAnimationBounds(appRootTaskClipMode);
|
||||
}
|
||||
|
||||
boolean shouldAnimate() {
|
||||
/**
|
||||
* Animations are handled by the TaskOrganizer implementation.
|
||||
|
||||
@@ -79,17 +79,11 @@ class WindowStateAnimator {
|
||||
*/
|
||||
static final int ROOT_TASK_CLIP_AFTER_ANIM = 0;
|
||||
|
||||
/**
|
||||
* Mode how the window gets clipped by the root task bounds: The clipping should be applied
|
||||
* before applying the animation transformation, i.e. the root task bounds move with the window.
|
||||
*/
|
||||
static final int ROOT_TASK_CLIP_BEFORE_ANIM = 1;
|
||||
|
||||
/**
|
||||
* Mode how window gets clipped by the root task bounds during an animation: Don't clip the
|
||||
* window by the root task bounds.
|
||||
*/
|
||||
static final int ROOT_TASK_CLIP_NONE = 2;
|
||||
static final int ROOT_TASK_CLIP_NONE = 1;
|
||||
|
||||
// Unchanging local convenience fields.
|
||||
final WindowManagerService mService;
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.android.server.wm;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
|
||||
import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
|
||||
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
|
||||
import static android.content.pm.ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE;
|
||||
@@ -83,7 +82,6 @@ import static com.android.server.wm.TaskFragment.TASK_FRAGMENT_VISIBILITY_VISIBL
|
||||
import static com.android.server.wm.TaskFragment.TASK_FRAGMENT_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
|
||||
import static com.android.server.wm.WindowContainer.POSITION_TOP;
|
||||
import static com.android.server.wm.WindowStateAnimator.ROOT_TASK_CLIP_AFTER_ANIM;
|
||||
import static com.android.server.wm.WindowStateAnimator.ROOT_TASK_CLIP_BEFORE_ANIM;
|
||||
import static com.android.server.wm.WindowStateAnimator.ROOT_TASK_CLIP_NONE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
@@ -2779,10 +2777,36 @@ public class ActivityRecordTests extends WindowTestsBase {
|
||||
|
||||
assertEquals(taskBounds, activity.getAnimationBounds(ROOT_TASK_CLIP_AFTER_ANIM));
|
||||
assertEquals(new Point(0, 0), animationPosition);
|
||||
}
|
||||
|
||||
// ROOT_TASK_CLIP_BEFORE_ANIM should use stack bounds since it won't be clipped later.
|
||||
task.getWindowConfiguration().setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
|
||||
assertEquals(rootTask.getBounds(), activity.getAnimationBounds(ROOT_TASK_CLIP_BEFORE_ANIM));
|
||||
@Test
|
||||
public void testTransitionAnimationBounds_returnTaskFragment() {
|
||||
removeGlobalMinSizeRestriction();
|
||||
final Task task = new TaskBuilder(mSupervisor).setCreateParentTask(true).build();
|
||||
final Task rootTask = task.getRootTask();
|
||||
final TaskFragment taskFragment = createTaskFragmentWithParentTask(task,
|
||||
false /* createEmbeddedTask */);
|
||||
final ActivityRecord activity = taskFragment.getTopNonFinishingActivity();
|
||||
final Rect stackBounds = new Rect(0, 0, 1000, 600);
|
||||
final Rect taskBounds = new Rect(100, 400, 600, 800);
|
||||
final Rect taskFragmentBounds = new Rect(100, 400, 300, 800);
|
||||
final Rect activityBounds = new Rect(100, 400, 300, 600);
|
||||
// Set the bounds and windowing mode to window configuration directly, otherwise the
|
||||
// testing setups may be discarded by configuration resolving.
|
||||
rootTask.getWindowConfiguration().setBounds(stackBounds);
|
||||
task.getWindowConfiguration().setBounds(taskBounds);
|
||||
taskFragment.getWindowConfiguration().setBounds(taskFragmentBounds);
|
||||
activity.getWindowConfiguration().setBounds(activityBounds);
|
||||
|
||||
// Check that anim bounds for freeform window match task fragment bounds
|
||||
task.getWindowConfiguration().setWindowingMode(WINDOWING_MODE_FREEFORM);
|
||||
assertEquals(taskFragment.getBounds(), activity.getAnimationBounds(ROOT_TASK_CLIP_NONE));
|
||||
|
||||
// ROOT_TASK_CLIP_AFTER_ANIM should use task fragment bounds since they will be clipped by
|
||||
// bounds animation layer.
|
||||
task.getWindowConfiguration().setWindowingMode(WINDOWING_MODE_FULLSCREEN);
|
||||
assertEquals(taskFragment.getBounds(),
|
||||
activity.getAnimationBounds(ROOT_TASK_CLIP_AFTER_ANIM));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.android.server.wm;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
|
||||
import static com.android.server.wm.WindowStateAnimator.ROOT_TASK_CLIP_AFTER_ANIM;
|
||||
import static com.android.server.wm.WindowStateAnimator.ROOT_TASK_CLIP_BEFORE_ANIM;
|
||||
import static com.android.server.wm.WindowStateAnimator.ROOT_TASK_CLIP_NONE;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
@@ -88,43 +87,6 @@ public class WindowAnimationSpecTest {
|
||||
argThat(rect -> rect.equals(mStackBounds)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApply_clipBeforeNoAnimationBounds() {
|
||||
// Stack bounds is (0, 0, 10, 10) animation clip is (0, 0, 0, 0)
|
||||
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(mAnimation, null,
|
||||
mStackBounds, false /* canSkipFirstFrame */, ROOT_TASK_CLIP_BEFORE_ANIM,
|
||||
true /* isAppAnimation */, 0 /* windowCornerRadius */);
|
||||
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
|
||||
verify(mTransaction).setWindowCrop(eq(mSurfaceControl),
|
||||
argThat(rect -> rect.equals(mStackBounds)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApply_clipBeforeNoStackBounds() {
|
||||
// Stack bounds is (0, 0, 0, 0) animation clip is (0, 0, 20, 20)
|
||||
Rect windowCrop = new Rect(0, 0, 20, 20);
|
||||
Animation a = createClipRectAnimation(windowCrop, windowCrop);
|
||||
a.initialize(0, 0, 0, 0);
|
||||
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
|
||||
null, false /* canSkipFirstFrame */, ROOT_TASK_CLIP_BEFORE_ANIM,
|
||||
true /* isAppAnimation */, 0 /* windowCornerRadius */);
|
||||
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
|
||||
verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApply_setCornerRadius() {
|
||||
final float windowCornerRadius = 30f;
|
||||
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(mAnimation, null,
|
||||
mStackBounds, false /* canSkipFirstFrame */, ROOT_TASK_CLIP_BEFORE_ANIM,
|
||||
true /* isAppAnimation */, windowCornerRadius);
|
||||
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
|
||||
verify(mTransaction, never()).setCornerRadius(eq(mSurfaceControl), eq(windowCornerRadius));
|
||||
when(mAnimation.hasRoundedCorners()).thenReturn(true);
|
||||
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
|
||||
verify(mTransaction).setCornerRadius(eq(mSurfaceControl), eq(windowCornerRadius));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApply_setCornerRadius_noClip() {
|
||||
final float windowCornerRadius = 30f;
|
||||
@@ -136,32 +98,6 @@ public class WindowAnimationSpecTest {
|
||||
verify(mTransaction, never()).setCornerRadius(any(), anyFloat());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApply_clipBeforeSmallerAnimationClip() {
|
||||
// Stack bounds is (0, 0, 10, 10) animation clip is (0, 0, 5, 5)
|
||||
Rect windowCrop = new Rect(0, 0, 5, 5);
|
||||
Animation a = createClipRectAnimation(windowCrop, windowCrop);
|
||||
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
|
||||
mStackBounds, false /* canSkipFirstFrame */, ROOT_TASK_CLIP_BEFORE_ANIM,
|
||||
true /* isAppAnimation */, 0 /* windowCornerRadius */);
|
||||
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
|
||||
verify(mTransaction).setWindowCrop(eq(mSurfaceControl),
|
||||
argThat(rect -> rect.equals(windowCrop)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApply_clipBeforeSmallerStackClip() {
|
||||
// Stack bounds is (0, 0, 10, 10) animation clip is (0, 0, 20, 20)
|
||||
Rect windowCrop = new Rect(0, 0, 20, 20);
|
||||
Animation a = createClipRectAnimation(windowCrop, windowCrop);
|
||||
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
|
||||
mStackBounds, false /* canSkipFirstFrame */, ROOT_TASK_CLIP_BEFORE_ANIM,
|
||||
true /* isAppAnimation */, 0 /* windowCornerRadius */);
|
||||
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
|
||||
verify(mTransaction).setWindowCrop(eq(mSurfaceControl),
|
||||
argThat(rect -> rect.equals(mStackBounds)));
|
||||
}
|
||||
|
||||
private Animation createClipRectAnimation(Rect fromClip, Rect toClip) {
|
||||
Animation a = new ClipRectAnimation(fromClip, toClip);
|
||||
a.initialize(0, 0, 0, 0);
|
||||
|
||||
Reference in New Issue
Block a user