Merge "Coordinate configuration changes and window frame size." into oc-dev
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 88c1627..417a95f 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -16,10 +16,7 @@
 
 package android.content.res;
 
-import android.graphics.Point;
 import android.graphics.Rect;
-import android.util.DisplayMetrics;
-import android.view.Display;
 import android.view.DisplayInfo;
 import com.android.internal.util.XmlUtils;
 
@@ -45,6 +42,12 @@
 import java.util.ArrayList;
 import java.util.Locale;
 
+import static android.view.Surface.ROTATION_UNDEFINED;
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_90;
+import static android.view.Surface.ROTATION_180;
+import static android.view.Surface.ROTATION_270;
+
 /**
  * This class describes all device configuration information that can
  * impact the resources the application retrieves.  This includes both
@@ -600,6 +603,13 @@
      */
     public int orientation;
 
+    /**
+     * The rotation used at the time orientation was determined.
+     * TODO(b/36812336): Move rotation out of {@link Configuration}.
+     * {@hide}
+     */
+    private int rotation;
+
     /** Constant for {@link #uiMode}: bits that encode the mode type. */
     public static final int UI_MODE_TYPE_MASK = 0x0f;
     /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
@@ -887,6 +897,7 @@
         navigation = o.navigation;
         navigationHidden = o.navigationHidden;
         orientation = o.orientation;
+        rotation = o.rotation;
         screenLayout = o.screenLayout;
         colorMode = o.colorMode;
         uiMode = o.uiMode;
@@ -990,6 +1001,14 @@
             case ORIENTATION_PORTRAIT: sb.append(" port"); break;
             default: sb.append(" orien="); sb.append(orientation); break;
         }
+        switch (rotation) {
+            case ROTATION_UNDEFINED: sb.append(" ?rotation"); break;
+            case ROTATION_0: sb.append(" rot0"); break;
+            case ROTATION_90: sb.append(" rot90"); break;
+            case ROTATION_180: sb.append(" rot180"); break;
+            case ROTATION_270: sb.append(" rot270"); break;
+            default: sb.append(" rot="); sb.append(rotation); break;
+        }
         switch ((uiMode&UI_MODE_TYPE_MASK)) {
             case UI_MODE_TYPE_UNDEFINED: sb.append(" ?uimode"); break;
             case UI_MODE_TYPE_NORMAL: /* normal is not interesting to print */ break;
@@ -1077,6 +1096,7 @@
         navigation = NAVIGATION_UNDEFINED;
         navigationHidden = NAVIGATIONHIDDEN_UNDEFINED;
         orientation = ORIENTATION_UNDEFINED;
+        rotation = ROTATION_UNDEFINED;
         screenLayout = SCREENLAYOUT_UNDEFINED;
         colorMode = COLOR_MODE_UNDEFINED;
         uiMode = UI_MODE_TYPE_UNDEFINED;
@@ -1185,6 +1205,11 @@
             changed |= ActivityInfo.CONFIG_ORIENTATION;
             orientation = delta.orientation;
         }
+        if (delta.rotation != ROTATION_UNDEFINED
+                && rotation != delta.rotation) {
+            changed |= ActivityInfo.CONFIG_ORIENTATION;
+            rotation = delta.rotation;
+        }
 
         if (((delta.screenLayout & SCREENLAYOUT_SIZE_MASK) != SCREENLAYOUT_SIZE_UNDEFINED)
                 && (delta.screenLayout & SCREENLAYOUT_SIZE_MASK)
@@ -1379,6 +1404,10 @@
                 && orientation != delta.orientation) {
             changed |= ActivityInfo.CONFIG_ORIENTATION;
         }
