Reparent recents animation task leash to app animation layer
- When swiping up in split screen, the task is clipped by the unminimized
stack bounds, instead reparent to app animation layer to allow it to be
unconstrained. Currently, this will bump it up to the top, but we need
a mechanism later to bump it only to under the primary splitscreen stack.
Bug: 73118672
Test: Swipe up from split screen, ensure app window is not clipped
Change-Id: Iacc6d6b82274b8b26b2dab85628479b5ff490817
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index c9ff9e3..d77985c 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3566,7 +3566,8 @@
if (s.inSplitScreenWindowingMode() && mSplitScreenDividerAnchor != null) {
t.setLayer(mSplitScreenDividerAnchor, layer++);
}
- if (s.isAppAnimating() && state != ALWAYS_ON_TOP_STATE) {
+ if ((s.isTaskAnimating() || s.isAppAnimating())
+ && state != ALWAYS_ON_TOP_STATE) {
// Ensure the animation layer ends up above the
// highest animating stack and no higher.
layerForAnimationLayer = layer++;
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index b12c36e..c4f5197 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -432,6 +432,15 @@
return mHomeAppToken.windowsCanBeWallpaperTarget();
}
+ boolean isAnimatingTask(Task task) {
+ for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
+ if (task == mPendingAnimations.get(i).mTask) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private boolean isAnimatingApp(AppWindowToken appToken) {
for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
final Task task = mPendingAnimations.get(i).mTask;
@@ -452,18 +461,18 @@
private OnAnimationFinishedCallback mCapturedFinishCallback;
private final boolean mIsRecentTaskInvisible;
private RemoteAnimationTarget mTarget;
+ private final Point mPosition = new Point();
+ private final Rect mBounds = new Rect();
TaskAnimationAdapter(Task task, boolean isRecentTaskInvisible) {
mTask = task;
mIsRecentTaskInvisible = isRecentTaskInvisible;
+ final WindowContainer container = mTask.getParent();
+ container.getRelativePosition(mPosition);
+ container.getBounds(mBounds);
}
RemoteAnimationTarget createRemoteAnimationApp() {
- final Point position = new Point();
- final Rect bounds = new Rect();
- final WindowContainer container = mTask.getParent();
- container.getRelativePosition(position);
- container.getBounds(bounds);
final WindowState mainWindow = mTask.getTopVisibleAppMainWindow();
if (mainWindow == null) {
return null;
@@ -472,7 +481,7 @@
InsetUtils.addInsets(insets, mainWindow.mAppToken.getLetterboxInsets());
mTarget = new RemoteAnimationTarget(mTask.mTaskId, MODE_CLOSING, mCapturedLeash,
!mTask.fillsParent(), mainWindow.mWinAnimator.mLastClipRect,
- insets, mTask.getPrefixOrderIndex(), position, bounds,
+ insets, mTask.getPrefixOrderIndex(), mPosition, mBounds,
mTask.getWindowConfiguration(), mIsRecentTaskInvisible);
return mTarget;
}
@@ -495,6 +504,7 @@
@Override
public void startAnimation(SurfaceControl animationLeash, Transaction t,
OnAnimationFinishedCallback finishCallback) {
+ t.setPosition(animationLeash, mPosition.x, mPosition.y);
mCapturedLeash = animationLeash;
mCapturedFinishCallback = finishCallback;
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index e8d3210..95223d8 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -44,6 +44,7 @@
import android.util.proto.ProtoOutputStream;
import android.view.Surface;
+import android.view.SurfaceControl;
import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
@@ -559,6 +560,23 @@
&& !mStack.isAnimatingBoundsToFullscreen() && !mPreserveNonFloatingState;
}
+ @Override
+ public SurfaceControl getAnimationLeashParent() {
+ // Reparent to the animation layer so that we aren't clipped by the non-minimized
+ // stack bounds, currently we only animate the task for the recents animation
+ return getAppAnimationLayer(false /* boosted */);
+ }
+
+ boolean isTaskAnimating() {
+ final RecentsAnimationController recentsAnim = mService.getRecentsAnimationController();
+ if (recentsAnim != null) {
+ if (recentsAnim.isAnimatingTask(this)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
WindowState getTopVisibleAppMainWindow() {
final AppWindowToken token = getTopVisibleAppToken();
return token != null ? token.findMainWindow() : null;
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index c97f394..2175c6b 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1331,6 +1331,20 @@
return mMinimizeAmount != 0f;
}
+ /**
+ * @return {@code true} if we have a {@link Task} that is animating (currently only used for the
+ * recents animation); {@code false} otherwise.
+ */
+ boolean isTaskAnimating() {
+ for (int j = mChildren.size() - 1; j >= 0; j--) {
+ final Task task = mChildren.get(j);
+ if (task.isTaskAnimating()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@CallSuper
@Override
public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) {