Merge "Fix enter/exit horizontal ActivityEmbedding split with Shell transition" into tm-qpr-dev am: 4013b5600d
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20505728
Change-Id: I47186d15111d7ea14218e6ba197db9e9e9b201dd
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java
index 215308d..00b9fced 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java
@@ -30,6 +30,8 @@
import androidx.annotation.NonNull;
+import com.android.wm.shell.transition.Transitions;
+
/**
* Wrapper to handle the ActivityEmbedding animation update in one
* {@link SurfaceControl.Transaction}.
@@ -50,6 +52,16 @@
/** Area in absolute coordinate that the animation surface shouldn't go beyond. */
@NonNull
private final Rect mWholeAnimationBounds = new Rect();
+ /**
+ * Area in absolute coordinate that should represent all the content to show for this window.
+ * This should be the end bounds for opening window, and start bounds for closing window in case
+ * the window is resizing during the open/close transition.
+ */
+ @NonNull
+ private final Rect mContentBounds = new Rect();
+ /** Offset relative to the window parent surface for {@link #mContentBounds}. */
+ @NonNull
+ private final Point mContentRelOffset = new Point();
@NonNull
final Transformation mTransformation = new Transformation();
@@ -80,6 +92,21 @@
mChange = change;
mLeash = leash;
mWholeAnimationBounds.set(wholeAnimationBounds);
+ if (Transitions.isClosingType(change.getMode())) {
+ // When it is closing, we want to show the content at the start position in case the
+ // window is resizing as well. For example, when the activities is changing from split
+ // to stack, the bottom TaskFragment will be resized to fullscreen when hiding.
+ final Rect startBounds = change.getStartAbsBounds();
+ final Rect endBounds = change.getEndAbsBounds();
+ mContentBounds.set(startBounds);
+ mContentRelOffset.set(change.getEndRelOffset());
+ mContentRelOffset.offset(
+ startBounds.left - endBounds.left,
+ startBounds.top - endBounds.top);
+ } else {
+ mContentBounds.set(change.getEndAbsBounds());
+ mContentRelOffset.set(change.getEndRelOffset());
+ }
}
/**
@@ -110,8 +137,7 @@
/** To be overridden by subclasses to adjust the animation surface change. */
void onAnimationUpdateInner(@NonNull SurfaceControl.Transaction t) {
// Update the surface position and alpha.
- final Point offset = mChange.getEndRelOffset();
- mTransformation.getMatrix().postTranslate(offset.x, offset.y);
+ mTransformation.getMatrix().postTranslate(mContentRelOffset.x, mContentRelOffset.y);
t.setMatrix(mLeash, mTransformation.getMatrix(), mMatrix);
t.setAlpha(mLeash, mTransformation.getAlpha());
@@ -119,8 +145,8 @@
// positionX/Y are in local coordinate, so minus the local offset to get the slide amount.
final int positionX = Math.round(mMatrix[MTRANS_X]);
final int positionY = Math.round(mMatrix[MTRANS_Y]);
- final Rect cropRect = new Rect(mChange.getEndAbsBounds());
- cropRect.offset(positionX - offset.x, positionY - offset.y);
+ final Rect cropRect = new Rect(mContentBounds);
+ cropRect.offset(positionX - mContentRelOffset.x, positionY - mContentRelOffset.y);
// Store the current offset of the surface top left from (0,0) in absolute coordinate.
final int offsetX = cropRect.left;
@@ -133,7 +159,7 @@
} else if (mAnimation.hasExtension()) {
// Allow the surface to be shown in its original bounds in case we want to use edge
// extensions.
- cropRect.union(mChange.getEndAbsBounds());
+ cropRect.union(mContentBounds);
}
// cropRect is in absolute coordinate, so we need to translate it to surface top left.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java
index 921861a..c0a6456 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java
@@ -304,6 +304,7 @@
// This is because the TaskFragment surface/change won't contain the Activity's before its
// reparent.
Animation changeAnimation = null;
+ Rect parentBounds = new Rect();
for (TransitionInfo.Change change : info.getChanges()) {
if (change.getMode() != TRANSIT_CHANGE
|| change.getStartAbsBounds().equals(change.getEndAbsBounds())) {
@@ -326,10 +327,15 @@
}
}
+ // The TaskFragment may be enter/exit split, so we take the union of both as the parent
+ // size.
+ parentBounds.union(boundsAnimationChange.getStartAbsBounds());
+ parentBounds.union(boundsAnimationChange.getEndAbsBounds());
+
// There are two animations in the array. The first one is for the start leash
// (snapshot), and the second one is for the end leash (TaskFragment).
final Animation[] animations = mAnimationSpec.createChangeBoundsChangeAnimations(change,
- boundsAnimationChange.getEndAbsBounds());
+ parentBounds);
// Keep track as we might need to add background color for the animation.
// Although there may be multiple change animation, record one of them is sufficient
// because the background color will be added to the root leash for the whole animation.
@@ -352,6 +358,11 @@
animations[1], boundsAnimationChange));
}
+ if (parentBounds.isEmpty()) {
+ throw new IllegalStateException(
+ "There should be at least one changing window to play the change animation");
+ }
+
// If there is no corresponding open/close window with the change, we should show background
// color to cover the empty part of the screen.
boolean shouldShouldBackgroundColor = true;
@@ -368,10 +379,10 @@
// No-op if it will be covered by the changing parent window.
animation = ActivityEmbeddingAnimationSpec.createNoopAnimation(change);
} else if (Transitions.isClosingType(change.getMode())) {
- animation = mAnimationSpec.createChangeBoundsCloseAnimation(change);
+ animation = mAnimationSpec.createChangeBoundsCloseAnimation(change, parentBounds);
shouldShouldBackgroundColor = false;
} else {
- animation = mAnimationSpec.createChangeBoundsOpenAnimation(change);
+ animation = mAnimationSpec.createChangeBoundsOpenAnimation(change, parentBounds);
shouldShouldBackgroundColor = false;
}
adapters.add(new ActivityEmbeddingAnimationAdapter(animation, change));
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
index 2bb7369..65a7d09 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
@@ -21,7 +21,6 @@
import static com.android.wm.shell.transition.TransitionAnimationHelper.loadAttributeAnimation;
import android.content.Context;
-import android.graphics.Point;
import android.graphics.Rect;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
@@ -80,15 +79,25 @@
/** Animation for window that is opening in a change transition. */
@NonNull
- Animation createChangeBoundsOpenAnimation(@NonNull TransitionInfo.Change change) {
+ Animation createChangeBoundsOpenAnimation(@NonNull TransitionInfo.Change change,
+ @NonNull Rect parentBounds) {
+ // Use end bounds for opening.
final Rect bounds = change.getEndAbsBounds();
- final Point offset = change.getEndRelOffset();
- // The window will be animated in from left or right depends on its position.
- final int startLeft = offset.x == 0 ? -bounds.width() : bounds.width();
+ final int startLeft;
+ final int startTop;
+ if (parentBounds.top == bounds.top && parentBounds.bottom == bounds.bottom) {
+ // The window will be animated in from left or right depends on its position.
+ startTop = 0;
+ startLeft = parentBounds.left == bounds.left ? -bounds.width() : bounds.width();
+ } else {
+ // The window will be animated in from top or bottom depends on its position.
+ startTop = parentBounds.top == bounds.top ? -bounds.height() : bounds.height();
+ startLeft = 0;
+ }
// The position should be 0-based as we will post translate in
// ActivityEmbeddingAnimationAdapter#onAnimationUpdate
- final Animation animation = new TranslateAnimation(startLeft, 0, 0, 0);
+ final Animation animation = new TranslateAnimation(startLeft, 0, startTop, 0);
animation.setInterpolator(mFastOutExtraSlowInInterpolator);
animation.setDuration(CHANGE_ANIMATION_DURATION);
animation.initialize(bounds.width(), bounds.height(), bounds.width(), bounds.height());
@@ -98,15 +107,25 @@
/** Animation for window that is closing in a change transition. */
@NonNull
- Animation createChangeBoundsCloseAnimation(@NonNull TransitionInfo.Change change) {
- final Rect bounds = change.getEndAbsBounds();
- final Point offset = change.getEndRelOffset();
- // The window will be animated out to left or right depends on its position.
- final int endLeft = offset.x == 0 ? -bounds.width() : bounds.width();
+ Animation createChangeBoundsCloseAnimation(@NonNull TransitionInfo.Change change,
+ @NonNull Rect parentBounds) {
+ // Use start bounds for closing.
+ final Rect bounds = change.getStartAbsBounds();
+ final int endTop;
+ final int endLeft;
+ if (parentBounds.top == bounds.top && parentBounds.bottom == bounds.bottom) {
+ // The window will be animated out to left or right depends on its position.
+ endTop = 0;
+ endLeft = parentBounds.left == bounds.left ? -bounds.width() : bounds.width();
+ } else {
+ // The window will be animated out to top or bottom depends on its position.
+ endTop = parentBounds.top == bounds.top ? -bounds.height() : bounds.height();
+ endLeft = 0;
+ }
// The position should be 0-based as we will post translate in
// ActivityEmbeddingAnimationAdapter#onAnimationUpdate
- final Animation animation = new TranslateAnimation(0, endLeft, 0, 0);
+ final Animation animation = new TranslateAnimation(0, endLeft, 0, endTop);
animation.setInterpolator(mFastOutExtraSlowInInterpolator);
animation.setDuration(CHANGE_ANIMATION_DURATION);
animation.initialize(bounds.width(), bounds.height(), bounds.width(), bounds.height());