Improve compat mode scaling implementation.

Rip out the old funky code for trying to restrict the app window
sizes to be within the compat mode range.  Instead, we know rely
entirely on scaling -- we deal with windows always with the scaling
applied so that the window manager doesn't have to deal with them
specially.  Instead, we just apply the inverse scale at the few
points we need to do something the app sees.

Change-Id: I785409dd4513b5f738684e1635dc8f770c249651
diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java
index c8f8ff3..118cd55 100644
--- a/services/java/com/android/server/wm/DragState.java
+++ b/services/java/com/android/server/wm/DragState.java
@@ -156,9 +156,8 @@
         }
 
         if (mDragInProgress && newWin.isPotentialDragTarget()) {
-            DragEvent event = DragEvent.obtain(DragEvent.ACTION_DRAG_STARTED,
-                    touchX - newWin.mFrame.left, touchY - newWin.mFrame.top,
-                    null, desc, null, false);
+            DragEvent event = obtainDragEvent(newWin, DragEvent.ACTION_DRAG_STARTED,
+                    touchX, touchY, null, desc, null, false);
             try {
                 newWin.mClient.dispatchDragEvent(event);
                 // track each window that we've notified that the drag is starting
@@ -267,9 +266,8 @@
                     Slog.d(WindowManagerService.TAG, "sending DRAG_EXITED to " + mTargetWindow);
                 }
                 // force DRAG_EXITED_EVENT if appropriate
-                DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_EXITED,
-                        x - mTargetWindow.mFrame.left, y - mTargetWindow.mFrame.top,
-                        null, null, null, false);
+                DragEvent evt = obtainDragEvent(mTargetWindow, DragEvent.ACTION_DRAG_EXITED,
+                        x, y, null, null, null, false);
                 mTargetWindow.mClient.dispatchDragEvent(evt);
                 if (myPid != mTargetWindow.mSession.mPid) {
                     evt.recycle();
@@ -279,9 +277,8 @@
                 if (false && WindowManagerService.DEBUG_DRAG) {
                     Slog.d(WindowManagerService.TAG, "sending DRAG_LOCATION to " + touchedWin);
                 }
-                DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_LOCATION,
-                        x - touchedWin.mFrame.left, y - touchedWin.mFrame.top,
-                        null, null, null, false);
+                DragEvent evt = obtainDragEvent(touchedWin, DragEvent.ACTION_DRAG_LOCATION,
+                        x, y, null, null, null, false);
                 touchedWin.mClient.dispatchDragEvent(evt);
                 if (myPid != touchedWin.mSession.mPid) {
                     evt.recycle();
@@ -310,8 +307,7 @@
         }
         final int myPid = Process.myPid();
         final IBinder token = touchedWin.mClient.asBinder();
-        DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DROP,
-                x - touchedWin.mFrame.left, y - touchedWin.mFrame.top,
+        DragEvent evt = obtainDragEvent(touchedWin, DragEvent.ACTION_DROP, x, y,
                 null, null, mData, false);
         try {
             touchedWin.mClient.dispatchDragEvent(evt);
@@ -365,4 +361,16 @@
 
         return touchedWin;
     }
+
+    private static DragEvent obtainDragEvent(WindowState win, int action,
+            float x, float y, Object localState,
+            ClipDescription description, ClipData data, boolean result) {
+        float winX = x - win.mFrame.left;
+        float winY = y - win.mFrame.top;
+        if (win.mEnforceSizeCompat) {
+            winX *= win.mGlobalScale;
+            winY *= win.mGlobalScale;
+        }
+        return DragEvent.obtain(action, winX, winY, localState, description, data, result);
+    }
 }
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/FadeInOutAnimation.java b/services/java/com/android/server/wm/FadeInOutAnimation.java
deleted file mode 100644
index 06f7657..0000000
--- a/services/java/com/android/server/wm/FadeInOutAnimation.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm;
-
-import android.view.animation.AccelerateInterpolator;
-import android.view.animation.Animation;
-import android.view.animation.Transformation;
-
-/**
- * Animation that fade in after 0.5 interpolate time, or fade out in reverse order.
- * This is used for opening/closing transition for apps in compatible mode.
- */
-class FadeInOutAnimation extends Animation {
-    boolean mFadeIn;
-
-    public FadeInOutAnimation(boolean fadeIn) {
-        setInterpolator(new AccelerateInterpolator());
-        setDuration(WindowManagerService.DEFAULT_FADE_IN_OUT_DURATION);
-        mFadeIn = fadeIn;
-    }
-
-    @Override
-    protected void applyTransformation(float interpolatedTime, Transformation t) {
-        float x = interpolatedTime;
-        if (!mFadeIn) {
-            x = 1.0f - x; // reverse the interpolation for fade out
-        }
-        t.setAlpha(x);
-    }
-}
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java
index a3e8be0..9dc92d3 100644
--- a/services/java/com/android/server/wm/InputMonitor.java
+++ b/services/java/com/android/server/wm/InputMonitor.java
@@ -205,7 +205,7 @@
             inputWindow.ownerPid = child.mSession.mPid;
             inputWindow.ownerUid = child.mSession.mUid;
             
