Re-implementation of large screen support using window manager.
 * added background filler surface to fill the outer rim. Using the same layer as dim surface because
   they never co-exists (in the same window)
 * clean up the obsolete code in CompatibiltyMode/ViewRoot for support large screen support.
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index bcf95b6..0d00f21 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -173,7 +173,7 @@
      * {@hide}
      */
     public static final int ANY_DENSITY = -1;
-    private static final int[] ANY_DENSITIES_ARRAY = { ANY_DENSITY };
+    static final int[] ANY_DENSITIES_ARRAY = { ANY_DENSITY };
 
     /**
      * Flags associated with the application.  Any combination of
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 558b0c3..b293636 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -945,15 +945,25 @@
                         >= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) {
             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
         }
-        
+        int densities[] = null;
         int size = pkg.supportsDensityList.size();
         if (size > 0) {
-            int densities[] = pkg.supportsDensities = new int[size];
+            densities = pkg.supportsDensities = new int[size];
             List<Integer> densityList = pkg.supportsDensityList;
             for (int i = 0; i < size; i++) {
                 densities[i] = densityList.get(i);
             }
         }
+        /**
+         * TODO: enable this before code freeze. b/1967935
+         * *
+        if ((densities == null || densities.length == 0)
+                && (pkg.applicationInfo.targetSdkVersion
+                        >= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) {
+            pkg.supportsDensities = ApplicationInfo.ANY_DENSITIES_ARRAY;
+        }
+         */
+
         return pkg;
     }
 
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index dfe304d..ebe556e 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -51,18 +51,6 @@
     public static final int DEFAULT_PORTRAIT_HEIGHT = 480;
 
     /**
-     * The x-shift mode that controls the position of the content or the window under
-     * compatibility mode.
-     * {@see getTranslator}
-     * {@see Translator#mShiftMode}
-     */
-    private static final int X_SHIFT_NONE = 0;
-    private static final int X_SHIFT_CONTENT = 1;
-    private static final int X_SHIFT_AND_CLIP_CONTENT = 2;
-    private static final int X_SHIFT_WINDOW = 3;
-
-
-    /**
      *  A compatibility flags
      */
     private int mCompatibilityFlags;
@@ -106,20 +94,6 @@
      */
     public final int appFlags;
     
-    /**
-     * Window size in Compatibility Mode, in real pixels. This is updated by
-     * {@link DisplayMetrics#updateMetrics}.
-     */
-    private int mWidth;
-    private int mHeight;
-    
-    /**
-     * The x offset to center the window content. In X_SHIFT_WINDOW mode, the offset is added
-     * to the window's layout. In X_SHIFT_CONTENT/X_SHIFT_AND_CLIP_CONTENT mode, the offset
-     * is used to translate the Canvas.
-     */
-    private int mXOffset;
-
     public CompatibilityInfo(ApplicationInfo appInfo) {
         appFlags = appInfo.flags;
         
@@ -153,6 +127,7 @@
             applicationScale =
                     DisplayMetrics.DEVICE_DENSITY / (float) DisplayMetrics.DEFAULT_DENSITY;
         }
