Set crop and final crop for WindowAnimation
Added crop and final crop to WindowAnimation depending on clip mode.
Test: 1. Enter split screen by dragging app from recents.
2. In split screen, open new activities in primary window.
3. Lock screen and unlock while in split screen
Change-Id: Idc4055de8c2c9aaa449f6387097c1970ef1d94fa
diff --git a/services/core/java/com/android/server/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
index b01b268..b86cd50 100644
--- a/services/core/java/com/android/server/wm/AppWindowThumbnail.java
+++ b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
@@ -86,12 +86,10 @@
void startAnimation(Transaction t, Animation anim) {
anim.restrictDuration(MAX_ANIMATION_DURATION);
anim.scaleCurrentDuration(mAppToken.mService.getTransitionAnimationScaleLocked());
- mSurfaceAnimator.startAnimation(t,
- new LocalAnimationAdapter(
- new WindowAnimationSpec(anim, new Point(),
- mAppToken.mService.mAppTransition.canSkipFirstFrame()),
- mAppToken.mService.mSurfaceAnimationRunner),
- false /* hidden */);
+ mSurfaceAnimator.startAnimation(t, new LocalAnimationAdapter(
+ new WindowAnimationSpec(anim, null /* position */,
+ mAppToken.mService.mAppTransition.canSkipFirstFrame()),
+ mAppToken.mService.mSurfaceAnimationRunner), false /* hidden */);
}
private void onAnimationFinished() {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index af7523c..b24a8ca 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -222,6 +222,7 @@
private boolean mNeedsZBoost;
private final Point mTmpPoint = new Point();
+ private final Rect mTmpRect = new Rect();
AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction,
DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen,
@@ -1536,12 +1537,15 @@
if (a != null) {
final TaskStack stack = getStack();
mTmpPoint.set(0, 0);
+ mTmpRect.setEmpty();
if (stack != null) {
stack.getRelativePosition(mTmpPoint);
+ stack.getBounds(mTmpRect);
}
final AnimationAdapter adapter = new LocalAnimationAdapter(
- new WindowAnimationSpec(a, mTmpPoint,
- mService.mAppTransition.canSkipFirstFrame()),
+ new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
+ mService.mAppTransition.canSkipFirstFrame(),
+ mService.mAppTransition.getAppStackClipMode()),
mService.mSurfaceAnimationRunner);
if (a.getZAdjustment() == Animation.ZORDER_TOP) {
mNeedsZBoost = true;
@@ -1549,7 +1553,6 @@
startAnimation(getPendingTransaction(), adapter, !isVisible());
mTransit = transit;
mTransitFlags = mService.mAppTransition.getTransitFlags();
- // TODO: Skip first frame and app stack clip mode.
}
} else {
cancelAnimation();
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 7aae129..3ffc7fa 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -320,7 +320,7 @@
if (matchParentBounds()
|| !inSplitScreenSecondaryWindowingMode()
|| mDisplayContent == null
- || mDisplayContent.getSplitScreenPrimaryStack() != null) {
+ || mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility() != null) {
return true;
}
return false;
diff --git a/services/core/java/com/android/server/wm/WindowAnimationSpec.java b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
index 20e19f4..9865293 100644
--- a/services/core/java/com/android/server/wm/WindowAnimationSpec.java
+++ b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
@@ -17,8 +17,11 @@
package com.android.server.wm;
import static com.android.server.wm.AnimationAdapter.STATUS_BAR_TRANSITION_DURATION;
+import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
+import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE;
import android.graphics.Point;
+import android.graphics.Rect;
import android.os.SystemClock;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
@@ -39,11 +42,25 @@
private final Point mPosition = new Point();
private final ThreadLocal<TmpValues> mThreadLocalTmps = ThreadLocal.withInitial(TmpValues::new);
private final boolean mCanSkipFirstFrame;
+ private final Rect mStackBounds = new Rect();
+ private int mStackClipMode;
+ private final Rect mTmpRect = new Rect();
public WindowAnimationSpec(Animation animation, Point position, boolean canSkipFirstFrame) {
+ this(animation, position, null /* stackBounds */, canSkipFirstFrame, STACK_CLIP_NONE);
+ }
+
+ public WindowAnimationSpec(Animation animation, Point position, Rect stackBounds,
+ boolean canSkipFirstFrame, int stackClipMode) {
mAnimation = animation;
- mPosition.set(position.x, position.y);
+ if (position != null) {
+ mPosition.set(position.x, position.y);
+ }
mCanSkipFirstFrame = canSkipFirstFrame;
+ mStackClipMode = stackClipMode;
+ if (stackBounds != null) {
+ mStackBounds.set(stackBounds);
+ }
}
@Override
@@ -69,7 +86,16 @@
tmp.transformation.getMatrix().postTranslate(mPosition.x, mPosition.y);
t.setMatrix(leash, tmp.transformation.getMatrix(), tmp.floats);
t.setAlpha(leash, tmp.transformation.getAlpha());
- t.setWindowCrop(leash, tmp.transformation.getClipRect());
+ if (mStackClipMode == STACK_CLIP_NONE) {
+ t.setWindowCrop(leash, tmp.transformation.getClipRect());
+ } else if (mStackClipMode == STACK_CLIP_AFTER_ANIM) {
+ t.setFinalCrop(leash, mStackBounds);
+ t.setWindowCrop(leash, tmp.transformation.getClipRect());
+ } else {
+ mTmpRect.set(tmp.transformation.getClipRect());
+ mTmpRect.intersect(mStackBounds);
+ t.setWindowCrop(leash, mTmpRect);
+ }
}
@Override
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index ce93b95..d2247ac 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -45,7 +45,6 @@
import static com.android.server.wm.proto.WindowStateAnimatorProto.LAST_CLIP_RECT;
import static com.android.server.wm.proto.WindowStateAnimatorProto.SURFACE;
-import android.app.WindowConfiguration;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
@@ -64,7 +63,6 @@
import android.view.WindowManager.LayoutParams;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
-import android.view.animation.Transformation;
import com.android.server.policy.WindowManagerPolicy;
@@ -769,47 +767,6 @@
}
/**
- * In some scenarios we use a screen space clip rect (so called, final clip rect)
- * to crop to stack bounds. Generally because it's easier to deal with while
- * animating.
- *
- * @return True in scenarios where we use the final clip rect for stack clipping.
- */
- private boolean useFinalClipRect() {
- return (isAnimationSet() && resolveStackClip() == STACK_CLIP_AFTER_ANIM)
- || mDestroyPreservedSurfaceUponRedraw || mWin.inPinnedWindowingMode();
- }
-
- /**
- * Calculate the screen-space crop rect and fill finalClipRect.
- * @return true if finalClipRect has been filled, otherwise,
- * no screen space crop should be applied.
- */
- private boolean calculateFinalCrop(Rect finalClipRect) {
- final WindowState w = mWin;
- final DisplayContent displayContent = w.getDisplayContent();
- finalClipRect.setEmpty();
-
- if (displayContent == null) {
- return false;
- }
-
- if (!shouldCropToStackBounds() || !useFinalClipRect()) {
- return false;
- }
-
- // Task is non-null per shouldCropToStackBounds
- final TaskStack stack = w.getTask().mStack;
- stack.getDimBounds(finalClipRect);
-
- if (stack.getWindowConfiguration().tasksAreFloating()) {
- w.expandForSurfaceInsets(finalClipRect);
- }
-
- return true;
- }
-
- /**
* Calculate the window-space crop rect and fill clipRect.
* @return true if clipRect has been filled otherwise, no window space crop should be applied.
*/
@@ -869,9 +826,6 @@
// so we need to translate to match the actual surface coordinates.
clipRect.offset(w.mAttrs.surfaceInsets.left, w.mAttrs.surfaceInsets.top);
- if (!useFinalClipRect()) {
- adjustCropToStackBounds(clipRect, isFreeformResizing);
- }
if (DEBUG_WINDOW_CROP) Slog.d(TAG,
"win=" + w + " Clip rect after stack adjustment=" + clipRect);
@@ -880,9 +834,9 @@
return true;
}
- private void applyCrop(Rect clipRect, Rect finalClipRect, boolean recoveringMemory) {
+ private void applyCrop(Rect clipRect, boolean recoveringMemory) {
if (DEBUG_WINDOW_CROP) Slog.d(TAG, "applyCrop: win=" + mWin
- + " clipRect=" + clipRect + " finalClipRect=" + finalClipRect);
+ + " clipRect=" + clipRect);
if (clipRect != null) {
if (!clipRect.equals(mLastClipRect)) {
mLastClipRect.set(clipRect);
@@ -891,94 +845,6 @@
} else {
mSurfaceController.clearCropInTransaction(recoveringMemory);
}
-
- if (finalClipRect == null) {
- finalClipRect = mService.mTmpRect;
- finalClipRect.setEmpty();
- }
- if (!finalClipRect.equals(mLastFinalClipRect)) {
- mLastFinalClipRect.set(finalClipRect);
- mSurfaceController.setFinalCropInTransaction(finalClipRect);
- if (mDestroyPreservedSurfaceUponRedraw && mPendingDestroySurface != null) {
- mPendingDestroySurface.setFinalCropInTransaction(finalClipRect);
- }
- }
- }
-
- private int resolveStackClip() {
- // TODO
- /*// App animation overrides window animation stack clip mode.
- if (mAppAnimator != null && mAppAnimator.animation != null) {
- return mAppAnimator.getStackClip();
- } else {*/
- return STACK_CLIP_AFTER_ANIM;
- //}
- }
-
- private boolean shouldCropToStackBounds() {
- final WindowState w = mWin;
- final DisplayContent displayContent = w.getDisplayContent();
- if (displayContent != null && !displayContent.isDefaultDisplay) {
- // There are some windows that live on other displays while their app and main window
- // live on the default display (e.g. casting...). We don't want to crop this windows
- // to the stack bounds which is only currently supported on the default display.
- // TODO(multi-display): Need to support cropping to stack bounds on other displays
- // when we have stacks on other displays.
- return false;
- }
-
- final Task task = w.getTask();
- if (task == null || !task.cropWindowsToStackBounds()) {
- return false;
- }
-
- final int stackClip = resolveStackClip();
-
- // It's animating and we don't want to clip it to stack bounds during animation - abort.
- if (isAnimationSet() && stackClip == STACK_CLIP_NONE) {
- return false;
- }
- return true;
- }
-
- private void adjustCropToStackBounds(Rect clipRect,
- boolean isFreeformResizing) {
- final WindowState w = mWin;
-
- if (!shouldCropToStackBounds()) {
- return;
- }
-
- final TaskStack stack = w.getTask().mStack;
- stack.getDimBounds(mTmpStackBounds);
- final Rect surfaceInsets = w.getAttrs().surfaceInsets;
- // When we resize we use the big surface approach, which means we can't trust the
- // window frame bounds anymore. Instead, the window will be placed at 0, 0, but to avoid
- // hardcoding it, we use surface coordinates.
- final int frameX = isFreeformResizing ? (int) mSurfaceController.getX() :
- w.mFrame.left + mWin.mXOffset - surfaceInsets.left;
- final int frameY = isFreeformResizing ? (int) mSurfaceController.getY() :
- w.mFrame.top + mWin.mYOffset - surfaceInsets.top;
-
- // We need to do some acrobatics with surface position, because their clip region is
- // relative to the inside of the surface, but the stack bounds aren't.
- final WindowConfiguration winConfig = w.getWindowConfiguration();
- if (winConfig.hasWindowShadow() && !winConfig.canResizeTask()) {
- // The windows in this stack display drop shadows and the fill the entire stack
- // area. Adjust the stack bounds we will use to cropping take into account the
- // offsets we use to display the drop shadow so it doesn't get cropped.
- mTmpStackBounds.inset(-surfaceInsets.left, -surfaceInsets.top,
- -surfaceInsets.right, -surfaceInsets.bottom);
- }
-
- clipRect.left = Math.max(0,
- Math.max(mTmpStackBounds.left, frameX + clipRect.left) - frameX);
- clipRect.top = Math.max(0,
- Math.max(mTmpStackBounds.top, frameY + clipRect.top) - frameY);
- clipRect.right = Math.max(0,
- Math.min(mTmpStackBounds.right, frameX + clipRect.right) - frameX);
- clipRect.bottom = Math.max(0,
- Math.min(mTmpStackBounds.bottom, frameY + clipRect.bottom) - frameY);
}
void setSurfaceBoundariesLocked(final boolean recoveringMemory) {
@@ -1023,13 +889,10 @@
// updates until a resize occurs.
mService.markForSeamlessRotation(w, w.mSeamlesslyRotated && !mSurfaceResized);
- Rect clipRect = null, finalClipRect = null;
+ Rect clipRect = null;
if (calculateCrop(mTmpClipRect)) {
clipRect = mTmpClipRect;
}
- if (calculateFinalCrop(mTmpFinalClipRect)) {
- finalClipRect = mTmpFinalClipRect;
- }
float surfaceWidth = mSurfaceController.getWidth();
float surfaceHeight = mSurfaceController.getHeight();
@@ -1094,7 +957,6 @@
// Always clip to the stack bounds since the surface can be larger with the current
// scale
clipRect = null;
- finalClipRect = mTmpStackBounds;
} else {
// We want to calculate the scaling based on the content area, not based on
// the entire surface, so that we scale in sync with windows that don't have insets.
@@ -1105,7 +967,6 @@
// expose the whole window in buffer space, and not risk extending
// past where the system would have cropped us
clipRect = null;
- finalClipRect = null;
}
// In the case of ForceScaleToStack we scale entire tasks together,
@@ -1153,7 +1014,7 @@
}
if (!w.mSeamlesslyRotated) {
- applyCrop(clipRect, finalClipRect, recoveringMemory);
+ applyCrop(clipRect, recoveringMemory);
mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale * mExtraHScale,
mDtDx * w.mVScale * mExtraVScale,
mDtDy * w.mHScale * mExtraHScale,
@@ -1351,7 +1212,7 @@
mService.openSurfaceTransaction();
mSurfaceController.setPositionInTransaction(mWin.mFrame.left + left,
mWin.mFrame.top + top, false);
- applyCrop(null, null, false);
+ applyCrop(null, false);
} catch (RuntimeException e) {
Slog.w(TAG, "Error positioning surface of " + mWin
+ " pos=(" + left + "," + top + ")", e);