-            final Rect frame = child.mScaledFrame;
+            final Rect frame = child.mFrame;
             inputWindow.frameLeft = frame.left;
             inputWindow.frameTop = frame.top;
             inputWindow.frameRight = frame.right;
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 6103b0f..26d89cd 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -603,9 +603,6 @@
     // The frame use to limit the size of the app running in compatibility mode.
     Rect mCompatibleScreenFrame = new Rect();
     float mCompatibleScreenScale;
-    // The surface used to fill the outer rim of the app running in compatibility mode.
-    Surface mBackgroundFillerSurface = null;
-    WindowState mBackgroundFillerTarget = null;
 
     public static WindowManagerService main(Context context,
             PowerManagerService pm, boolean haveInputMethods) {
@@ -1774,7 +1771,7 @@
         boolean rawChanged = false;
         float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f;
         float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
-        int availw = wallpaperWin.mScaledFrame.right-wallpaperWin.mScaledFrame.left-dw;
+        int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
         int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0;
         changed = wallpaperWin.mXOffset != offset;
         if (changed) {
@@ -2369,6 +2366,11 @@
                     w.mGivenVisibleInsets.set(visibleInsets);
                     w.mGivenTouchableRegion.set(touchableRegion);
                     w.mTouchableInsets = touchableInsets;
+                    if (w.mGlobalScale != 1) {
+                        w.mGivenContentInsets.scale(w.mGlobalScale);
+                        w.mGivenVisibleInsets.scale(w.mGlobalScale);
+                        w.mGivenTouchableRegion.scale(w.mGlobalScale);
+                    }
                     mLayoutNeeded = true;
                     performLayoutAndPlaceSurfacesLocked();
                 }
@@ -2704,7 +2706,7 @@
             if (win.mAppToken != null) {
                 win.mAppToken.updateReportedVisibilityLocked();
             }
-            outFrame.set(win.mFrame);
+            outFrame.set(win.mCompatFrame);
             outContentInsets.set(win.mContentInsets);
             outVisibleInsets.set(win.mVisibleInsets);
             if (localLOGV) Slog.v(
@@ -2903,18 +2905,14 @@
     }
 
     private boolean applyAnimationLocked(AppWindowToken wtoken,
-            WindowManager.LayoutParams lp, int transit, boolean enter, boolean bgFiller) {
+            WindowManager.LayoutParams lp, int transit, boolean enter) {
         // Only apply an animation if the display isn't frozen.  If it is
         // frozen, there is no reason to animate and it can cause strange
         // artifacts when we unfreeze the display if some different animation
         // is running.
         if (!mDisplayFrozen && mPolicy.isScreenOn()) {
             Animation a;
-            if (bgFiller) {
-                a = new FadeInOutAnimation(enter);
-                if (DEBUG_ANIM) Slog.v(TAG,
-                        "applying FadeInOutAnimation for a window in compatibility mode");
-            } else if (mNextAppTransitionPackage != null) {
+            if (mNextAppTransitionPackage != null) {
                 a = loadAnimation(mNextAppTransitionPackage, enter ?
                         mNextAppTransitionEnter : mNextAppTransitionExit);
             } else {
@@ -3706,7 +3704,7 @@
     }
 
     boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
-            boolean visible, int transit, boolean performLayout, boolean bgFiller) {
+            boolean visible, int transit, boolean performLayout) {
         boolean delayed = false;
 
         if (wtoken.clientHidden == visible) {
@@ -3728,7 +3726,7 @@
                 if (wtoken.animation == sDummyAnimation) {
                     wtoken.animation = null;
                 }
-                applyAnimationLocked(wtoken, lp, transit, visible, bgFiller);
+                applyAnimationLocked(wtoken, lp, transit, visible);
                 changed = true;
                 if (wtoken.animation != null) {
                     delayed = runningAppAnimation = true;
@@ -3882,7 +3880,7 @@
 
             final long origId = Binder.clearCallingIdentity();
             setTokenVisibilityLocked(wtoken, null, visible, WindowManagerPolicy.TRANSIT_UNSET,
-                    true, false);
+                    true);
             wtoken.updateReportedVisibilityLocked();
             Binder.restoreCallingIdentity(origId);
         }
@@ -4009,7 +4007,7 @@
             if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken);
                 delayed = setTokenVisibilityLocked(wtoken, null, false,
-                        WindowManagerPolicy.TRANSIT_UNSET, true, false);
+                        WindowManagerPolicy.TRANSIT_UNSET, true);
                 wtoken.inPendingTransaction = false;
                 mOpeningApps.remove(wtoken);
                 wtoken.waitingToShow = false;
@@ -4830,7 +4828,7 @@
                 
                 // Don't include wallpaper in bounds calculation
                 if (!ws.mIsWallpaper) {
-                    final Rect wf = ws.mScaledFrame;
+                    final Rect wf = ws.mFrame;
                     final Rect cr = ws.mContentInsets;
                     int left = wf.left + cr.left;
                     int top = wf.top + cr.top;
@@ -5549,8 +5547,8 @@
 
         // 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);
+        dm.widthPixels = dm.realWidthPixels = mPolicy.getNonDecorDisplayWidth(dw);
+        dm.heightPixels = dm.realHeightPixels = mPolicy.getNonDecorDisplayHeight(dh);
 
         mCompatibleScreenScale = CompatibilityInfo.updateCompatibleScreenFrame(
                 dm, mCompatibleScreenFrame, null);
@@ -6851,7 +6849,6 @@
                     }
                     win.prelayout();
                     mPolicy.layoutWindowLw(win, win.mAttrs, null);
-                    win.evalNeedsBackgroundFiller(innerDw, innerDh);
                     win.mLayoutSeq = seq;
                     if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame="
                             + win.mFrame + " mContainingFrame="
@@ -6888,7 +6885,6 @@
                     }
                     win.prelayout();
                     mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
-                    win.evalNeedsBackgroundFiller(innerDw, innerDh);
                     win.mLayoutSeq = seq;
                     if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame="
                             + win.mFrame + " mContainingFrame="
@@ -7340,7 +7336,6 @@
                         LayoutParams animLp = null;
                         int bestAnimLayer = -1;
                         boolean fullscreenAnim = false;
-                        boolean needBgFiller = false;
 
                         if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
                                 "New wallpaper target=" + mWallpaperTarget
@@ -7378,16 +7373,8 @@
                             if (wtoken.appFullscreen) {
                                 WindowState ws = wtoken.findMainWindow();
                                 if (ws != null) {
-                                    // If this is a compatibility mode
-                                    // window, we will always use its anim.
-                                    if (ws.mNeedsBackgroundFiller) {
-                                        animLp = ws.mAttrs;
-                                        bestAnimLayer = Integer.MAX_VALUE;
-                                        needBgFiller = true;
-                                    } else if (!fullscreenAnim || ws.mLayer > bestAnimLayer) {
-                                        animLp = ws.mAttrs;
-                                        bestAnimLayer = ws.mLayer;
-                                    }
+                                    animLp = ws.mAttrs;
+                                    bestAnimLayer = ws.mLayer;
                                     fullscreenAnim = true;
                                 }
                             } else if (!fullscreenAnim) {
@@ -7449,7 +7436,7 @@
                             wtoken.inPendingTransaction = false;
                             wtoken.animation = null;
                             setTokenVisibilityLocked(wtoken, animLp, true,
-                                    transit, false, needBgFiller);
+                                    transit, false);
                             wtoken.updateReportedVisibilityLocked();
                             wtoken.waitingToShow = false;
                             wtoken.showAllWindowsLocked();
@@ -7462,7 +7449,7 @@
                             wtoken.inPendingTransaction = false;
                             wtoken.animation = null;
                             setTokenVisibilityLocked(wtoken, animLp, false,
-                                    transit, false, needBgFiller);
+                                    transit, false);
                             wtoken.updateReportedVisibilityLocked();
                             wtoken.waitingToHide = false;
                             // Force the allDrawn flag, because we want to start
