DO NOT MERGE.  From main -- Start work on simulating landscape/portrait when orientation is locked.

Not yet working, so turned off.

Also fix a bug where the display size configuration became inconsistent
after a configuration change -- we now figure out everything about the
display size when computing a new configuration.

Change-Id: Id155f133c0bf108508a225ef64ed3ca398a90a58
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 0ea461b..1d60066 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -200,8 +200,27 @@
      * @param outMetrics
      */
     public void getMetrics(DisplayMetrics outMetrics) {
-        outMetrics.widthPixels  = getWidth();
-        outMetrics.heightPixels = getHeight();
+        synchronized (mTmpPoint) {
+            getSize(mTmpPoint);
+            outMetrics.widthPixels = mTmpPoint.x;
+            outMetrics.heightPixels = mTmpPoint.y;
+        }
+        getNonSizeMetrics(outMetrics);
+    }
+
+    /**
+     * Initialize a DisplayMetrics object from this display's data.
+     *
+     * @param outMetrics
+     * @hide
+     */
+    public void getRealMetrics(DisplayMetrics outMetrics) {
+        outMetrics.widthPixels = getRealWidth();
+        outMetrics.heightPixels = getRealHeight();
+        getNonSizeMetrics(outMetrics);
+    }
+
+    private void getNonSizeMetrics(DisplayMetrics outMetrics) {
         outMetrics.density      = mDensity;
         outMetrics.densityDpi   = (int)((mDensity*DisplayMetrics.DENSITY_DEFAULT)+.5f);
         outMetrics.scaledDensity= outMetrics.density;
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 03b3553..c7cf459 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -398,7 +398,7 @@
      * display dimensions.
      */
     public void setInitialDisplaySize(int width, int height);
-    
+
     /**
      * Check permissions when adding a window.
      * 
@@ -826,6 +826,13 @@
             boolean displayEnabled);
     
     /**
+     * Return the currently locked screen rotation, if any.  Return
+     * Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_180, or
+     * Surface.ROTATION_270 if locked; return -1 if not locked.
+     */
+    public int getLockedRotationLw();
+
+    /**
      * Called when the system is mostly done booting to determine whether
      * the system should go into safe mode.
      */
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index bf602c6..2d68667 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2594,6 +2594,26 @@
         }
     }
 
+    public int getLockedRotationLw() {
+        synchronized (mLock) {
+            if (false) {
+                // Not yet working.
+                if (mHdmiPlugged) {
+                    return Surface.ROTATION_0;
+                } else if (mLidOpen == LID_OPEN) {
+                    return mLidOpenRotation;
+                } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR && mCarDockRotation >= 0) {
+                    return mCarDockRotation;
+                } else if (mDockMode == Intent.EXTRA_DOCK_STATE_DESK && mDeskDockRotation >= 0) {
+                    return mDeskDockRotation;
+                } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
+                    return mUserRotation;
+                }
+            }
+            return -1;
+        }
+    }
+
     private int getCurrentLandscapeRotation(int lastRotation) {
         // if the user has locked rotation, we ignore the sensor 
         if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 4b9ce90..992ab3b 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -397,6 +397,7 @@
     int mRotation = 0;
     int mRequestedRotation = 0;
     int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+    boolean mAltOrientation = false;
     int mLastRotationFlags;
     ArrayList<IRotationWatcher> mRotationWatchers
             = new ArrayList<IRotationWatcher>();
@@ -584,7 +585,6 @@
     }
 
     final Configuration mTempConfiguration = new Configuration();
-    int mScreenLayout = Configuration.SCREENLAYOUT_SIZE_UNDEFINED;
 
     // The frame use to limit the size of the app running in compatibility mode.
     Rect mCompatibleScreenFrame = new Rect();
@@ -4757,8 +4757,8 @@
         synchronized(mWindowMap) {
             long ident = Binder.clearCallingIdentity();
 
-            dw = mCurDisplayWidth;
-            dh = mCurDisplayHeight;
+            dw = mPolicy.getNonDecorDisplayWidth(mCurDisplayWidth);
+            dh = mPolicy.getNonDecorDisplayHeight(mCurDisplayHeight);
 
             int aboveAppLayer = mPolicy.windowTypeToLayerLw(
                     WindowManager.LayoutParams.TYPE_APPLICATION) * TYPE_LAYER_MULTIPLIER
@@ -4952,7 +4952,52 @@
         rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation,
                 mRotation, mDisplayEnabled);
         if (DEBUG_ORIENTATION) Slog.v(TAG, "new rotation is set to " + rotation);