+        if ((compareUndefined || delta.rotation != ROTATION_UNDEFINED)
+                && rotation != delta.rotation) {
+            changed |= ActivityInfo.CONFIG_ORIENTATION;
+        }
         if ((compareUndefined || getScreenLayoutNoDirection(delta.screenLayout) !=
                 (SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED))
                 && getScreenLayoutNoDirection(screenLayout) !=
@@ -1515,6 +1544,7 @@
         dest.writeInt(navigation);
         dest.writeInt(navigationHidden);
         dest.writeInt(orientation);
+        dest.writeInt(rotation);
         dest.writeInt(screenLayout);
         dest.writeInt(colorMode);
         dest.writeInt(uiMode);
@@ -1551,6 +1581,7 @@
         navigation = source.readInt();
         navigationHidden = source.readInt();
         orientation = source.readInt();
+        rotation = source.readInt();
         screenLayout = source.readInt();
         colorMode = source.readInt();
         uiMode = source.readInt();
@@ -1635,6 +1666,8 @@
         if (n != 0) return n;
         n = this.orientation - that.orientation;
         if (n != 0) return n;
+        n = this.rotation - that.rotation;
+        if (n != 0) return n;
         n = this.colorMode - that.colorMode;
         if (n != 0) return n;
         n = this.screenLayout - that.screenLayout;
@@ -1766,6 +1799,24 @@
     /**
      * @hide
      *
+     * Setter for orientation converts from {@link Surface} values to internal representation.
+     */
+    public void setRotation(int rotation) {
+        this.rotation = rotation;
+    }
+
+    /**
+     * @hide
+     *
+     * Getter for orientation. Converts from internal representation to  {@link Surface} values.
+     */
+    public int getRotation() {
+        return rotation != ROTATION_UNDEFINED ? rotation : ROTATION_0;
+    }
+
+    /**
+     * @hide
+     *
      * Clears the locale without changing layout direction.
      */
     public void clearLocales() {
@@ -2000,6 +2051,23 @@
                 break;
         }
 
+        switch (config.rotation) {
+            case ROTATION_0:
+                parts.add("rot0");
+                break;
+            case ROTATION_90:
+                parts.add("rot90");
+                break;
+            case ROTATION_180:
+                parts.add("rot180");
+                break;
+            case ROTATION_270:
+                parts.add("rot270");
+                break;
+            default:
+                break;
+        }
+
         switch (config.uiMode & Configuration.UI_MODE_TYPE_MASK) {
             case Configuration.UI_MODE_TYPE_APPLIANCE:
                 parts.add("appliance");
@@ -2194,6 +2262,10 @@
             delta.orientation = change.orientation;
         }
 
+        if (base.rotation != change.rotation) {
+            base.rotation = change.rotation;
+        }
+
         if ((base.screenLayout & SCREENLAYOUT_SIZE_MASK) !=
                 (change.screenLayout & SCREENLAYOUT_SIZE_MASK)) {
             delta.screenLayout |= change.screenLayout & SCREENLAYOUT_SIZE_MASK;
@@ -2265,6 +2337,7 @@
     private static final String XML_ATTR_NAVIGATION = "nav";
     private static final String XML_ATTR_NAVIGATION_HIDDEN = "navHid";
     private static final String XML_ATTR_ORIENTATION = "ori";
+    private static final String XML_ATTR_ROTATION = "rot";
     private static final String XML_ATTR_SCREEN_LAYOUT = "scrLay";
     private static final String XML_ATTR_COLOR_MODE = "clrMod";
     private static final String XML_ATTR_UI_MODE = "ui";
@@ -2324,6 +2397,8 @@
                 DENSITY_DPI_UNDEFINED);
         configOut.appBounds =
             Rect.unflattenFromString(XmlUtils.readStringAttribute(parser, XML_ATTR_APP_BOUNDS));
+        configOut.rotation = XmlUtils.readIntAttribute(parser, XML_ATTR_ROTATION,
+                ROTATION_UNDEFINED);
 
         // For persistence, we don't care about assetsSeq, so do not read it out.
     }
@@ -2400,6 +2475,10 @@
                 config.appBounds.flattenToString());
         }
 
+        if (config.rotation != ROTATION_UNDEFINED) {
+            XmlUtils.writeIntAttribute(xml, XML_ATTR_ROTATION, config.rotation);
+        }
+
         // For persistence, we do not care about assetsSeq, so do not write it out.
     }
 }
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 51d6514..286e790 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -96,7 +96,7 @@
             int flags, out Rect outFrame, out Rect outOverscanInsets,
             out Rect outContentInsets, out Rect outVisibleInsets, out Rect outStableInsets,
             out Rect outOutsets, out Rect outBackdropFrame,
