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
This commit is contained in:
chaviw
2017-12-20 15:29:04 -08:00
committed by Jorim Jaggi
parent 619c9f7c5c
commit 2301211526
5 changed files with 44 additions and 156 deletions

View File

@@ -86,12 +86,10 @@ class AppWindowThumbnail implements Animatable {
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() {

View File

@@ -222,6 +222,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
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 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
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 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
startAnimation(getPendingTransaction(), adapter, !isVisible());
mTransit = transit;
mTransitFlags = mService.mAppTransition.getTransitFlags();
// TODO: Skip first frame and app stack clip mode.
}
} else {
cancelAnimation();

View File

@@ -320,7 +320,7 @@ public class TaskStack extends WindowContainer<Task> implements
if (matchParentBounds()
|| !inSplitScreenSecondaryWindowingMode()
|| mDisplayContent == null
|| mDisplayContent.getSplitScreenPrimaryStack() != null) {
|| mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility() != null) {
return true;
}
return false;

View File

@@ -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 @@ public class WindowAnimationSpec implements AnimationSpec {
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 @@ public class WindowAnimationSpec implements AnimationSpec {
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

View File

@@ -45,7 +45,6 @@ import static com.android.server.wm.WindowSurfacePlacer.SET_TURN_ON_SCREEN;
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;
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;
@@ -768,47 +766,6 @@ class WindowStateAnimator {
mDsDy = mWin.mGlobalScale;
}
/**
* 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 @@ class WindowStateAnimator {
// 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 @@ class WindowStateAnimator {
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 @@ class WindowStateAnimator {
} 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 @@ class WindowStateAnimator {
// 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 @@ class WindowStateAnimator {
// 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 @@ class WindowStateAnimator {
// 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 @@ class WindowStateAnimator {
}
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 @@ class WindowStateAnimator {
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);