@@ -7629,8 +7616,6 @@
             boolean dimming = false;
             boolean covered = false;
             boolean syswin = false;
-            boolean backgroundFillerWasShown = mBackgroundFillerTarget != null;
-            mBackgroundFillerTarget = null;
 
             final int N = mWindows.size();
 
@@ -7659,8 +7644,7 @@
                     w.computeShownFrameLocked();
                     if (localLOGV) Slog.v(
                             TAG, "Placing surface #" + i + " " + w.mSurface
-                            + ": new=" + w.mShownFrame + ", old="
-                            + w.mLastShownFrame);
+                            + ": new=" + w.mShownFrame);
 
                     int width, height;
                     if ((w.mAttrs.flags & w.mAttrs.FLAG_SCALED) != 0) {
@@ -7668,13 +7652,9 @@
                         // the requested size.
                         width  = w.mRequestedWidth;
                         height = w.mRequestedHeight;
-                        w.mLastRequestedWidth = width;
-                        w.mLastRequestedHeight = height;
-                        w.mLastShownFrame.set(w.mShownFrame);
                     } else {
-                        width = w.mShownFrame.width();
-                        height = w.mShownFrame.height();
-                        w.mLastShownFrame.set(w.mShownFrame);
+                        width = w.mCompatFrame.width();
+                        height = w.mCompatFrame.height();
                     }
 
                     if (w.mSurface != null) {
@@ -7741,8 +7721,8 @@
                         }
                         if (localLOGV) Slog.v(TAG, "Resizing " + w
                                 + ": configChanged=" + configChanged
-                                + " last=" + w.mLastFrame + " frame=" + w.mFrame);
-                        boolean frameChanged = !w.mLastFrame.equals(w.mFrame);
+                                + " last=" + w.mLastCompatFrame + " frame=" + w.mCompatFrame);
+                        boolean frameChanged = !w.mLastCompatFrame.equals(w.mCompatFrame);
                         if (frameChanged
                                 || w.mContentInsetsChanged
                                 || w.mVisibleInsetsChanged
@@ -7758,6 +7738,7 @@
                             }
 
                             w.mLastFrame.set(w.mFrame);
