Fix issue #2519590: Lock screen stuck in landscape mode

Well, mostly.  There is still a problem here where the first time
you show the lock screen it just doesn't draw itself.  I assume
this is something breaking in the view hierarchy as it floounders
around removing and adding new views as it is first being shown...
but no idea at this point what is the actual case.

Change-Id: Iba99ae3242931c8673b17b106c86fc99e2c52abe
diff --git a/api/current.xml b/api/current.xml
index 8a9e4ce..e982dfcb 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -47612,6 +47612,32 @@
 <parameter name="interestingChanges" type="int">
 </parameter>
 </method>
+<method name="readFromParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="android.os.Parcel">
+</parameter>
+</method>
+<method name="setTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="o" type="android.content.res.Configuration">
+</parameter>
+</method>
 <method name="setToDefaults"
  return="void"
  abstract="false"
@@ -121947,7 +121973,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="text" type="java.lang.String">
+<parameter name="message" type="java.lang.String">
 </parameter>
 </method>
 </class>
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 35d1948..1c980e3 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3913,6 +3913,8 @@
             mResConfiguration = new Configuration();
         }
         if (!mResConfiguration.isOtherSeqNewer(config)) {
+            if (DEBUG_CONFIGURATION) Log.v(TAG, "Skipping new config: curSeq="
+                    + mResConfiguration.seq + ", newSeq=" + config.seq);
             return;
         }
         mResConfiguration.updateFrom(config);
