Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 958b9adc authored by Dianne Hackborn's avatar Dianne Hackborn Committed by The Android Open Source Project
Browse files

AI 143899: am: CL 143896 Fix issue #1748954 and #1737952:

  #1748954 (New status bar fades into all white background): FrameLayout wasn't updating its foreground drawable when its padding changed, which would happen as the status bar is shown and hidden.  To fix this I also ended up fixing a problem in the view debug stuff where we couldn't get a bitmap for a view that is the full screen size because it is too big...  actually I just went ahead and added another function to snapshot the view hierarchy which works a lot better for us anyway.
  #1737952 (Home screen icons overlap with the notification bar after exiting any camera app): Originally I punted this because it only happened in rare situations, but now that home is always portrait it happens a lot more so it is more important to fix.  This involved a few things to clean up hiding/showing the status bar:
  - We now determine when to hide and show it during layout, which allows us to do this at the time it is actually needed rather than during animation after we can actually catch it for the initial display of a window.  This required tweaking the layout API so the policy can request a second layout pass if needed.
  - When doing layout, we are now much more aggressive about skipping the layout of windows.  Basically anything that we know will be hidden in the near future is ignored for layout, so that it doesn't glitch as it is transfered out of the screen.  The theory being that it is better to leave it as it was originally placed while we are transitioning it out, than to switch it to something slightly more correct.
  Original author: hackbod
  Merged from: //branches/cupcake/...

Automated import of CL 143899
parent d928d683
Loading
Loading
Loading
Loading
+57 −1
Original line number Diff line number Diff line
@@ -5535,7 +5535,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback {
                (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE);

            if (width <= 0 || height <= 0 ||
                    (width * height * (opaque ? 2 : 4) >= // Projected bitmap size in bytes
                    (width * height * (opaque ? 2 : 4) > // Projected bitmap size in bytes
                            ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) {
                destroyDrawingCache();
                return;
@@ -5631,6 +5631,62 @@ public class View implements Drawable.Callback, KeyEvent.Callback {
        }
    }

    /**
     * Create a snapshot of the view into a bitmap.  We should probably make
     * some form of this public, but should think about the API.
     */
    /*package*/ Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor) {
        final int width = mRight - mLeft;
        final int height = mBottom - mTop;

        Bitmap bitmap = Bitmap.createBitmap(width, height, quality);
        if (bitmap == null) {
            throw new OutOfMemoryError();
        }

        Canvas canvas;
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) {
            canvas = attachInfo.mCanvas;
            if (canvas == null) {
                canvas = new Canvas();
            }
            canvas.setBitmap(bitmap);
            // Temporarily clobber the cached Canvas in case one of our children
            // is also using a drawing cache. Without this, the children would
            // steal the canvas by attaching their own bitmap to it and bad, bad
            // things would happen (invisible views, corrupted drawings, etc.)
            attachInfo.mCanvas = null;
        } else {
            // This case should hopefully never or seldom happen
            canvas = new Canvas(bitmap);
        }

        if ((backgroundColor&0xff000000) != 0) {
            bitmap.eraseColor(backgroundColor);
        }

        computeScroll();
        final int restoreCount = canvas.save();
        canvas.translate(-mScrollX, -mScrollY);

        // Fast path for layouts with no backgrounds
        if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
            dispatchDraw(canvas);
        } else {
            draw(canvas);
        }

        canvas.restoreToCount(restoreCount);

        if (attachInfo != null) {
            // Restore the cached Canvas for our siblings
            attachInfo.mCanvas = canvas;
        }
        
        return bitmap;
    }

    /**
     * Indicates whether this View is currently in edit mode. A View is usually
     * in edit mode when displayed within a developer tool. For instance, if
+12 −21
Original line number Diff line number Diff line
@@ -741,22 +741,18 @@ public class ViewDebug {
            final CountDownLatch latch = new CountDownLatch(1);
            final Bitmap[] cache = new Bitmap[1];

            final boolean hasCache = captureView.isDrawingCacheEnabled();
            final boolean willNotCache = captureView.willNotCacheDrawing();

            if (willNotCache) {
                // TODO: Should happen on the UI thread
                captureView.setWillNotCacheDrawing(false);
            }

            root.post(new Runnable() {
                public void run() {
                    try {
                        if (!hasCache) {
                            captureView.buildDrawingCache();
                        cache[0] = captureView.createSnapshot(
                                Bitmap.Config.ARGB_8888, 0);
                    } catch (OutOfMemoryError e) {
                        try {
                            cache[0] = captureView.createSnapshot(
                                    Bitmap.Config.ARGB_4444, 0);
                        } catch (OutOfMemoryError e2) {
                            Log.w("View", "Out of memory for bitmap");
                        }

                        cache[0] = captureView.getDrawingCache();
                    } finally {
                        latch.countDown();
                    }
@@ -776,20 +772,15 @@ public class ViewDebug {
                        if (out != null) {
                            out.close();
                        }
                        cache[0].recycle();
                    }
                } else {
                    Log.w("View", "Failed to create capture bitmap!");
                    clientStream.close();
                }
            } catch (InterruptedException e) {
                Log.w("View", "Could not complete the capture of the view " + captureView);
                Thread.currentThread().interrupt();
            } finally {
                if (willNotCache) {
                    // TODO: Should happen on the UI thread
                    captureView.setWillNotCacheDrawing(true);
                }
                if (!hasCache) {
                    // TODO: Should happen on the UI thread                    
                    captureView.destroyDrawingCache();
                }
            }
        }
    }
+4 −1
Original line number Diff line number Diff line
@@ -580,8 +580,11 @@ public interface WindowManagerPolicy {
     * Called when layout of the windows is finished.  After this function has
     * returned, all windows given to layoutWindow() <em>must</em> have had a
     * frame assigned.
     *  
     * @return Return true if layout state may have changed (so that another 
     *         layout will be performed).
     */
    public void finishLayoutLw();
    public boolean finishLayoutLw();

    /**
     * Called when animation of the windows is about to start.
+37 −17
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.graphics.Region;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.Gravity;
import android.widget.RemoteViews.RemoteView;
@@ -45,21 +46,31 @@ import android.widget.RemoteViews.RemoteView;
 */