-            out MergedConfiguration outMergedConfiguration, out Surface outSurface);
+            inout MergedConfiguration mergedConfiguration, out Surface outSurface);
 
     /*
      * Notify the window manager that an application is relaunching and
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 8bb3fa9..0ad591b 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -129,11 +129,17 @@
     public static final int SCALING_MODE_NO_SCALE_CROP = 3;
 
     /** @hide */
-    @IntDef({ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270})
+    @IntDef({ROTATION_UNDEFINED, ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270})
     @Retention(RetentionPolicy.SOURCE)
     public @interface Rotation {}
 
     /**
+     * Rotation constant: undefined
+     * @hide
+     */
+    public static final int ROTATION_UNDEFINED = -1;
+
+    /**
      * Rotation constant: 0 degree rotation (natural orientation)
      */
     public static final int ROTATION_0 = 0;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 2605b4a..19e0c95 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1845,8 +1845,12 @@
 
         final boolean isViewVisible = viewVisibility == View.VISIBLE;
         final boolean windowRelayoutWasForced = mForceNextWindowRelayout;
-        if (mFirst || windowShouldResize || insetsChanged ||
-                viewVisibilityChanged || params != null || mForceNextWindowRelayout) {
+        final int contextConfigSeq = mContext.getResources().getConfiguration().seq;
+        final int lastConfigSeq = mLastReportedMergedConfiguration.getMergedConfiguration().seq;
+        final boolean staleConfig = lastConfigSeq != 0 && contextConfigSeq != lastConfigSeq;
+
+        if (mFirst || windowShouldResize || insetsChanged || staleConfig || viewVisibilityChanged
+                || params != null || mForceNextWindowRelayout) {
             mForceNextWindowRelayout = false;
 
             if (isViewVisible) {
@@ -6083,7 +6087,13 @@
         if (params != null) {
             if (DBG) Log.d(mTag, "WindowLayout in layoutWindow:" + params);
         }
-        mPendingMergedConfiguration.getMergedConfiguration().seq = 0;
+
+        if (mPendingMergedConfiguration.getMergedConfiguration().seq == 0) {
+            mPendingMergedConfiguration.setTo(mLastReportedMergedConfiguration);
+        }
+
+        int initialConfigSeq = mPendingMergedConfiguration.getMergedConfiguration().seq;
+
         //Log.d(mTag, ">>>>>> CALLING relayout");
         if (params != null && mOrigWindowType != params.type) {
             // For compatibility with old apps, don't crash here.
@@ -6102,6 +6112,10 @@
                 mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame,
                 mPendingMergedConfiguration, mSurface);
 
+        if (initialConfigSeq == mPendingMergedConfiguration.getMergedConfiguration().seq) {
+            mPendingMergedConfiguration.getMergedConfiguration().seq = 0;
+        }
+
         mPendingAlwaysConsumeNavBar =
                 (relayoutResult & WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR) != 0;
 
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b5476d7..eef4c9b 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1162,6 +1162,8 @@
         final int dh = displayInfo.logicalHeight;
         config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
                 Configuration.ORIENTATION_LANDSCAPE;
+        config.setRotation(displayInfo.rotation);
+
         config.screenWidthDp =
                 (int)(mService.mPolicy.getConfigDisplayWidth(dw, dh, displayInfo.rotation,
                         config.uiMode, mDisplayId) / mDisplayMetrics.density);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index f74948f..1d08c2e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2231,15 +2231,14 @@
             mWinAnimator.applyEnterAnimationLocked();
         }
 
-        if (isConfigChanged()) {
-            final Configuration globalConfig = mService.mRoot.getConfiguration();
-            final Configuration overrideConfig = getMergedOverrideConfiguration();
-            mergedConfiguration.setConfiguration(globalConfig, overrideConfig);
-            if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + this
-                    + " visible with new global config: " + globalConfig
-                    + " merged override config: " + overrideConfig);
-            mLastReportedConfiguration.setTo(getConfiguration());
-        }
+        // always report back the new configuration
+        final Configuration globalConfig = mService.mRoot.getConfiguration();
+        final Configuration overrideConfig = getMergedOverrideConfiguration();
+        mergedConfiguration.setConfiguration(globalConfig, overrideConfig);
+        if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + this
+                + " reporting new global config: " + globalConfig
+                + " merged override config: " + overrideConfig);
+        mLastReportedConfiguration.setTo(getConfiguration());
     }
 
     void adjustStartingWindowFlags() {