@@ -3936,6 +3938,8 @@
             WeakReference<Resources> v = it.next();
             Resources r = v.get();
             if (r != null) {
+                if (DEBUG_CONFIGURATION) Log.v(TAG, "Changing resources "
+                        + r + " config to: " + config);
                 r.updateConfiguration(config, dm);
                 //Log.i(TAG, "Updated app resources " + v.getKey()
                 //        + " " + r + ": " + r.getConfiguration());
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 6598264..1a0c867 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -219,6 +219,10 @@
      * Makes a deep copy suitable for modification.
      */
     public Configuration(Configuration o) {
+        setTo(o);
+    }
+
+    public void setTo(Configuration o) {
         fontScale = o.fontScale;
         mcc = o.mcc;
         mnc = o.mnc;
@@ -237,7 +241,7 @@
         uiMode = o.uiMode;
         seq = o.seq;
     }
-
+    
     public String toString() {
         StringBuilder sb = new StringBuilder(128);
         sb.append("{ scale=");
@@ -552,21 +556,7 @@
         dest.writeInt(seq);
     }
 
-    public static final Parcelable.Creator<Configuration> CREATOR
-            = new Parcelable.Creator<Configuration>() {
-        public Configuration createFromParcel(Parcel source) {
-            return new Configuration(source);
-        }
-
-        public Configuration[] newArray(int size) {
-            return new Configuration[size];
-        }
-    };
-
-    /**
-     * Construct this Configuration object, reading from the Parcel.
-     */
-    private Configuration(Parcel source) {
+    public void readFromParcel(Parcel source) {
         fontScale = source.readFloat();
         mcc = source.readInt();
         mnc = source.readInt();
@@ -586,6 +576,24 @@
         uiMode = source.readInt();
         seq = source.readInt();
     }
+    
+    public static final Parcelable.Creator<Configuration> CREATOR
+            = new Parcelable.Creator<Configuration>() {
+        public Configuration createFromParcel(Parcel source) {
+            return new Configuration(source);
+        }
+
+        public Configuration[] newArray(int size) {
+            return new Configuration[size];
+        }
+    };
+
+    /**
+     * Construct this Configuration object, reading from the Parcel.
+     */
+    private Configuration(Parcel source) {
+        readFromParcel(source);
+    }
 
     public int compareTo(Configuration that) {
         int n;
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 444135a..f47a8d0 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -141,6 +141,7 @@
         final Rect mVisibleInsets = new Rect();
         final Rect mWinFrame = new Rect();
         final Rect mContentInsets = new Rect();
+        final Configuration mConfiguration = new Configuration();
         
         final WindowManager.LayoutParams mLayout
                 = new WindowManager.LayoutParams();
@@ -494,7 +495,7 @@
                     final int relayoutResult = mSession.relayout(
                         mWindow, mLayout, mWidth, mHeight,
                             View.VISIBLE, false, mWinFrame, mContentInsets,
-                            mVisibleInsets, mSurfaceHolder.mSurface);
+                            mVisibleInsets, mConfiguration, mSurfaceHolder.mSurface);
 
                     if (DEBUG) Log.v(TAG, "New surface: " + mSurfaceHolder.mSurface
                             + ", frame=" + mWinFrame);
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index b6b009b..01f07d6 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -17,6 +17,7 @@
 
 package android.view;
 
+import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.os.Bundle;
@@ -63,6 +64,9 @@
      * contents to make sure the user can see it.  This is different than
      * <var>outContentInsets</var> in that these insets change transiently,
      * so complex relayout of the window should not happen based on them.
+     * @param outConfiguration New configuration of window, if it is now
+     * becoming visible and the global configuration has changed since it
+     * was last displayed.
      * @param outSurface Object in which is placed the new display surface.
      * 
      * @return int Result flags: {@link WindowManagerImpl#RELAYOUT_SHOW_FOCUS},
@@ -71,7 +75,8 @@
     int relayout(IWindow window, in WindowManager.LayoutParams attrs,
             int requestedWidth, int requestedHeight, int viewVisibility,
             boolean insetsPending, out Rect outFrame, out Rect outContentInsets,
-            out Rect outVisibleInsets, out Surface outSurface);
+            out Rect outVisibleInsets, out Configuration outConfig,
+            out Surface outSurface);
 
     /**
      * Give the window manager a hint of the part of the window that is
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 0722699..d8010bc 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -39,7 +39,6 @@
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.concurrent.locks.ReentrantLock;
-import java.lang.ref.WeakReference;
 
 /**
  * Provides a dedicated drawing surface embedded inside of a view hierarchy.
@@ -102,7 +101,8 @@
     final Rect mVisibleInsets = new Rect();
     final Rect mWinFrame = new Rect();
     final Rect mContentInsets = new Rect();
-
+    final Configuration mConfiguration = new Configuration();
+    
     static final int KEEP_SCREEN_ON_MSG = 1;
     static final int GET_NEW_SURFACE_MSG = 2;
     
@@ -428,7 +428,7 @@
                 final int relayoutResult = mSession.relayout(
                     mWindow, mLayout, mWidth, mHeight,
                         visible ? VISIBLE : GONE, false, mWinFrame, mContentInsets,
-                        mVisibleInsets, mSurface);
+                        mVisibleInsets, mConfiguration, mSurface);
 
                 if (localLOGV) Log.i(TAG, "New surface: " + mSurface
                         + ", vis=" + visible + ", frame=" + mWinFrame);
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 484922d..c87ffee 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -80,6 +80,7 @@
     private static final boolean DEBUG_ORIENTATION = false || LOCAL_LOGV;
     private static final boolean DEBUG_TRACKBALL = false || LOCAL_LOGV;
     private static final boolean DEBUG_IMF = false || LOCAL_LOGV;
+    private static final boolean DEBUG_CONFIGURATION = false || LOCAL_LOGV;
     private static final boolean WATCH_POINTER = false;
 
     private static final boolean MEASURE_LATENCY = false;
@@ -176,6 +177,9 @@
     final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets
             = new ViewTreeObserver.InternalInsetsInfo();
 
+    final Configuration mLastConfiguration = new Configuration();
+    final Configuration mPendingConfiguration = new Configuration();
+    
     class ResizedInfo {
         Rect coveredInsets;
         Rect visibleInsets;
@@ -719,6 +723,7 @@
             attachInfo.mRecomputeGlobalAttributes = false;
             attachInfo.mKeepScreenOn = false;
             viewVisibilityChanged = false;
+            mLastConfiguration.setTo(host.getResources().getConfiguration());
             host.dispatchAttachedToWindow(attachInfo, 0);
             //Log.i(TAG, "Screen on initialized: " + attachInfo.mKeepScreenOn);
 
@@ -904,6 +909,13 @@
                         + " visible=" + mPendingVisibleInsets.toShortString()
                         + " surface=" + mSurface);
 
+                if (mPendingConfiguration.seq != 0) {
+                    if (DEBUG_CONFIGURATION) Log.v(TAG, "Visible with new config: "
+                            + mPendingConfiguration);
+                    updateConfiguration(mPendingConfiguration, !mFirst);
+                    mPendingConfiguration.seq = 0;
+                }
+                
                 contentInsetsChanged = !mPendingContentInsets.equals(
                         mAttachInfo.mContentInsets);
                 visibleInsetsChanged = !mPendingVisibleInsets.equals(
@@ -1627,6 +1639,30 @@
         }
     }
 
+    void updateConfiguration(Configuration config, boolean force) {
+        if (DEBUG_CONFIGURATION) Log.v(TAG,
+                "Applying new config to window "
+                + mWindowAttributes.getTitle()
+                + ": " + config);
+        synchronized (sConfigCallbacks) {
+            for (int i=sConfigCallbacks.size()-1; i>=0; i--) {
+                sConfigCallbacks.get(i).onConfigurationChanged(config);
+            }
+        }
+        if (mView != null) {
+            // At this point the resources have been updated to
+            // have the most recent config, whatever that is.  Use
+            // the on in them which may be newer.
+            if (mView != null) {
+                config = mView.getResources().getConfiguration();
+            }
+            if (force || mLastConfiguration.diff(config) != 0) {
+                mLastConfiguration.setTo(config);
+                mView.dispatchConfigurationChanged(config);
+            }
+        }
+    }
+    
     /**
      * Return true if child is an ancestor of parent, (or equal to the parent).
      */
@@ -1815,14 +1851,7 @@
             if (mAdded) {
                 Configuration config = ((ResizedInfo)msg.obj).newConfig;
                 if (config != null) {
-                    synchronized (sConfigCallbacks) {
-                        for (int i=sConfigCallbacks.size()-1; i>=0; i--) {
-                            sConfigCallbacks.get(i).onConfigurationChanged(config);
-                        }
-                    }
-                    if (mView != null) {
-                        mView.dispatchConfigurationChanged(config);
-                    }
+                    updateConfiguration(config, false);
                 }
                 mWinFrame.left = 0;
                 mWinFrame.right = msg.arg1;
@@ -2500,12 +2529,14 @@
         if (params != null) {
             if (DBG) Log.d(TAG, "WindowLayout in layoutWindow:" + params);
         }
+        mPendingConfiguration.seq = 0;
         int relayoutResult = sWindowSession.relayout(
                 mWindow, params,
                 (int) (mView.mMeasuredWidth * appScale + 0.5f),
                 (int) (mView.mMeasuredHeight * appScale + 0.5f),
                 viewVisibility, insetsPending, mWinFrame,
-                mPendingContentInsets, mPendingVisibleInsets, mSurface);
+                mPendingContentInsets, mPendingVisibleInsets,
+                mPendingConfiguration, mSurface);
         if (restore) {
             params.restore();
         }
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index b27736a..93e45fc 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -143,6 +143,7 @@
     static final boolean DEBUG_VISIBILITY = false;
     static final boolean DEBUG_WINDOW_MOVEMENT = false;
     static final boolean DEBUG_ORIENTATION = false;
+    static final boolean DEBUG_CONFIGURATION = false;
     static final boolean DEBUG_APP_TRANSITIONS = false;
     static final boolean DEBUG_STARTING_WINDOW = false;
     static final boolean DEBUG_REORDER = false;
@@ -2317,7 +2318,7 @@
             WindowManager.LayoutParams attrs, int requestedWidth,
             int requestedHeight, int viewVisibility, boolean insetsPending,
             Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
-            Surface outSurface) {
+            Configuration outConfig, Surface outSurface) {
         boolean displayed = false;
         boolean inTouchMode;
         boolean configChanged;
@@ -2390,16 +2391,30 @@
                 if (oldVisibility == View.GONE) {
                     win.mEnterAnimationPending = true;
                 }
-                if (displayed && win.mSurface != null && !win.mDrawPending
-                        && !win.mCommitDrawPending && !mDisplayFrozen
-                        && mPolicy.isScreenOn()) {
-                    applyEnterAnimationLocked(win);
-                }
-                if (displayed && (win.mAttrs.flags
-                        & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
-                    if (DEBUG_VISIBILITY) Slog.v(TAG,
-                            "Relayout window turning screen on: " + win);
-                    win.mTurnOnScreen = true;
+                if (displayed) {
+                    if (win.mSurface != null && !win.mDrawPending
+                            && !win.mCommitDrawPending && !mDisplayFrozen
+                            && mPolicy.isScreenOn()) {
+                        applyEnterAnimationLocked(win);
+                    }
+                    if ((win.mAttrs.flags
+                            & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
+                        if (DEBUG_VISIBILITY) Slog.v(TAG,
+                                "Relayout window turning screen on: " + win);
+                        win.mTurnOnScreen = true;
+                    }
+                    int diff = 0;
+                    if (win.mConfiguration != mCurConfiguration
+                            && (win.mConfiguration == null
+                                    || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0)) {
+                        win.mConfiguration = mCurConfiguration;
+                        if (DEBUG_CONFIGURATION) {
+                            Slog.i(TAG, "Window " + win + " visible with new config: "
+                                    + win.mConfiguration + " / 0x"
+                                    + Integer.toHexString(diff));
+                        }
+                        outConfig.setTo(mCurConfiguration);
+                    }
                 }
                 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
                     // To change the format, we need to re-build the surface.
@@ -6694,10 +6709,10 @@
         public int relayout(IWindow window, WindowManager.LayoutParams attrs,
                 int requestedWidth, int requestedHeight, int viewFlags,
                 boolean insetsPending, Rect outFrame, Rect outContentInsets,
-                Rect outVisibleInsets, Surface outSurface) {
+                Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
             return relayoutWindow(this, window, attrs,
                     requestedWidth, requestedHeight, viewFlags, insetsPending,
-                    outFrame, outContentInsets, outVisibleInsets, outSurface);
+                    outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface);
         }
 
         public void setTransparentRegion(IWindow window, Region region) {
@@ -10163,6 +10178,10 @@
                             w.mConfiguration != mCurConfiguration
                             && (w.mConfiguration == null
                                     || mCurConfiguration.diff(w.mConfiguration) != 0);
+                        if (DEBUG_CONFIGURATION && configChanged) {
+                            Slog.v(TAG, "Win " + w + " config changed: "
+                                    + mCurConfiguration);
+                        }
                         if (localLOGV) Slog.v(TAG, "Resizing " + w
                                 + ": configChanged=" + configChanged
                                 + " last=" + w.mLastFrame + " frame=" + w.mFrame);
@@ -10507,16 +10526,19 @@
                 try {
                     if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
                             "Reporting new frame to " + win + ": " + win.mFrame);
+                    int diff = 0;
                     boolean configChanged =
                         win.mConfiguration != mCurConfiguration
                         && (win.mConfiguration == null
-                                || mCurConfiguration.diff(win.mConfiguration) != 0);
-                    win.mConfiguration = mCurConfiguration;
-                    if ((DEBUG_RESIZE || DEBUG_ORIENTATION) && configChanged) {
+                                || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0);
+                    if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION)
+                            && configChanged) {
                         Slog.i(TAG, "Sending new config to window " + win + ": "
                                 + win.mFrame.width() + "x" + win.mFrame.height()
-                                + " / " + win.mConfiguration);
+                                + " / " + mCurConfiguration + " / 0x"
+                                + Integer.toHexString(diff));
                     }
+                    win.mConfiguration = mCurConfiguration;
                     win.mClient.resized(win.mFrame.width(),
                             win.mFrame.height(), win.mLastContentInsets,
                             win.mLastVisibleInsets, win.mDrawPending,
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 8e9e75f..4201e80 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -1032,7 +1032,7 @@
 
         @SuppressWarnings("unused")
         public int relayout(IWindow arg0, LayoutParams arg1, int arg2, int arg3, int arg4,
-                boolean arg4_5, Rect arg5, Rect arg6, Rect arg7, Surface arg8)
+                boolean arg4_5, Rect arg5, Rect arg6, Rect arg7, Configuration arg7b, Surface arg8)
                 throws RemoteException {
             // pass for now.
             return 0;