+
+        int desiredRotation = rotation;
+        int lockedRotation = mPolicy.getLockedRotationLw();
+        if (lockedRotation >= 0 && rotation != lockedRotation) {
+            // We are locked in a rotation but something is requesting
+            // a different rotation...  we will either keep the locked
+            // rotation if it results in the same orientation, or have to
+            // switch into an emulated orientation mode.
+
+            // First, we know that our rotation is actually going to be
+            // the locked rotation.
+            rotation = lockedRotation;
+
+            // Now the difference between the desired and lockedRotation
+            // may mean that the orientation is different...  if that is
+            // not the case, we can just make the desired rotation be the
+            // same as the new locked rotation.
+            switch (lockedRotation) {
+                case Surface.ROTATION_0:
+                    if (rotation == Surface.ROTATION_180) {
+                        desiredRotation = lockedRotation;
+                    }
+                    break;
+                case Surface.ROTATION_90:
+                    if (rotation == Surface.ROTATION_270) {
+                        desiredRotation = lockedRotation;
+                    }
+                    break;
+                case Surface.ROTATION_180:
+                    if (rotation == Surface.ROTATION_0) {
+                        desiredRotation = lockedRotation;
+                    }
+                    break;
+                case Surface.ROTATION_270:
+                    if (rotation == Surface.ROTATION_90) {
+                        desiredRotation = lockedRotation;
+                    }
+                    break;
+            }
+        }
+
         changed = mDisplayEnabled && mRotation != rotation;
+        if (mAltOrientation != (rotation != desiredRotation)) {
+            changed = true;
+            mAltOrientation = rotation != desiredRotation;
+        }
 
         if (changed) {
             if (DEBUG_ORIENTATION) Slog.v(TAG,
@@ -4998,6 +5043,7 @@
                     Surface.setOrientation(0, rotation, animFlags);
                 }
             }
