Fix some issues with updating the offsets of a window.

- Apply the correct crop rect at this point.
- Apply the correct position by taking into account the frame left/top.
- Don't directly apply the new values if the window is currently
  animating, since we need to go through the whole animation step
  to determine what the correct position is (taking into account
  any transformations).

Change-Id: I15d79354d9779867c49c7c0880faccdead7b021d
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index cba92f3..5516dea 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -935,6 +935,59 @@
         mDtDy = mWin.mGlobalScale;
     }
 
+    void updateSurfaceWindowCrop(final boolean recoveringMemory) {
+        final WindowState w = mWin;
+
+        // Need to recompute a new system decor rect each time.
+        if ((w.mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
+            // Currently can't do this cropping for scaled windows.  We'll
+            // just keep the crop rect the same as the source surface.
+            w.mSystemDecorRect.set(0, 0, w.mRequestedWidth, w.mRequestedHeight);
+        } else if (w.mLayer >= mService.mSystemDecorLayer) {
+            // Above the decor layer is easy, just use the entire window.
+            w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(),
+                    w.mCompatFrame.height());
+        } else {
+            final Rect decorRect = mService.mSystemDecorRect;
+            // Compute the offset of the window in relation to the decor rect.
+            final int offX = w.mXOffset + w.mFrame.left;
+            final int offY = w.mYOffset + w.mFrame.top;
+            // Initialize the decor rect to the entire frame.
+            w.mSystemDecorRect.set(0, 0, w.mFrame.width(), w.mFrame.height());
+            // Intersect with the decor rect, offsetted by window position.
+            w.mSystemDecorRect.intersect(decorRect.left-offX, decorRect.top-offY,
+                    decorRect.right-offX, decorRect.bottom-offY);
+            // If size compatibility is being applied to the window, the
+            // surface is scaled relative to the screen.  Also apply this
+            // scaling to the crop rect.  We aren't using the standard rect
+            // scale function because we want to round things to make the crop
+            // always round to a larger rect to ensure we don't crop too
+            // much and hide part of the window that should be seen.
+            if (w.mEnforceSizeCompat && w.mInvGlobalScale != 1.0f) {
+                final float scale = w.mInvGlobalScale;
+                w.mSystemDecorRect.left = (int) (w.mSystemDecorRect.left * scale - 0.5f);
+                w.mSystemDecorRect.top = (int) (w.mSystemDecorRect.top * scale - 0.5f);
+                w.mSystemDecorRect.right = (int) ((w.mSystemDecorRect.right+1) * scale - 0.5f);
+                w.mSystemDecorRect.bottom = (int) ((w.mSystemDecorRect.bottom+1) * scale - 0.5f);
+            }
+        }
+
+        if (!w.mSystemDecorRect.equals(w.mLastSystemDecorRect)) {
+            w.mLastSystemDecorRect.set(w.mSystemDecorRect);
+            try {
+                if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
+                        "CROP " + w.mSystemDecorRect.toShortString(), null);
+                mSurface.setWindowCrop(w.mSystemDecorRect);
+            } catch (RuntimeException e) {
+                Slog.w(TAG, "Error setting crop surface of " + w
+                        + " crop=" + w.mSystemDecorRect.toShortString(), e);
+                if (!recoveringMemory) {
+                    mService.reclaimSomeSurfaceMemoryLocked(this, "crop", true);
+                }
+            }
+        }
+    }
+
     void setSurfaceBoundaries(final boolean recoveringMemory) {
         final WindowState w = mWin;
         int width, height;
@@ -1003,54 +1056,7 @@
             }
         }
 