+                            w.mLastCompatFrame.set(w.mCompatFrame);
                             w.mLastContentInsets.set(w.mContentInsets);
                             w.mLastVisibleInsets.set(w.mVisibleInsets);
                             // If the screen is currently frozen, then keep
@@ -7793,7 +7774,7 @@
                                 }
                             }
                             if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
-                                    "Resizing window " + w + " to " + w.mFrame);
+                                    "Resizing window " + w + " to " + w.mCompatFrame);
                             mResizingWindows.add(w);
                         } else if (w.mOrientationChanging) {
                             if (!w.mDrawPending && !w.mCommitDrawPending) {
@@ -7932,16 +7913,6 @@
 
                 final boolean obscuredChanged = w.mObscured != obscured;
 
-                if (mBackgroundFillerTarget != null) {
-                    if (w.isAnimating()) {
-                        // Background filler is below all other windows that
-                        // are animating.
-                        mBackgroundFillerTarget = w;
-                    } else if (w.mIsWallpaper) {
-                        mBackgroundFillerTarget = w;
-                    }
-                }
-
                 // Update effect.
                 if (!(w.mObscured=obscured)) {
                     if (w.mSurface != null) {
@@ -7970,12 +7941,6 @@
                         // so we want to leave all of them as unblurred (for
                         // performance reasons).
                         obscured = true;
-                    } else if (w.mNeedsBackgroundFiller && w.mHasDrawn
-                            && w.mViewVisibility == View.VISIBLE
-                            && (canBeSeen || w.isAnimating())) {
-                        // This window is in compatibility mode, and needs background filler.
-                        obscured = true;
-                        mBackgroundFillerTarget = w;
                     } else if (canBeSeen && !obscured &&
                             (attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) {
                         if (localLOGV) Slog.v(TAG, "Win " + w
@@ -8042,47 +8007,6 @@
                 }
             }
 
-            if (mBackgroundFillerTarget != null) {
-                if (mBackgroundFillerSurface == null) {
-                    try {
-                        mBackgroundFillerSurface = new Surface(mFxSession, 0,
-                                "BackGroundFiller",
-                                0, dw, dh,
-                                PixelFormat.OPAQUE,
-                                Surface.FX_SURFACE_NORMAL);
-                    } catch (Exception e) {
-                        Slog.e(TAG, "Exception creating filler surface", e);
-                    }
-                    if (SHOW_TRANSACTIONS) Slog.i(TAG, "  BG FILLER "
-                            + mBackgroundFillerSurface + ": CREATE");
-                }
-                try {
-                    if (SHOW_TRANSACTIONS) Slog.i(TAG, "  BG FILLER "
-                            + mBackgroundFillerSurface + " SHOW: pos=(0,0) ("
-                            + dw + "x" + dh + ") layer="
-                            + (mBackgroundFillerTarget.mLayer - 1));
-                    mBackgroundFillerSurface.setPosition(0, 0);
-                    mBackgroundFillerSurface.setSize(dw, dh);
-                    // Using the same layer as Dim because they will never be shown at the
-                    // same time.  NOTE: we do NOT use mAnimLayer, because we don't
-                    // want this surface dragged up in front of stuff that is animating.
-                    mBackgroundFillerSurface.setLayer(mBackgroundFillerTarget.mLayer
-                            - LAYER_OFFSET_DIM);
-                    mBackgroundFillerSurface.show();
-                } catch (RuntimeException e) {
-                    Slog.e(TAG, "Exception showing filler surface");
-                }
-            } else if (backgroundFillerWasShown) {
-                mBackgroundFillerTarget = null;
-                if (SHOW_TRANSACTIONS) Slog.i(TAG, "  BG FILLER "
-                        + mBackgroundFillerSurface + " HIDE");
-                try {
-                    mBackgroundFillerSurface.hide();
-                } catch (RuntimeException e) {
-                    Slog.e(TAG, "Exception hiding filler surface", e);
-                }
-            }
-
             if (mDimAnimator != null && mDimAnimator.mDimShown) {
                 animating |= mDimAnimator.updateSurface(dimming, currentTime,
                         mDisplayFrozen || !mPolicy.isScreenOn());
@@ -8137,7 +8061,7 @@
                 WindowState win = mResizingWindows.get(i);
                 try {
                     if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
-                            "Reporting new frame to " + win + ": " + win.mFrame);
+                            "Reporting new frame to " + win + ": " + win.mCompatFrame);
                     int diff = 0;
                     boolean configChanged =
                         win.mConfiguration != mCurConfiguration
@@ -8146,13 +8070,13 @@
                     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.mCompatFrame.width() + "x" + win.mCompatFrame.height()
                                 + " / " + mCurConfiguration + " / 0x"
                                 + Integer.toHexString(diff));
                     }
                     win.mConfiguration = mCurConfiguration;
-                    win.mClient.resized(win.mFrame.width(),
-                            win.mFrame.height(), win.mLastContentInsets,
+                    win.mClient.resized(win.mCompatFrame.width(),
+                            win.mCompatFrame.height(), win.mLastContentInsets,
                             win.mLastVisibleInsets, win.mDrawPending,
                             configChanged ? win.mConfiguration : null);
                     win.mContentInsetsChanged = false;
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index 2014e9d..144341b 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -18,7 +18,6 @@
 
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
@@ -83,23 +82,30 @@
     boolean mAttachedHidden;    // is our parent window hidden?
     boolean mLastHidden;        // was this window last hidden?
     boolean mWallpaperVisible;  // for wallpaper, what was last vis report?
+
+    /**
+     * The window size that was requested by the application.  These are in
+     * the application's coordinate space (without compatibility scale applied).
+     */
     int mRequestedWidth;
     int mRequestedHeight;
-    int mLastRequestedWidth;
-    int mLastRequestedHeight;
+
     int mLayer;
     int mAnimLayer;
     int mLastLayer;
     boolean mHaveFrame;
     boolean mObscured;
-    boolean mNeedsBackgroundFiller;
     boolean mTurnOnScreen;
 
     int mLayoutSeq = -1;
     
     Configuration mConfiguration = null;
     
-    // Actual frame shown on-screen (may be modified by animation)
+    /**
+     * Actual frame shown on-screen (may be modified by animation).  These
+     * are in the screen's coordinate space (WITH the compatibility scale
+     * applied).
+     */
     final Rect mShownFrame = new Rect();
     final Rect mLastShownFrame = new Rect();
 
@@ -110,14 +116,16 @@
     boolean mSurfaceResized;
     
     /**
-     * Insets that determine the actually visible area
+     * Insets that determine the actually visible area.  These are in the application's
+     * coordinate space (without compatibility scale applied).
      */
     final Rect mVisibleInsets = new Rect();
     final Rect mLastVisibleInsets = new Rect();
     boolean mVisibleInsetsChanged;
 
     /**
-     * Insets that are covered by system windows
+     * Insets that are covered by system windows.  These are in the application's
+     * coordinate space (without compatibility scale applied).
      */
     final Rect mContentInsets = new Rect();
     final Rect mLastContentInsets = new Rect();
@@ -157,16 +165,20 @@
     // Current transformation being applied.
     boolean mHaveMatrix;
     float mGlobalScale=1;
+    float mInvGlobalScale=1;
     float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
     float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
     float mHScale=1, mVScale=1;
     float mLastHScale=1, mLastVScale=1;
     final Matrix mTmpMatrix = new Matrix();
 
-    // "Real" frame that the application sees.
+    // "Real" frame that the application sees, in display coordinate space.
     final Rect mFrame = new Rect();
     final Rect mLastFrame = new Rect();
-    final Rect mScaledFrame = new Rect();
+    // Frame that is scaled to the application's coordinate space when in
+    // screen size compatibility mode.
+    final Rect mCompatFrame = new Rect();
+    final Rect mLastCompatFrame = new Rect();
 
     final Rect mContainingFrame = new Rect();
     final Rect mDisplayFrame = new Rect();
@@ -346,8 +358,6 @@
         mSurface = null;
         mRequestedWidth = 0;
         mRequestedHeight = 0;
-        mLastRequestedWidth = 0;
-        mLastRequestedHeight = 0;
         mXOffset = 0;
         mYOffset = 0;
         mLayer = 0;
@@ -373,23 +383,40 @@
         final Rect display = mDisplayFrame;
         display.set(df);
 
-        if (mEnforceSizeCompat) {
-            container.intersect(mService.mCompatibleScreenFrame);
-            if ((mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) == 0) {
-                display.intersect(mService.mCompatibleScreenFrame);
-            }
-        }
-
         final int pw = container.right - container.left;
         final int ph = container.bottom - container.top;
 
         int w,h;
-        if ((mAttrs.flags & mAttrs.FLAG_SCALED) != 0) {
-            w = mAttrs.width < 0 ? pw : mAttrs.width;
-            h = mAttrs.height< 0 ? ph : mAttrs.height;
+        if ((mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0) {
+            if (mAttrs.width < 0) {
+                w = pw;
+            } else if (mEnforceSizeCompat) {
+                w = (int)(mAttrs.width * mGlobalScale + .5f);
+            } else {
+                w = mAttrs.width;
+            }
+            if (mAttrs.height < 0) {
+                h = ph;
+            } else if (mEnforceSizeCompat) {
+                h = (int)(mAttrs.height * mGlobalScale + .5f);
+            } else {
+                h = mAttrs.height;
+            }
         } else {
-            w = mAttrs.width == mAttrs.MATCH_PARENT ? pw : mRequestedWidth;
-            h = mAttrs.height== mAttrs.MATCH_PARENT ? ph : mRequestedHeight;
+            if (mAttrs.width == WindowManager.LayoutParams.MATCH_PARENT) {
+                w = pw;
+            } else if (mEnforceSizeCompat) {
+                w = (int)(mRequestedWidth * mGlobalScale + .5f);
+            } else {
+                w = mRequestedWidth;
+            }
+            if (mAttrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
+                h = ph;
+            } else if (mEnforceSizeCompat) {
+                h = (int)(mRequestedHeight * mGlobalScale + .5f);
+            } else {
+                h = mRequestedHeight;
+            }
         }
 
         if (!mParentFrame.equals(pf)) {
@@ -412,37 +439,24 @@
         //System.out.println("In: w=" + w + " h=" + h + " container=" +
         //                   container + " x=" + mAttrs.x + " y=" + mAttrs.y);
 
+        float x, y;
+        if (mEnforceSizeCompat) {
+            x = mAttrs.x * mGlobalScale;
+            y = mAttrs.y * mGlobalScale;
+        } else {
+            x = mAttrs.x;
+            y = mAttrs.y;
+        }
+
         Gravity.apply(mAttrs.gravity, w, h, container,
-                (int) (mAttrs.x + mAttrs.horizontalMargin * pw),
-                (int) (mAttrs.y + mAttrs.verticalMargin * ph), frame);
+                (int) (x + mAttrs.horizontalMargin * pw),
+                (int) (y + mAttrs.verticalMargin * ph), frame);
 
         //System.out.println("Out: " + mFrame);
 
         // Now make sure the window fits in the overall display.
         Gravity.applyDisplay(mAttrs.gravity, df, frame);
 
-        int adjRight=0, adjBottom=0;
-
-        if (mEnforceSizeCompat) {
-            // Adjust window offsets by the scaling factor.
-            int xoff = (int)((frame.left-mService.mCompatibleScreenFrame.left)*mGlobalScale)
-                    - (frame.left-mService.mCompatibleScreenFrame.left);
-            int yoff = (int)((frame.top-mService.mCompatibleScreenFrame.top)*mGlobalScale)
-                    - (frame.top-mService.mCompatibleScreenFrame.top);
-            frame.offset(xoff, yoff);
-
-            // We are temporarily going to apply the compatibility scale
-            // to the window so that we can correctly associate it with the
-            // content and visible frame.
-            adjRight = frame.right - frame.left;
-            adjRight = (int)((adjRight)*mGlobalScale + .5f) - adjRight;
-            adjBottom = frame.bottom - frame.top;
-            adjBottom = (int)((adjBottom)*mGlobalScale + .5f) - adjBottom;
-            frame.right += adjRight;
-            frame.bottom += adjBottom;
-        }
-        mScaledFrame.set(frame);
-
         // Make sure the content and visible frames are inside of the
         // final window frame.
         if (content.left < frame.left) content.left = frame.left;
@@ -466,20 +480,17 @@
         visibleInsets.right = frame.right-visible.right;
         visibleInsets.bottom = frame.bottom-visible.bottom;
 
+        mCompatFrame.set(frame);
         if (mEnforceSizeCompat) {
-            // Scale the computed insets back to the window's compatibility
-            // coordinate space, and put frame back to correct size.
-            final float invScale = 1.0f/mGlobalScale;
-            contentInsets.left = (int)(contentInsets.left*invScale);
-            contentInsets.top = (int)(contentInsets.top*invScale);
-            contentInsets.right = (int)(contentInsets.right*invScale);
-            contentInsets.bottom = (int)(contentInsets.bottom*invScale);
-            visibleInsets.left = (int)(visibleInsets.left*invScale);
-            visibleInsets.top = (int)(visibleInsets.top*invScale);
-            visibleInsets.right = (int)(visibleInsets.right*invScale);
-            visibleInsets.bottom = (int)(visibleInsets.bottom*invScale);
-            frame.right -= adjRight;
-            frame.bottom -= adjBottom;
+            // If there is a size compatibility scale being applied to the
+            // window, we need to apply this to its insets so that they are
+            // reported to the app in its coordinate space.
+            contentInsets.scale(mInvGlobalScale);
+            visibleInsets.scale(mInvGlobalScale);
+
+            // Also the scaled frame that we report to the app needs to be
+            // adjusted to be in its coordinate space.
+            mCompatFrame.scale(mInvGlobalScale);
         }
 
         if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
@@ -592,12 +603,12 @@
             if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(
                 WindowManagerService.TAG, "Creating surface in session "
                 + mSession.mSurfaceSession + " window " + this
-                + " w=" + mFrame.width()
-                + " h=" + mFrame.height() + " format="
+                + " w=" + mCompatFrame.width()
+                + " h=" + mCompatFrame.height() + " format="
                 + mAttrs.format + " flags=" + flags);
 
-            int w = mFrame.width();
-            int h = mFrame.height();
+            int w = mCompatFrame.width();
+            int h = mCompatFrame.height();
             if ((mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
                 // for a scaled surface, we always want the requested
                 // size.
@@ -650,8 +661,9 @@
                 + ", animLayer=" + mAnimLayer);
             if (WindowManagerService.SHOW_TRANSACTIONS) {
                 Slog.i(WindowManagerService.TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
-                WindowManagerService.logSurface(this, "CREATE pos=(" + mFrame.left + "," + mFrame.top + ") (" +
-                        mFrame.width() + "x" + mFrame.height() + "), layer=" +
+                WindowManagerService.logSurface(this, "CREATE pos=(" + mFrame.left
+                        + "," + mFrame.top + ") (" +
+                        mCompatFrame.width() + "x" + mCompatFrame.height() + "), layer=" +
                         mAnimLayer + " HIDE", null);
             }
             Surface.openTransaction();
@@ -862,10 +874,10 @@
                 if (!mLocalAnimating) {
                     if (WindowManagerService.DEBUG_ANIM) Slog.v(
                         WindowManagerService.TAG, "Starting animation in " + this +
-                        " @ " + currentTime + ": ww=" + mScaledFrame.width() +
-                        " wh=" + mScaledFrame.height() +
+                        " @ " + currentTime + ": ww=" + mFrame.width() +
+                        " wh=" + mFrame.height() +
                         " dw=" + dw + " dh=" + dh + " scale=" + mService.mWindowAnimationScale);
-                    mAnimation.initialize(mScaledFrame.width(), mScaledFrame.height(), dw, dh);
+                    mAnimation.initialize(mFrame.width(), mFrame.height(), dw, dh);
                     mAnimation.setStartTime(currentTime);
                     mLocalAnimating = true;
                     mAnimating = true;
@@ -1035,8 +1047,9 @@
     void prelayout() {
         if (mEnforceSizeCompat) {
             mGlobalScale = mService.mCompatibleScreenScale;
+            mInvGlobalScale = 1/mGlobalScale;
         } else {
-            mGlobalScale = 1;
+            mGlobalScale = mInvGlobalScale = 1;
         }
     }
 
@@ -1334,35 +1347,9 @@
                 && mService.mPolicy.isScreenOn();
     }
 
-    void evalNeedsBackgroundFiller(int screenWidth, int screenHeight) {
-        mNeedsBackgroundFiller =
-             // only if the application is requesting compatible window
-             mEnforceSizeCompat &&
-             // only if it's visible
-             mHasDrawn && mViewVisibility == View.VISIBLE &&
-             // not needed if the compat window is actually full screen
-             !isFullscreenIgnoringCompat(screenWidth, screenHeight) &&
-             // and only if the application fills the compatible screen
-             mFrame.left <= mService.mCompatibleScreenFrame.left &&
-             mFrame.top <= mService.mCompatibleScreenFrame.top &&
-             mFrame.right >= mService.mCompatibleScreenFrame.right &&
-             mFrame.bottom >= mService.mCompatibleScreenFrame.bottom;
-    }
-
     boolean isFullscreen(int screenWidth, int screenHeight) {
-        if (mEnforceSizeCompat) {
-            return mFrame.left <= mService.mCompatibleScreenFrame.left &&
-                    mFrame.top <= mService.mCompatibleScreenFrame.top &&
-                    mFrame.right >= mService.mCompatibleScreenFrame.right &&
-                    mFrame.bottom >= mService.mCompatibleScreenFrame.bottom;
-        } else {
-            return isFullscreenIgnoringCompat(screenWidth, screenHeight);
-        }
-    }
-
-    boolean isFullscreenIgnoringCompat(int screenWidth, int screenHeight) {
-        return mScaledFrame.left <= 0 && mScaledFrame.top <= 0 &&
-                mScaledFrame.right >= screenWidth && mScaledFrame.bottom >= screenHeight;
+        return mFrame.left <= 0 && mFrame.top <= 0 &&
+                mFrame.right >= screenWidth && mFrame.bottom >= screenHeight;
     }
 
     void removeLocked() {
@@ -1492,38 +1479,28 @@
         return true;
     }
 
-    private static void applyScaledInsets(Region outRegion, Rect frame, Rect inset, float scale) {
-        if (scale != 1) {
-            outRegion.set(frame.left + (int)(inset.left*scale),
-                    frame.top + (int)(inset.top*scale),
-                    frame.right - (int)(inset.right*scale),
-                    frame.bottom - (int)(inset.bottom*scale));
-        } else {
-            outRegion.set(
-                    frame.left + inset.left, frame.top + inset.top,
-                    frame.right - inset.right, frame.bottom - inset.bottom);
-        }
+    private static void applyInsets(Region outRegion, Rect frame, Rect inset) {
+        outRegion.set(
+                frame.left + inset.left, frame.top + inset.top,
+                frame.right - inset.right, frame.bottom - inset.bottom);
     }
 
     public void getTouchableRegion(Region outRegion) {
-        final Rect frame = mScaledFrame;
+        final Rect frame = mFrame;
         switch (mTouchableInsets) {
             default:
             case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME:
                 outRegion.set(frame);
                 break;
             case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT:
-                applyScaledInsets(outRegion, frame, mGivenContentInsets, mGlobalScale);
+                applyInsets(outRegion, frame, mGivenContentInsets);
                 break;
             case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE:
-                applyScaledInsets(outRegion, frame, mGivenVisibleInsets, mGlobalScale);
+                applyInsets(outRegion, frame, mGivenVisibleInsets);
                 break;
             case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION: {
                 final Region givenTouchableRegion = mGivenTouchableRegion;
                 outRegion.set(givenTouchableRegion);
-                if (mGlobalScale != 1) {
-                    outRegion.scale(mGlobalScale);
-                }
                 outRegion.translate(frame.left, frame.top);
                 break;
             }
@@ -1586,8 +1563,7 @@
         }
         pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
                 pw.print(" h="); pw.print(mRequestedHeight);
-                pw.print(" mLayoutSeq="); pw.print(mLayoutSeq);
-                pw.print(" mNeedsBackgroundFiller="); pw.println(mNeedsBackgroundFiller);
+                pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
         if (mXOffset != 0 || mYOffset != 0) {
             pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
                     pw.print(" y="); pw.println(mYOffset);
@@ -1608,8 +1584,12 @@
                 pw.println();
         pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
                 pw.print(" last="); mLastFrame.printShortString(pw);
-                pw.print(" scaled="); mScaledFrame.printShortString(pw);
                 pw.println();
+        if (mEnforceSizeCompat) {
+            pw.print(prefix); pw.print("mCompatFrame="); mCompatFrame.printShortString(pw);
+                    pw.print(" last="); mLastCompatFrame.printShortString(pw);
+                    pw.println();
+        }
         pw.print(prefix); pw.print("mContainingFrame=");
                 mContainingFrame.printShortString(pw);
                 pw.print(" mParentFrame=");