diff options
| -rw-r--r-- | core/java/android/content/pm/ApplicationInfo.java | 2 | ||||
| -rw-r--r-- | core/java/android/content/pm/PackageParser.java | 14 | ||||
| -rw-r--r-- | core/java/android/content/res/CompatibilityInfo.java | 244 | ||||
| -rw-r--r-- | core/java/android/util/DisplayMetrics.java | 3 | ||||
| -rw-r--r-- | core/java/android/view/SurfaceView.java | 2 | ||||
| -rw-r--r-- | core/java/android/view/ViewRoot.java | 8 | ||||
| -rw-r--r-- | core/java/android/view/WindowManager.java | 10 | ||||
| -rw-r--r-- | services/java/com/android/server/WindowManagerService.java | 114 | 
8 files changed, 164 insertions, 233 deletions
| 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 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {       * {@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 @@ public class PackageParser {                          >= 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 class CompatibilityInfo {      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 class CompatibilityInfo {       */      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 @@ public class CompatibilityInfo {              applicationScale =                      DisplayMetrics.DEVICE_DENSITY / (float) DisplayMetrics.DEFAULT_DENSITY;          } +          applicationInvertedScale = 1.0f / applicationScale;          if (applicationScale != 1.0f) {              mCompatibilityFlags |= SCALING_REQUIRED; @@ -181,23 +156,10 @@ public class CompatibilityInfo {      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 @@ public class CompatibilityInfo {          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 @@ public class CompatibilityInfo {      /**       * 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 @@ public class CompatibilityInfo {              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 @@ public class CompatibilityInfo {       * @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 @@ public class CompatibilityInfo {           * 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 @@ public class CompatibilityInfo {           * @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 @@ public class CompatibilityInfo {           * 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 class DisplayMetrics {       */      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 @@ public class DisplayMetrics {                  if (defaultWidth < widthPixels) {                      // content/window's x offset in original pixels -                    xOffset = ((widthPixels - defaultWidth) / 2);                      widthPixels = defaultWidth;                  }                  if (defaultHeight < heightPixels) { @@ -154,7 +152,6 @@ public class DisplayMetrics {                  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 @@ public class SurfaceView extends View {          // 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 @@ public final class ViewRoot extends Handler implements ViewParent,              if (mView == null) {                  mView = view;                  mWindowAttributes.copyFrom(attrs); +                attrs = mWindowAttributes;                  CompatibilityInfo compatibilityInfo =                          mView.getContext().getResources().getCompatibilityInfo(); @@ -397,11 +398,14 @@ public final class ViewRoot extends Handler implements ViewParent,                  }                  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 interface WindowManager extends ViewManager {          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.app.IActivityManager;  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 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo      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 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo          }          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 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo              }              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 class WindowManagerService extends IWindowManager.Stub implements Watchdo          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 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo                  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 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo              // 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 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo              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 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo              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 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo                              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 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo                      }                  }              } +             +            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. | 