-        // Need to recompute a new system decor rect each time.
-        if ((w.mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
-            // Currently can't do this cropping for scaled windows.  We'll
-            // just keep the crop rect the same as the source surface.
-            w.mSystemDecorRect.set(0, 0, w.mRequestedWidth, w.mRequestedHeight);
-        } else if (w.mLayer >= mService.mSystemDecorLayer) {
-            // Above the decor layer is easy, just use the entire window.
-            w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(),
-                    w.mCompatFrame.height());
-        } else {
-            final Rect decorRect = mService.mSystemDecorRect;
-            // Compute the offset of the window in relation to the decor rect.
-            final int offX = w.mXOffset + w.mFrame.left;
-            final int offY = w.mYOffset + w.mFrame.top;
-            // Initialize the decor rect to the entire frame.
-            w.mSystemDecorRect.set(0, 0, w.mFrame.width(), w.mFrame.height());
-            // Intersect with the decor rect, offsetted by window position.
-            w.mSystemDecorRect.intersect(decorRect.left-offX, decorRect.top-offY,
-                    decorRect.right-offX, decorRect.bottom-offY);
-            // If size compatibility is being applied to the window, the
-            // surface is scaled relative to the screen.  Also apply this
-            // scaling to the crop rect.  We aren't using the standard rect
-            // scale function because we want to round things to make the crop
-            // always round to a larger rect to ensure we don't crop too
-            // much and hide part of the window that should be seen.
-            if (w.mEnforceSizeCompat && w.mInvGlobalScale != 1.0f) {
-                final float scale = w.mInvGlobalScale;
-                w.mSystemDecorRect.left = (int) (w.mSystemDecorRect.left * scale - 0.5f);
-                w.mSystemDecorRect.top = (int) (w.mSystemDecorRect.top * scale - 0.5f);
-                w.mSystemDecorRect.right = (int) ((w.mSystemDecorRect.right+1) * scale - 0.5f);
-                w.mSystemDecorRect.bottom = (int) ((w.mSystemDecorRect.bottom+1) * scale - 0.5f);
-            }
-        }
-
-        if (!w.mSystemDecorRect.equals(w.mLastSystemDecorRect)) {
-            w.mLastSystemDecorRect.set(w.mSystemDecorRect);
-            try {
-                if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
-                        "CROP " + w.mSystemDecorRect.toShortString(), null);
-                mSurface.setWindowCrop(w.mSystemDecorRect);
-            } catch (RuntimeException e) {
-                Slog.w(TAG, "Error setting crop surface of " + w
-                        + " crop=" + w.mSystemDecorRect.toShortString(), e);
-                if (!recoveringMemory) {
-                    mService.reclaimSomeSurfaceMemoryLocked(this, "crop", true);
-                }
-            }
-        }
+        updateSurfaceWindowCrop(recoveringMemory);
     }
 
     public void prepareSurfaceLocked(final boolean recoveringMemory) {
@@ -1181,17 +1187,31 @@
     }
 
     void setWallpaperOffset(int left, int top) {
+        mSurfaceX = left;
+        mSurfaceY = top;
+        if (mAnimating) {
+            // If this window (or its app token) is animating, then the position
+            // of the surface will be re-computed on the next animation frame.
+            // We can't poke it directly here because it depends on whatever
+            // transformation is being applied by the animation.
+            return;
+        }
+        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+                ">>> OPEN TRANSACTION setWallpaperOffset");
         Surface.openTransaction();
         try {
-            mSurfaceX = left;
-            mSurfaceY = top;
-            mSurface.setPosition(left, top);
-            mSurface.setWindowCrop(null);
+            if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin,
+                    "POS " + left + ", " + top, null);
+            mSurface.setPosition(mWin.mFrame.left + left, mWin.mFrame.top + top);
+            updateSurfaceWindowCrop(false);
         } catch (RuntimeException e) {
             Slog.w(TAG, "Error positioning surface of " + mWin
                     + " pos=(" + left + "," + top + ")", e);
+        } finally {
+            Surface.closeTransaction();
+            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+                    "<<< CLOSE TRANSACTION setWallpaperOffset");
         }
-        Surface.closeTransaction();
     }
 
     // This must be called while inside a transaction.