@RemoteView
public class FrameLayout extends ViewGroup {
    @ViewDebug.ExportedProperty
    boolean mMeasureAllChildren = false;

    @ViewDebug.ExportedProperty
    private Drawable mForeground;
    @ViewDebug.ExportedProperty
    private int mForegroundPaddingLeft = 0;
    @ViewDebug.ExportedProperty
    private int mForegroundPaddingTop = 0;
    @ViewDebug.ExportedProperty
    private int mForegroundPaddingRight = 0;
    @ViewDebug.ExportedProperty
    private int mForegroundPaddingBottom = 0;

    private final Rect mSelfBounds = new Rect();
    private final Rect mOverlayBounds = new Rect();
    @ViewDebug.ExportedProperty
    private int mForegroundGravity = Gravity.FILL;

    /** {@hide} */
    @ViewDebug.ExportedProperty
    protected boolean mForegroundInPadding = true;

    boolean mForegroundBoundsChanged = false;
    
    public FrameLayout(Context context) {
        super(context);
    }
@@ -269,6 +280,8 @@ public class FrameLayout extends ViewGroup {
        final int parentTop = mPaddingTop + mForegroundPaddingTop;
        final int parentBottom = bottom - top - mPaddingBottom - mForegroundPaddingBottom;

        mForegroundBoundsChanged = true;
        
        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() != GONE) {
@@ -328,12 +341,27 @@ public class FrameLayout extends ViewGroup {
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mForegroundBoundsChanged = true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);

        if (mForeground != null) {
            final Drawable foreground = mForeground;
            if (mForegroundBoundsChanged) {
                mForegroundBoundsChanged = false;
                if (foreground != null) {
                    final Rect selfBounds = mSelfBounds;
                    final Rect overlayBounds = mOverlayBounds;

                    final int w = mRight-mLeft;
                    final int h = mBottom-mTop;
                    
                    if (mForegroundInPadding) {
                        selfBounds.set(0, 0, w, h);
                    } else {
@@ -346,15 +374,7 @@ public class FrameLayout extends ViewGroup {
                }
            }
            
    /**
     * {@inheritDoc}
     */
    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);

        if (mForeground != null) {
            mForeground.draw(canvas);
            foreground.draw(canvas);
        }
    }

+21 −6
Original line number Diff line number Diff line
@@ -7485,11 +7485,12 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
        final int dh = mDisplay.getHeight();

        final int N = mWindows.size();
        int repeats = 0;
        int i;

        // FIRST LOOP: Perform a layout, if needed.
        
        if (mLayoutNeeded) {
        while (mLayoutNeeded) {
            mPolicy.beginLayoutLw(dw, dh);

            // First perform layout of any root windows (not attached
@@ -7498,9 +7499,17 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
            for (i = N-1; i >= 0; i--) {
                WindowState win = (WindowState) mWindows.get(i);

                boolean gone = win.mViewVisibility == View.GONE
                // Don't do layout of a window if it is not visible, or
                // soon won't be visible, to avoid wasting time and funky
                // changes while a window is animating away.
                final AppWindowToken atoken = win.mAppToken;
                final boolean gone = win.mViewVisibility == View.GONE
                        || !win.mRelayoutCalled
                        || win.mRootToken.hidden;
                        || win.mRootToken.hidden
                        || (atoken != null && atoken.hiddenRequested)
                        || !win.mPolicyVisibility
                        || win.mAttachedHidden
                        || win.mExiting || win.mDestroying;

                // If this view is GONE, then skip it -- keep the current
                // frame, and let the caller know so they can ignore it
@@ -7536,8 +7545,14 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
                }
            }

            mPolicy.finishLayoutLw();
            if (!mPolicy.finishLayoutLw()) {
                mLayoutNeeded = false;
            } else if (repeats > 2) {
                Log.w(TAG, "Layout repeat aborted after too many iterations");
                mLayoutNeeded = false;
            } else {
                repeats++;
            }
        }
    }