+
         applicationInvertedScale = 1.0f / applicationScale;
         if (applicationScale != 1.0f) {
             mCompatibilityFlags |= SCALING_REQUIRED;
@@ -181,23 +156,10 @@
     public CompatibilityInfo copy() {
         CompatibilityInfo info = new CompatibilityInfo(appFlags, mCompatibilityFlags,
                 applicationScale, applicationInvertedScale);
-        info.setVisibleRect(mXOffset, mWidth, mHeight);
         return info;
     }
  
     /**
-     * Sets the application's visible rect in compatibility mode.
-     * @param xOffset the application's x offset that is added to center the content.
-     * @param widthPixels the application's width in real pixels on the screen.
-     * @param heightPixels the application's height in real pixels on the screen.
-     */
-    public void setVisibleRect(int xOffset, int widthPixels, int heightPixels) {
-        this.mXOffset = xOffset; 
-        mWidth = widthPixels;
-        mHeight = heightPixels;
-    }
-    
-    /**
      * Sets expandable bit in the compatibility flag.
      */
     public void setExpandable(boolean expandable) {
@@ -222,6 +184,10 @@
         return (mCompatibilityFlags & SCALING_REQUIRED) != 0;
     }
     
+    public boolean supportsScreen() {
+        return (mCompatibilityFlags & CompatibilityInfo.EXPANDABLE) != 0;
+    }
+    
     @Override
     public String toString() {
         return "CompatibilityInfo{scale=" + applicationScale +
@@ -231,21 +197,6 @@
     /**
      * Returns the translator which can translate the coordinates of the window.
      * There are five different types of Translator.
-     * 
-     * 1) {@link CompatibilityInfo#X_SHIFT_AND_CLIP_CONTENT}
-     *   Shift and clip the content of the window at drawing time. Used for activities'
-     *   main window (with no gravity).
-     * 2) {@link CompatibilityInfo#X_SHIFT_CONTENT}
-     *   Shift the content of the window at drawing time. Used for windows that is created by
-     *   an application and expected to be aligned with the application window.
-     * 3) {@link CompatibilityInfo#X_SHIFT_WINDOW}
-     *   Create the window with adjusted x- coordinates. This is typically used 
-     *   in popup window, where it has to be placed relative to main window.
-     * 4) {@link CompatibilityInfo#X_SHIFT_NONE}
-     *   No adjustment required, such as dialog.
-     * 5) Same as X_SHIFT_WINDOW, but no scaling. This is used by {@link SurfaceView}, which
-     *  does not require scaling, but its window's location has to be adjusted.
-     * 
      * @param params the window's parameter
      */
     public Translator getTranslator(WindowManager.LayoutParams params) {
@@ -254,35 +205,11 @@
             if (DBG) Log.d(TAG, "no translation required");
             return null;
         }
-        
-        if ((mCompatibilityFlags & CompatibilityInfo.EXPANDABLE) == 0) {
-            if ((params.flags & WindowManager.LayoutParams.FLAG_NO_COMPATIBILITY_SCALING) != 0) {
-                if (DBG) Log.d(TAG, "translation for surface view selected");
-                return new Translator(X_SHIFT_WINDOW, false, 1.0f, 1.0f);
-            } else {
-                int shiftMode;
-                if (params.gravity == Gravity.NO_GRAVITY) {
-                    // For Regular Application window
-                    shiftMode = X_SHIFT_AND_CLIP_CONTENT;
-                    if (DBG) Log.d(TAG, "shift and clip translator");
-                } else if (params.width == WindowManager.LayoutParams.FILL_PARENT) {
-                    // For Regular Application window
-                    shiftMode = X_SHIFT_CONTENT;
-                    if (DBG) Log.d(TAG, "shift content translator");
-                } else if ((params.gravity & Gravity.LEFT) != 0 && params.x > 0) {
-                    shiftMode = X_SHIFT_WINDOW;
-                    if (DBG) Log.d(TAG, "shift window translator");
-                } else {
-                    shiftMode = X_SHIFT_NONE;
-                    if (DBG) Log.d(TAG, "no content/window translator");
-                }
-                return new Translator(shiftMode);
-            }
-        } else if (isScalingRequired()) {
-            return new Translator();
-        } else {
+        if (!isScalingRequired() ||
+            (params.flags & WindowManager.LayoutParams.FLAG_NO_COMPATIBILITY_SCALING) != 0) {
             return null;
         }
+        return new Translator();
     }
 
     /**
@@ -290,97 +217,48 @@
      * @hide
      */
     public class Translator {
-        final private int mShiftMode;
-        final public boolean scalingRequired;
         final public float applicationScale;
         final public float applicationInvertedScale;
         
         private Rect mContentInsetsBuffer = null;
-        private Rect mVisibleInsets = null;
+        private Rect mVisibleInsetsBuffer = null;
         
-        Translator(int shiftMode, boolean scalingRequired, float applicationScale,
-                float applicationInvertedScale) {
-            mShiftMode = shiftMode;
-            this.scalingRequired = scalingRequired;
+        Translator(float applicationScale, float applicationInvertedScale) {
             this.applicationScale = applicationScale;
             this.applicationInvertedScale = applicationInvertedScale;
         }
 
-        Translator(int shiftMode) {
-            this(shiftMode,
-                    isScalingRequired(),
-                    CompatibilityInfo.this.applicationScale,
-                    CompatibilityInfo.this.applicationInvertedScale);
-        }
-        
         Translator() {
-            this(X_SHIFT_NONE);
+            this(CompatibilityInfo.this.applicationScale,
+                    CompatibilityInfo.this.applicationInvertedScale);
         }
 
         /**
          * Translate the screen rect to the application frame.
          */
         public void translateRectInScreenToAppWinFrame(Rect rect) {
-            if (rect.isEmpty()) return; // skip if the window size is empty.
-            switch (mShiftMode) {
-                case X_SHIFT_AND_CLIP_CONTENT:
-                    rect.intersect(0, 0, mWidth, mHeight);
-                    break;
-                case X_SHIFT_CONTENT:
-                    rect.intersect(0, 0, mWidth + mXOffset, mHeight);
-                    break;
-                case X_SHIFT_WINDOW:
-                case X_SHIFT_NONE:
-                    break;
-            }
-            if (scalingRequired) {
-                rect.scale(applicationInvertedScale);
-            }
+            rect.scale(applicationInvertedScale);
         }
 
         /**
          * Translate the region in window to screen. 
          */
         public void translateRegionInWindowToScreen(Region transparentRegion) {
-            switch (mShiftMode) {
-                case X_SHIFT_AND_CLIP_CONTENT:
-                case X_SHIFT_CONTENT:
-                    transparentRegion.scale(applicationScale);
-                    transparentRegion.translate(mXOffset, 0);
-                    break;
-                case X_SHIFT_WINDOW:
-                case X_SHIFT_NONE:
-                    transparentRegion.scale(applicationScale);
-            }
+            transparentRegion.scale(applicationScale);
         }
 
         /**
          * Apply translation to the canvas that is necessary to draw the content.
          */
         public void translateCanvas(Canvas canvas) {
-            if (mShiftMode == X_SHIFT_CONTENT ||
-                    mShiftMode == X_SHIFT_AND_CLIP_CONTENT) {
-                // TODO: clear outside when rotation is changed.
-
-                // Translate x-offset only when the content is shifted.
-                canvas.translate(mXOffset, 0);
-            }
-            if (scalingRequired) {
-                canvas.scale(applicationScale, applicationScale);
-            }
+            canvas.scale(applicationScale, applicationScale);
         }
 
         /**
          * Translate the motion event captured on screen to the application's window.
          */
         public void translateEventInScreenToAppWindow(MotionEvent event) {
-            if (mShiftMode == X_SHIFT_CONTENT ||
-                    mShiftMode == X_SHIFT_AND_CLIP_CONTENT) {
-                event.translate(-mXOffset, 0);
-            }
-            if (scalingRequired) {
-                event.scale(applicationInvertedScale);
-            }
+            event.scale(applicationInvertedScale);
         }
 
         /**
@@ -388,62 +266,21 @@
          * Screen's view.
          */
         public void translateWindowLayout(WindowManager.LayoutParams params) {
-            switch (mShiftMode) {
-                case X_SHIFT_NONE:
-                case X_SHIFT_AND_CLIP_CONTENT:
-                case X_SHIFT_CONTENT:
-                    params.scale(applicationScale);
-                    break;
-                case X_SHIFT_WINDOW:
-                    params.scale(applicationScale);
-                    params.x += mXOffset;
-                    break;
-            }
+            params.scale(applicationScale);
         }
         
         /**
          * Translate a Rect in application's window to screen.
          */
         public void translateRectInAppWindowToScreen(Rect rect) {
-            // TODO Auto-generated method stub
-            if (scalingRequired) {
-                rect.scale(applicationScale);
-            }
-            switch(mShiftMode) {
-                case X_SHIFT_NONE:
-                case X_SHIFT_WINDOW:
-                    break;
-                case X_SHIFT_CONTENT:
-                case X_SHIFT_AND_CLIP_CONTENT:
-                    rect.offset(mXOffset, 0);
-                    break;
-            }
+            rect.scale(applicationScale);
         }
  
         /**
          * Translate a Rect in screen coordinates into the app window's coordinates.
          */
         public void translateRectInScreenToAppWindow(Rect rect) {
-            switch (mShiftMode) {
-                case X_SHIFT_NONE:
-                case X_SHIFT_WINDOW:
-                    break;
-                case X_SHIFT_CONTENT: {
-                    rect.intersects(mXOffset, 0, rect.right, rect.bottom);
-                    int dx = Math.min(mXOffset, rect.left);
-                    rect.offset(-dx, 0);
-                    break;
-                }
-                case X_SHIFT_AND_CLIP_CONTENT: {
-                    rect.intersects(mXOffset, 0, mWidth + mXOffset, mHeight);
-                    int dx = Math.min(mXOffset, rect.left);
-                    rect.offset(-dx, 0);
-                    break;
-                }
-            }
-            if (scalingRequired) {
-                rect.scale(applicationInvertedScale);
-            }
+            rect.scale(applicationInvertedScale);
         }
 
         /**
@@ -451,19 +288,7 @@
          * @param params
          */
         public void translateLayoutParamsInAppWindowToScreen(LayoutParams params) {
-            if (scalingRequired) {
-                params.scale(applicationScale);
-            }
-            switch (mShiftMode) {
-                // the window location on these mode does not require adjustmenet.
-                case X_SHIFT_NONE:
-                case X_SHIFT_WINDOW:
-                    break;
-                case X_SHIFT_CONTENT:
-                case X_SHIFT_AND_CLIP_CONTENT:
-                    params.x += mXOffset;
-                    break;
-            }
+            params.scale(applicationScale);
         }
 
         /**
@@ -482,10 +307,31 @@
          * the internal buffer for content insets to avoid extra object allocation.
          */
         public Rect getTranslatedVisbileInsets(Rect visibleInsets) {
-            if (mVisibleInsets == null) mVisibleInsets = new Rect();
-            mVisibleInsets.set(visibleInsets);
-            translateRectInAppWindowToScreen(mVisibleInsets);
-            return mVisibleInsets;
+            if (mVisibleInsetsBuffer == null) mVisibleInsetsBuffer = new Rect();
+            mVisibleInsetsBuffer.set(visibleInsets);
+            translateRectInAppWindowToScreen(mVisibleInsetsBuffer);
+            return mVisibleInsetsBuffer;
+        }
+    }
+
+    /**
+     * Returns the frame Rect for applications runs under compatibility mode.
+     *
+     * @param dm the display metrics used to compute the frame size.
+     * @param orientation the orientation of the screen.
+     * @param outRect the output parameter which will contain the result.
+     */
+    public static void updateCompatibleScreenFrame(DisplayMetrics dm, int orientation,
+            Rect outRect) {
+        int width = dm.widthPixels;
+        int portraitHeight = (int) (DEFAULT_PORTRAIT_HEIGHT * dm.density);
+        int portraitWidth = (int) (DEFAULT_PORTRAIT_WIDTH * dm.density);
+        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
+            int xOffset = (width - portraitHeight) / 2 ;
+            outRect.set(xOffset, 0, xOffset + portraitHeight, portraitWidth);
+        } else {
+            int xOffset = (width - portraitWidth) / 2 ;
+            outRect.set(xOffset, 0, xOffset + portraitWidth, portraitHeight);
         }
     }
 }
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index 4179edb..9071bf0 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -109,7 +109,6 @@
      */
     public void updateMetrics(CompatibilityInfo compatibilityInfo, int orientation,
             int screenLayout) {
-        int xOffset = 0;
         if (!compatibilityInfo.isConfiguredExpandable()) {
             // Note: this assume that configuration is updated before calling
             // updateMetrics method.
@@ -142,7 +141,6 @@
                 
                 if (defaultWidth < widthPixels) {
                     // content/window's x offset in original pixels
-                    xOffset = ((widthPixels - defaultWidth) / 2);
                     widthPixels = defaultWidth;
                 }
                 if (defaultHeight < heightPixels) {
@@ -154,7 +152,6 @@
                 compatibilityInfo.setExpandable(true);
             }
         }
-        compatibilityInfo.setVisibleRect(xOffset, widthPixels, heightPixels);
         if (compatibilityInfo.isScalingRequired()) {
             float invertedRatio = compatibilityInfo.applicationInvertedScale;
             density *= invertedRatio;
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 45b0f0a..ff1eb53 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -306,7 +306,7 @@
 
         // Use original size if the app specified the size of the view,
         // and let the flinger to scale up.
-        if (mRequestedWidth <= 0 && mTranslator != null && mTranslator.scalingRequired) {
+        if (mRequestedWidth <= 0 && mTranslator != null) {
             myWidth *= appScale;
             myHeight *= appScale;
         }
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 6f6e224..6bcb135 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -385,6 +385,7 @@
             if (mView == null) {
                 mView = view;
                 mWindowAttributes.copyFrom(attrs);
+                attrs = mWindowAttributes;
 
                 CompatibilityInfo compatibilityInfo =
                         mView.getContext().getResources().getCompatibilityInfo();
@@ -397,11 +398,14 @@
                 }
                 if (DEBUG_LAYOUT) Log.d(TAG, "WindowLayout in setView:" + attrs);
 
+                if (!compatibilityInfo.supportsScreen()) {
+                    attrs.flags |= WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
+                }
+
                 mSoftInputMode = attrs.softInputMode;
                 mWindowAttributesChanged = true;
                 mAttachInfo.mRootView = view;
-                mAttachInfo.mScalingRequired =
-                        mTranslator == null ? false : mTranslator.scalingRequired;
+                mAttachInfo.mScalingRequired = mTranslator == null ? false : true;
                 mAttachInfo.mApplicationScale =
                         mTranslator == null ? 1.0f : mTranslator.applicationScale;
                 if (panelParentView != null) {
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index bdb86d7..e96a15b 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -484,11 +484,19 @@
         public static final int FLAG_SHOW_WHEN_LOCKED = 0x00080000;
 
         /** Window flag: special flag to let a window ignore the compatibility scaling.
-         * This is used by SurfaceView to create a window that does not scale the content.
+         * This is used by SurfaceView to pass this info into ViewRoot, and not used
+         * by WindowManager.
          *
          * {@hide} */
         public static final int FLAG_NO_COMPATIBILITY_SCALING = 0x00100000;
 
+        /** Window flag: special flag to limit the size of the window to be
+         * original size ([320x480] x density). Used to create window for applications
+         * running under compatibility mode.
+         *
+         * {@hide} */
+        public static final int FLAG_COMPATIBLE_WINDOW = 0x00200000;
+
         /** Window flag: a special option intended for system dialogs.  When
          * this flag is set, the window will demand focus unconditionally when
          * it is created.
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 2dd70ef..ad882a9 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -53,6 +53,7 @@
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
+import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.graphics.Matrix;
 import android.graphics.PixelFormat;
@@ -417,7 +418,13 @@
 
     final Configuration mTempConfiguration = new Configuration();
     int screenLayout = Configuration.SCREENLAYOUT_UNDEFINED;
-    
+
+    // The frame use to limit the size of the app running in compatibility mode.
+    Rect mCompatibleScreenFrame = new Rect();
+    // The surface used to fill the outer rim of the app running in compatibility mode.
+    Surface mBackgroundFillerSurface = null;
+    boolean mBackgroundFillerShown = false;
+
     public static WindowManagerService main(Context context,
             PowerManagerService pm, boolean haveInputMethods) {
         WMThread thr = new WMThread(context, pm, haveInputMethods);
@@ -3738,12 +3745,14 @@
         }
         config.orientation = orientation;
         
+        DisplayMetrics dm = new DisplayMetrics();
+        mDisplay.getMetrics(dm);
+        CompatibilityInfo.updateCompatibleScreenFrame(dm, orientation, mCompatibleScreenFrame);
+
         if (screenLayout == Configuration.SCREENLAYOUT_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.
-            DisplayMetrics dm = new DisplayMetrics();
-            mDisplay.getMetrics(dm);
             int longSize = dw;
             int shortSize = dh;
             if (longSize < shortSize) {
@@ -3753,7 +3762,7 @@
             }
             longSize = (int)(longSize/dm.density);
             shortSize = (int)(shortSize/dm.density);
-            
+
             // These semi-magic numbers define our compatibility modes for
             // applications with different screens.  Don't change unless you
             // make sure to test lots and lots of apps!
@@ -5845,8 +5854,19 @@
         public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) {
             mHaveFrame = true;
 
-            final int pw = pf.right-pf.left;
-            final int ph = pf.bottom-pf.top;
+            final Rect container = mContainingFrame;
+            container.set(pf);
+
+            final Rect display = mDisplayFrame;
+            display.set(df);
+
+            if ((mAttrs.flags & WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW) != 0) {
+                container.intersect(mCompatibleScreenFrame);
+                display.intersect(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) {
@@ -5857,12 +5877,6 @@
                 h = mAttrs.height== mAttrs.FILL_PARENT ? ph : mRequestedHeight;
             }
 
-            final Rect container = mContainingFrame;
-            container.set(pf);
-
-            final Rect display = mDisplayFrame;
-            display.set(df);
-
             final Rect content = mContentFrame;
             content.set(cf);
 
@@ -5882,7 +5896,7 @@
 
             // Now make sure the window fits in the overall display.
             Gravity.applyDisplay(mAttrs.gravity, df, frame);
-
+            
             // Make sure the content and visible frames are inside of the
             // final window frame.
             if (content.left < frame.left) content.left = frame.left;
@@ -6573,16 +6587,29 @@
             return false;
         }
 
-        boolean isFullscreenOpaque(int screenWidth, int screenHeight) {
-            if (mAttrs.format != PixelFormat.OPAQUE || mSurface == null
-                    || mAnimation != null || mDrawPending || mCommitDrawPending) {
-                return false;
-            }
-            if (mFrame.left <= 0 && mFrame.top <= 0 &&
-                mFrame.right >= screenWidth && mFrame.bottom >= screenHeight) {
-                return true;
-            }
-            return false;
+        /**
+         * Return true if the window is opaque and fully drawn.
+         */
+        boolean isOpaqueDrawn() {
+            return mAttrs.format == PixelFormat.OPAQUE && mSurface != null
+                    && mAnimation == null && !mDrawPending && !mCommitDrawPending;
+        }
+
+        boolean needsBackgroundFiller(int screenWidth, int screenHeight) {
+            return
+                 // only if the application is requesting compatible window
+                 (mAttrs.flags & mAttrs.FLAG_COMPATIBLE_WINDOW) != 0 &&
+                 // and only if the application wanted to fill the screen
+                 mAttrs.width == mAttrs.FILL_PARENT &&
+                 mAttrs.height == mAttrs.FILL_PARENT &&
+                 // and only if the screen is bigger
+                 ((mFrame.right - mFrame.right) < screenWidth ||
+                         (mFrame.bottom - mFrame.top) < screenHeight);
+        }
+
+        boolean isFullscreen(int screenWidth, int screenHeight) {
+            return mFrame.left <= 0 && mFrame.top <= 0 &&
+                mFrame.right >= screenWidth && mFrame.bottom >= screenHeight;
         }
 
         void removeLocked() {
@@ -8102,6 +8129,7 @@
             boolean dimming = false;
             boolean covered = false;
             boolean syswin = false;
+            boolean backgroundFillerShown = false;
 
             for (i=N-1; i>=0; i--) {
                 WindowState w = (WindowState)mWindows.get(i);
@@ -8371,11 +8399,39 @@
                             syswin = true;
                         }
                     }
-                    if (w.isFullscreenOpaque(dw, dh)) {
+
+                    boolean opaqueDrawn = w.isOpaqueDrawn();
+                    if (opaqueDrawn && w.isFullscreen(dw, dh)) {
                         // This window completely covers everything behind it,
                         // so we want to leave all of them as unblurred (for
                         // performance reasons).
                         obscured = true;
+                    } else if (opaqueDrawn && w.needsBackgroundFiller(dw, dh)) {
+                        if (SHOW_TRANSACTIONS) Log.d(TAG, "showing background filler");
+                                                // This window is in compatibility mode, and needs background filler. 
+                        obscured = true;
+                        if (mBackgroundFillerSurface == null) {
+                            try {
+                                mBackgroundFillerSurface = new Surface(mFxSession, 0,
+                                        0, dw, dh,
+                                        PixelFormat.OPAQUE,
+                                        Surface.FX_SURFACE_NORMAL);
+                            } catch (Exception e) {
+                                Log.e(TAG, "Exception creating filler surface", e);
+                            }
+                        }
+                        try {
+                            mBackgroundFillerSurface.setPosition(0, 0);
+                            mBackgroundFillerSurface.setSize(dw, dh);
+                            // Using the same layer as Dim because they will never be shown at the
+                            // same time.
+                            mBackgroundFillerSurface.setLayer(w.mAnimLayer - 1);
+                            mBackgroundFillerSurface.show();
+                        } catch (RuntimeException e) {
+                            Log.e(TAG, "Exception showing filler surface");
+                        }
+                        backgroundFillerShown = true;
+                        mBackgroundFillerShown = true;
                     } else if (canBeSeen && !obscured &&
                             (attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) {
                         if (localLOGV) Log.v(TAG, "Win " + w
@@ -8472,6 +8528,16 @@
                     }
                 }
             }
+            
+            if (backgroundFillerShown == false && mBackgroundFillerShown) {
+                mBackgroundFillerShown = false;
+                if (SHOW_TRANSACTIONS) Log.d(TAG, "hiding background filler");
+                try {
+                    mBackgroundFillerSurface.hide();
+                } catch (RuntimeException e) {
+                    Log.e(TAG, "Exception hiding filler surface", e);
+                }
+            }
 
             if (!dimming && mDimShown) {
                 // Time to hide the dim surface...  start fading.