Fixes for ending PiP animation.

During the PiP animation, we have two basic requirements:
   1. We need to scale windows to the pinned stack bounds.
   2. We need to halt resize and movement notifications to the client.
As we end the animation, we need to disable these states at differing
times. First we need to deliver a final resize and movement notification
to the client for it's new position. However, Surfaces may not
immediately resize (in particular in the case of child windows,
it may be some time!), furthermore Surfaces may resize at different
times so we need to persist scaling on a Surface by Surface
basis after reenabling resize notifications.

Bug: 28559097
Change-Id: I6d52a3e213e08a34f4c0eea892b2a84cd4c20e18
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 8a92b54..1381ddb 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -702,6 +702,14 @@
         public static boolean windowsAreScaleable(int stackId) {
             return stackId == PINNED_STACK_ID;
         }
+
+        /**
+         * Returns true if windows in this stack should be given move animations
+         * by default.
+         */
+        public static boolean hasMovementAnimations(int stackId) {
+            return stackId != PINNED_STACK_ID;
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index 51c4045..5bfece4 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -156,12 +156,10 @@
                     + mTmpRect + " from=" + mFrom + " mTo=" + mTo + " value=" + value
                     + " remains=" + remains);
 
-            if (remains != 0) {
-                mTmpTaskBounds.set(mTmpRect.left, mTmpRect.top,
-                        mTmpRect.left + mFrozenTaskWidth, mTmpRect.top + mFrozenTaskHeight);
-            }
+            mTmpTaskBounds.set(mTmpRect.left, mTmpRect.top,
+                    mTmpRect.left + mFrozenTaskWidth, mTmpRect.top + mFrozenTaskHeight);
 
-            if (!mTarget.setPinnedStackSize(mTmpRect, remains != 0 ? mTmpTaskBounds : null)) {
+            if (!mTarget.setPinnedStackSize(mTmpRect, mTmpTaskBounds)) {
                 // Whoops, the target doesn't feel like animating anymore. Let's immediately finish
                 // any further animation.
                 animation.cancel();
@@ -205,11 +203,12 @@
                 return;
             }
 
+            finishAnimation();
+
+            mTarget.setPinnedStackSize(mTo, null);
             if (mMoveToFullScreen && !mWillReplace) {
                 mTarget.moveToFullscreen();
             }
-
-            finishAnimation();
         }
 
         @Override
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index eb8c1dc..f51fd8a 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -130,12 +130,6 @@
     // certain logic we would otherwise apply while resizing,
     // while resizing in the bounds animating mode.
     private boolean mBoundsAnimating = false;
-    // By default, movement animations are applied to all
-    // window movement. If this is true, animations will not
-    // be applied within this stack. This is useful for example
-    // if the windows are moving as the result of a stack animation,
-    // in which case a second window animation would cause jitter.
-    private boolean mFreezeMovementAnimations = false;
 
     // Temporary storage for the new bounds that should be used after the configuration change.
     // Will be cleared once the client retrieves the new bounds via getBoundsForNewConfiguration().
@@ -1361,7 +1355,6 @@
     @Override  // AnimatesBounds
     public void onAnimationStart() {
         synchronized (mService.mWindowMap) {
-            mFreezeMovementAnimations = true;
             mBoundsAnimating = true;
         }
     }
@@ -1369,7 +1362,6 @@
     @Override  // AnimatesBounds
     public void onAnimationEnd() {
         synchronized (mService.mWindowMap) {
-            mFreezeMovementAnimations = false;
             mBoundsAnimating = false;
             mService.requestTraversal();
         }
@@ -1396,8 +1388,8 @@
         getDisplayContent().getContentRect(bounds);
     }
 
-    public boolean getFreezeMovementAnimations() {
-        return mFreezeMovementAnimations;
+    public boolean hasMovementAnimations() {
+        return StackId.hasMovementAnimations(mStackId);
     }
 
     public boolean getForceScaleToCrop() {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index f7fc005..c92d325 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -229,6 +229,8 @@
     long mDeferTransactionUntilFrame = -1;
     long mDeferTransactionTime = -1;
 
+    boolean mForceScaleUntilResize;
+
     private final Rect mTmpSize = new Rect();
 
     WindowStateAnimator(final WindowState win) {
@@ -1416,8 +1418,13 @@
         float extraHScale = (float) 1.0;
         float extraVScale = (float) 1.0;
 
+        mSurfaceResized = mSurfaceController.setSizeInTransaction(
+                mTmpSize.width(), mTmpSize.height(), recoveringMemory);
+        mForceScaleUntilResize = mForceScaleUntilResize && !mSurfaceResized;
+
+
         calculateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect);
-        if (task != null && task.mStack.getForceScaleToCrop()) {
+        if ((task != null && task.mStack.getForceScaleToCrop()) || mForceScaleUntilResize) {
             int hInsets = w.getAttrs().surfaceInsets.left + w.getAttrs().surfaceInsets.right;
             int vInsets = w.getAttrs().surfaceInsets.top + w.getAttrs().surfaceInsets.bottom;
             // We want to calculate the scaling based on the content area, not based on
@@ -1447,6 +1454,14 @@
             // past where the system would have cropped us
             mTmpClipRect.set(0, 0, mTmpSize.width(), mTmpSize.height());
             mTmpFinalClipRect.setEmpty();
+
+            // Various surfaces in the scaled stack may resize at different times.
+            // We need to ensure for each surface, that we disable transformation matrix
+            // scaling in the same transaction which we resize the surface in.
+            // As we are in SCALING_MODE_SCALE_TO_WINDOW, SurfaceFlinger will
+            // then take over the scaling until the new buffer arrives, and things 
+            // will be seamless.
+            mForceScaleUntilResize = true;
         } else {
             mSurfaceController.setPositionInTransaction(mTmpSize.left, mTmpSize.top,
                     recoveringMemory);
@@ -1458,8 +1473,6 @@
                 mDtDx * w.mVScale * extraVScale,
                 mDsDy * w.mHScale * extraHScale,
                 mDtDy * w.mVScale * extraVScale, recoveringMemory);
-        mSurfaceResized = mSurfaceController.setSizeInTransaction(
-                mTmpSize.width(), mTmpSize.height(), recoveringMemory);
 
         if (mSurfaceResized) {
             mReportSurfaceResized = true;
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 7e9993d..308b24d 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -719,7 +719,7 @@
                                     || task.mStack.isAdjustedForIme());
                     if ((w.mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0
                             && !w.isDragResizing() && !adjustedForMinimizedDockOrIme
-                            && (task == null || !w.getTask().mStack.getFreezeMovementAnimations())
+                            && (task == null || w.getTask().mStack.hasMovementAnimations())
                             && !w.mWinAnimator.mLastHidden) {
                         winAnimator.setMoveAnimation(left, top);
                     }
@@ -731,7 +731,9 @@
                     }
 
                     try {
-                        w.mClient.moved(left, top);
+                        if (task == null || task.mStack.getBoundsAnimating()) {
+                            w.mClient.moved(left, top);
+                        }
                     } catch (RemoteException e) {
                     }
                     w.mMovedByResize = false;