+
             for (int i=mWindows.size()-1; i>=0; i--) {
                 WindowState w = mWindows.get(i);
                 if (w.mSurface != null) {
@@ -5438,8 +5484,32 @@
         // Use the effective "visual" dimensions based on current rotation
         final boolean rotated = (mRotation == Surface.ROTATION_90
                 || mRotation == Surface.ROTATION_270);
-        final int dw = rotated ? mInitialDisplayHeight : mInitialDisplayWidth;
-        final int dh = rotated ? mInitialDisplayWidth : mInitialDisplayHeight;
+        final int realdw = rotated ? mInitialDisplayHeight : mInitialDisplayWidth;
+        final int realdh = rotated ? mInitialDisplayWidth : mInitialDisplayHeight;
+
+        if (mAltOrientation) {
+            mCurDisplayWidth = realdw;
+            mCurDisplayHeight = realdh;
+            if (realdw > realdh) {
+                // Turn landscape into portrait.
+                int maxw = (int)(realdh/1.3f);
+                if (maxw < realdw) {
+                    mCurDisplayWidth = maxw;
+                }
+            } else {
+                // Turn portrait into landscape.
+                int maxh = (int)(realdw/1.3f);
+                if (maxh < realdh) {
+                    mCurDisplayHeight = maxh;
+                }
+            }
+        } else {
+            mCurDisplayWidth = realdw;
+            mCurDisplayHeight = realdh;
+        }
+
+        final int dw = mCurDisplayWidth;
+        final int dh = mCurDisplayHeight;
 
         int orientation = Configuration.ORIENTATION_SQUARE;
         if (dw < dh) {
@@ -5450,69 +5520,70 @@
         config.orientation = orientation;
 
         DisplayMetrics dm = new DisplayMetrics();
-        mDisplay.getMetrics(dm);
-        dm.realWidthPixels = mPolicy.getNonDecorDisplayWidth(dm.realWidthPixels);
-        dm.realHeightPixels = mPolicy.getNonDecorDisplayHeight(dm.realHeightPixels);
+        mDisplay.getRealMetrics(dm);
+
+        // Override display width and height with what we are computing,
+        // to be sure they remain consistent.
+        dm.widthPixels = mPolicy.getNonDecorDisplayWidth(dw);
+        dm.heightPixels = mPolicy.getNonDecorDisplayHeight(dh);
+
         mCompatibleScreenScale = CompatibilityInfo.updateCompatibleScreenFrame(
                 dm, mCompatibleScreenFrame, null);
 
         config.screenWidthDp = (int)(dm.widthPixels / dm.density);
         config.screenHeightDp = (int)(dm.heightPixels / dm.density);
 
-        if (mScreenLayout == Configuration.SCREENLAYOUT_SIZE_UNDEFINED) {
-            // Note we only do this once because at this point we don't
-            // expect the screen to change in this way at runtime, and want
-            // to avoid all of this computation for every config change.
-            int longSize = dw;
-            int shortSize = dh;
-            if (longSize < shortSize) {
-                int tmp = longSize;
-                longSize = shortSize;
-                shortSize = tmp;
-            }
-            longSize = (int)(longSize/dm.density);
-            shortSize = (int)(shortSize/dm.density);
+        // Compute the screen layout size class.
+        int screenLayout;
+        int longSize = dw;
+        int shortSize = dh;
+        if (longSize < shortSize) {
+            int tmp = longSize;
+            longSize = shortSize;
+            shortSize = tmp;
+        }
+        longSize = (int)(longSize/dm.density);
+        shortSize = (int)(shortSize/dm.density);
 
-            // These semi-magic numbers define our compatibility modes for
-            // applications with different screens.  These are guarantees to
-            // app developers about the space they can expect for a particular
-            // configuration.  DO NOT CHANGE!
-            if (longSize < 470) {
-                // This is shorter than an HVGA normal density screen (which
-                // is 480 pixels on its long side).
-                mScreenLayout = Configuration.SCREENLAYOUT_SIZE_SMALL
-                        | Configuration.SCREENLAYOUT_LONG_NO;
+        // These semi-magic numbers define our compatibility modes for
+        // applications with different screens.  These are guarantees to
+        // app developers about the space they can expect for a particular
+        // configuration.  DO NOT CHANGE!
+        if (longSize < 470) {
+            // This is shorter than an HVGA normal density screen (which
+            // is 480 pixels on its long side).
+            screenLayout = Configuration.SCREENLAYOUT_SIZE_SMALL
+                    | Configuration.SCREENLAYOUT_LONG_NO;
+        } else {
+            // What size is this screen screen?
+            if (longSize >= 960 && shortSize >= 720) {
+                // 1.5xVGA or larger screens at medium density are the point
+                // at which we consider it to be an extra large screen.
+                screenLayout = Configuration.SCREENLAYOUT_SIZE_XLARGE;
+            } else if (longSize >= 640 && shortSize >= 480) {
+                // VGA or larger screens at medium density are the point
+                // at which we consider it to be a large screen.
+                screenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE;
             } else {
-                // What size is this screen screen?
-                if (longSize >= 960 && shortSize >= 720) {
-                    // 1.5xVGA or larger screens at medium density are the point
-                    // at which we consider it to be an extra large screen.
-                    mScreenLayout = Configuration.SCREENLAYOUT_SIZE_XLARGE;
-                } else if (longSize >= 640 && shortSize >= 480) {
-                    // VGA or larger screens at medium density are the point
-                    // at which we consider it to be a large screen.
-                    mScreenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE;
-                } else {
-                    mScreenLayout = Configuration.SCREENLAYOUT_SIZE_NORMAL;
-                }
-                
-                // If this screen is wider than normal HVGA, or taller
-                // than FWVGA, then for old apps we want to run in size
-                // compatibility mode.
-                if (shortSize > 321 || longSize > 570) {
-                    mScreenLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
-                }
+                screenLayout = Configuration.SCREENLAYOUT_SIZE_NORMAL;
+            }
 
-                // Is this a long screen?
-                if (((longSize*3)/5) >= (shortSize-1)) {
-                    // Anything wider than WVGA (5:3) is considering to be long.
-                    mScreenLayout |= Configuration.SCREENLAYOUT_LONG_YES;
-                } else {
-                    mScreenLayout |= Configuration.SCREENLAYOUT_LONG_NO;
-                }
+            // If this screen is wider than normal HVGA, or taller
+            // than FWVGA, then for old apps we want to run in size
+            // compatibility mode.
+            if (shortSize > 321 || longSize > 570) {
+                screenLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
+            }
+
+            // Is this a long screen?
+            if (((longSize*3)/5) >= (shortSize-1)) {
+                // Anything wider than WVGA (5:3) is considering to be long.
+                screenLayout |= Configuration.SCREENLAYOUT_LONG_YES;
+            } else {
+                screenLayout |= Configuration.SCREENLAYOUT_LONG_NO;
             }
         }
-        config.screenLayout = mScreenLayout;
+        config.screenLayout = screenLayout;
 
         // Determine whether a hard keyboard is available and enabled.
         boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
@@ -6730,8 +6801,8 @@
         }
 
         final long currentTime = SystemClock.uptimeMillis();
-        final int dw = mCurDisplayWidth = mDisplay.getRealWidth();
-        final int dh = mCurDisplayHeight = mDisplay.getRealHeight();
+        final int dw = mCurDisplayWidth;
+        final int dh = mCurDisplayHeight;
 
         final int innerDw = mPolicy.getNonDecorDisplayWidth(dw);
         final int innerDh = mPolicy.getNonDecorDisplayHeight(dh);
@@ -8728,8 +8799,9 @@
                     pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen);
                     pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig);
             pw.print("  mRotation="); pw.print(mRotation);
-                    pw.print(", mForcedAppOrientation="); pw.print(mForcedAppOrientation);
-                    pw.print(", mRequestedRotation="); pw.println(mRequestedRotation);
+                    pw.print(" mForcedAppOrientation="); pw.print(mForcedAppOrientation);
+                    pw.print(" mRequestedRotation="); pw.print(mRequestedRotation);
+                    pw.print(" mAltOrientation="); pw.println(mAltOrientation);
             pw.print("  mDeferredRotation="); pw.print(mDeferredRotation);
                     pw.print(", mDeferredRotationAnimFlags="); pw.println(mDeferredRotationAnimFlags);
             pw.print("  mAnimationPending="); pw.print(mAnimationPending);