Don't move multi-window stacks on orientation change.

Change allows resized stacks to remain in the same location
while their content change orientation.

Bug: 19358195
Change-Id: I5a9898c1cf85cb5c4c2eab0f4969b339defb199a
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 8bbc5a9..ba8bd4d 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -340,6 +340,12 @@
         }
     }
 
+    static int deltaRotation(int oldRotation, int newRotation) {
+        int delta = newRotation - oldRotation;
+        if (delta < 0) delta += 4;
+        return delta;
+    }
+
     public void dump(String prefix, PrintWriter pw) {
         pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
         final String subPrefix = "  " + prefix;
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index f79896b..7dd716e 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -291,12 +291,6 @@
         return mSurfaceControl != null;
     }
 
-    static int deltaRotation(int oldRotation, int newRotation) {
-        int delta = newRotation - oldRotation;
-        if (delta < 0) delta += 4;
-        return delta;
-    }
-
     private void setSnapshotTransformInTransaction(Matrix matrix, float alpha) {
         if (mSurfaceControl != null) {
             matrix.getValues(mTmpFloats);
@@ -352,7 +346,7 @@
         // Compute the transformation matrix that must be applied
         // to the snapshot to make it stay in the same original position
         // with the current screen rotation.
-        int delta = deltaRotation(rotation, Surface.ROTATION_0);
+        int delta = DisplayContent.deltaRotation(rotation, Surface.ROTATION_0);
         createRotationMatrix(delta, mWidth, mHeight, mSnapshotInitialMatrix);
 
         if (DEBUG_STATE) Slog.v(TAG, "**** ROTATION: " + delta);
@@ -391,7 +385,7 @@
         boolean firstStart = false;
 
         // Figure out how the screen has moved from the original rotation.
-        int delta = deltaRotation(mCurRotation, mOriginalRotation);
+        int delta = DisplayContent.deltaRotation(mCurRotation, mOriginalRotation);
 
         if (TWO_PHASE_ANIMATION && mFinishExitAnimation == null
                 && (!dismissing || delta != Surface.ROTATION_0)) {
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index c677e2c..1283283 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -26,6 +26,8 @@
 import android.util.EventLog;
 import android.util.Slog;
 import android.util.TypedValue;
+import android.view.Display;
+import android.view.Surface;
 
 import com.android.server.EventLogTags;
 
@@ -52,6 +54,8 @@
 
     /** For comparison with DisplayContent bounds. */
     private Rect mTmpRect = new Rect();
+    /** For handling display rotations. */
+    private Rect mTmpRect2 = new Rect();
 
     /** Content limits relative to the DisplayContent this sits in. */
     private Rect mBounds = new Rect();
@@ -94,6 +98,9 @@
     // the status bar.
     boolean mUnderStatusBar;
 
+    // Device rotation as of the last time {@link #mBounds} was set.
+    int mRotation;
+
     TaskStack(WindowManagerService service, int stackId) {
         mService = service;
         mStackId = stackId;
@@ -135,8 +142,10 @@
     /** Set the stack bounds. Passing in null sets the bounds to fullscreen. */
     boolean setBounds(Rect bounds) {
         boolean oldFullscreen = mFullscreen;
+        int rotation = Surface.ROTATION_0;
         if (mDisplayContent != null) {
             mDisplayContent.getLogicalDisplayRect(mTmpRect);
+            rotation = mDisplayContent.getDisplayInfo().rotation;
             if (bounds == null) {
                 bounds = mTmpRect;
                 mFullscreen = true;
@@ -147,10 +156,10 @@
         }
 
         if (bounds == null) {
-            // Can set to fullscreen if we don't have a display to get bounds from...
+            // Can't set to fullscreen if we don't have a display to get bounds from...
             return false;
         }
-        if (mBounds.equals(bounds) && oldFullscreen == mFullscreen) {
+        if (mBounds.equals(bounds) && oldFullscreen == mFullscreen && mRotation == rotation) {
             return false;
         }
 
@@ -158,6 +167,7 @@
         mAnimationBackgroundSurface.setBounds(bounds);
         mBounds.set(bounds);
         mUnderStatusBar = (mBounds.top == 0);
+        mRotation = rotation;
         updateOverrideConfiguration();
         return true;
     }
@@ -191,9 +201,42 @@
     }
 
     void updateDisplayInfo() {
-        if (mFullscreen && mDisplayContent != null) {
+        if (mFullscreen) {
+            setBounds(null);
+        } else if (mDisplayContent != null) {
+            final int newRotation = mDisplayContent.getDisplayInfo().rotation;
+            if (mRotation == newRotation) {
+                return;
+            }
+
+            // Device rotation changed. We don't want the stack to move around on the screen when
+            // this happens, so update the stack bounds so it stays in the same place.
+            final int rotationDelta = DisplayContent.deltaRotation(mRotation, newRotation);
             mDisplayContent.getLogicalDisplayRect(mTmpRect);
-            setBounds(mTmpRect);
+            switch (rotationDelta) {
+                case Surface.ROTATION_0:
+                    mTmpRect2.set(mBounds);
+                    break;
+                case Surface.ROTATION_90:
+                    mTmpRect2.top = mTmpRect.bottom - mBounds.right;
+                    mTmpRect2.left = mBounds.top;
+                    mTmpRect2.right = mTmpRect2.left + mBounds.height();
+                    mTmpRect2.bottom = mTmpRect2.top + mBounds.width();
+                    break;
+                case Surface.ROTATION_180:
+                    mTmpRect2.top = mTmpRect.bottom - mBounds.bottom;
+                    mTmpRect2.left = mTmpRect.right - mBounds.right;
+                    mTmpRect2.right = mTmpRect2.left + mBounds.width();
+                    mTmpRect2.bottom = mTmpRect2.top + mBounds.height();
+                    break;
+                case Surface.ROTATION_270:
+                    mTmpRect2.top = mBounds.left;
+                    mTmpRect2.left = mTmpRect.right - mBounds.bottom;
+                    mTmpRect2.right = mTmpRect2.left + mBounds.height();
+                    mTmpRect2.bottom = mTmpRect2.top + mBounds.width();
+                    break;
+            }
+            setBounds(mTmpRect2);
         }
     }