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

Commit 5bef2fcc authored by Jorim Jaggi's avatar Jorim Jaggi Committed by Android (Google) Code Review
Browse files

Merge changes If489d2ba,I1fe12181,Ieb4f586a,Ib51163a0,Ifdfcf3ad, ...

* changes:
  Hide swipe-up gesture behind tuner flag
  When long pressing recents and already docked, undock
  More multi-window fixes
  Use separate flag to suppress resizes
  Only treat "null" bounds as fullscreen
  Exclude stable insets from task config
  Fix bug where surface was not clipped off during resizing
  Fix crash in SysUI when configuration changes
parents 5df0661d 8f2a44f9
Loading
Loading
Loading
Loading
+10 −4
Original line number Diff line number Diff line
@@ -1811,7 +1811,9 @@ public final class ViewRootImpl implements ViewParent,
                final boolean dragResizing = freeformResizing || dockedResizing;
                if (mDragResizing != dragResizing) {
                    if (dragResizing) {
                        startDragResizing(mPendingBackDropFrame);
                        startDragResizing(mPendingBackDropFrame,
                                mWinFrame.equals(mPendingBackDropFrame), mPendingVisibleInsets,
                                mPendingStableInsets);
                        mResizeMode = freeformResizing
                                ? RESIZE_MODE_FREEFORM
                                : RESIZE_MODE_DOCKED_DIVIDER;
@@ -5845,9 +5847,11 @@ public final class ViewRootImpl implements ViewParent,
        // Tell all listeners that we are resizing the window so that the chrome can get
        // updated as fast as possible on a separate thread,
        if (mDragResizing) {
            boolean fullscreen = frame.equals(backDropFrame);
            synchronized (mWindowCallbacks) {
                for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
                    mWindowCallbacks.get(i).onWindowSizeIsChanging(backDropFrame);
                    mWindowCallbacks.get(i).onWindowSizeIsChanging(backDropFrame, fullscreen,
                            visibleInsets, stableInsets);
                }
            }
        }
@@ -7046,12 +7050,14 @@ public final class ViewRootImpl implements ViewParent,
    /**
     * Start a drag resizing which will inform all listeners that a window resize is taking place.
     */
    private void startDragResizing(Rect initialBounds) {
    private void startDragResizing(Rect initialBounds, boolean fullscreen, Rect systemInsets,
            Rect stableInsets) {
        if (!mDragResizing) {
            mDragResizing = true;
            synchronized (mWindowCallbacks) {
                for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
                    mWindowCallbacks.get(i).onWindowDragResizeStart(initialBounds);
                    mWindowCallbacks.get(i).onWindowDragResizeStart(initialBounds, fullscreen,
                            systemInsets, stableInsets);
                }
            }
            mFullRedrawNeeded = true;
+14 −4
Original line number Diff line number Diff line
@@ -28,20 +28,30 @@ import android.graphics.Rect;
public interface WindowCallbacks {
    /**
     * Called by the system when the window got changed by the user, before the layouter got called.
     * It can be used to perform a "quick and dirty" resize which should never take more then 4ms to
     * complete.
     * It also gets called when the insets changed, or when the window switched between a fullscreen
     * layout or a non-fullscreen layout. It can be used to perform a "quick and dirty" resize which
     * should never take more then 4ms to complete.
     *
     * <p>At the time the layouting has not happened yet.
     *
     * @param newBounds The new window frame bounds.
     * @param fullscreen Whether the window is currently drawing in fullscreen.
     * @param systemInsets The current visible system insets for the window.
     * @param stableInsets The stable insets for the window.
     */
    void onWindowSizeIsChanging(Rect newBounds);
    void onWindowSizeIsChanging(Rect newBounds, boolean fullscreen, Rect systemInsets,
            Rect stableInsets);

    /**
     * Called when a drag resize starts.
     *
     * @param initialBounds The initial bounds where the window will be.
     * @param fullscreen Whether the window is currently drawing in fullscreen.
     * @param systemInsets The current visible system insets for the window.
     * @param stableInsets The stable insets for the window.
     */
    void onWindowDragResizeStart(Rect initialBounds);
    void onWindowDragResizeStart(Rect initialBounds, boolean fullscreen, Rect systemInsets,
            Rect stableInsets);

    /**
     * Called when a drag resize ends.
+5 −0
Original line number Diff line number Diff line
@@ -268,4 +268,9 @@ public abstract class WindowManagerInternal {

    /** Returns true if the stack with the input Id is currently visible. */
    public abstract boolean isStackVisible(int stackId);

    /**
     * @return True if and only if the docked divider is currently in resize mode.
     */
    public abstract boolean isDockedDividerResizing();
}
+90 −24
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@ import android.view.Choreographer;
import android.view.DisplayListCanvas;
import android.view.RenderNode;
import android.view.ThreadedRenderer;
import android.view.View;

/**
 * The thread which draws a fill in background while the app is resizing in areas where the app
@@ -49,6 +48,7 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame

    private final Rect mOldTargetRect = new Rect();
    private final Rect mNewTargetRect = new Rect();

    private Choreographer mChoreographer;

    // Cached size values from the last render for the case that the view hierarchy is gone
@@ -66,15 +66,23 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
    private Drawable mUserCaptionBackgroundDrawable;
    private Drawable mResizingBackgroundDrawable;
    private ColorDrawable mStatusBarColor;
    private ColorDrawable mNavigationBarColor;
    private boolean mOldFullscreen;
    private boolean mFullscreen;
    private final Rect mOldSystemInsets = new Rect();
    private final Rect mOldStableInsets = new Rect();
    private final Rect mSystemInsets = new Rect();
    private final Rect mStableInsets = new Rect();

    public BackdropFrameRenderer(DecorView decorView, ThreadedRenderer renderer, Rect initialBounds,
            Drawable resizingBackgroundDrawable, Drawable captionBackgroundDrawable,
            Drawable userCaptionBackgroundDrawable, int statusBarColor) {
            Drawable userCaptionBackgroundDrawable, int statusBarColor, int navigationBarColor,
            boolean fullscreen, Rect systemInsets, Rect stableInsets) {
        setName("ResizeFrame");

        mRenderer = renderer;
        onResourcesLoaded(decorView, resizingBackgroundDrawable, captionBackgroundDrawable,
                userCaptionBackgroundDrawable, statusBarColor);
                userCaptionBackgroundDrawable, statusBarColor, navigationBarColor);

        // Create a render node for the content and frame backdrop
        // which can be resized independently from the content.
@@ -84,8 +92,14 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame

        // Set the initial bounds and draw once so that we do not get a broken frame.
        mTargetRect.set(initialBounds);
        mFullscreen = fullscreen;
        mOldFullscreen = fullscreen;
        mSystemInsets.set(systemInsets);
        mStableInsets.set(stableInsets);
        mOldSystemInsets.set(systemInsets);
        mOldStableInsets.set(stableInsets);
        synchronized (this) {
            changeWindowSizeLocked(initialBounds);
            redrawLocked(initialBounds, fullscreen, mSystemInsets, mStableInsets);
        }

        // Kick off our draw thread.
@@ -94,7 +108,7 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame

    void onResourcesLoaded(DecorView decorView, Drawable resizingBackgroundDrawable,
            Drawable captionBackgroundDrawableDrawable, Drawable userCaptionBackgroundDrawable,
            int statusBarColor) {
            int statusBarColor, int navigationBarColor) {
        mDecorView = decorView;
        mResizingBackgroundDrawable = resizingBackgroundDrawable;
        mCaptionBackgroundDrawable = captionBackgroundDrawableDrawable;
@@ -108,6 +122,12 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
        } else {
            mStatusBarColor = null;
        }
        if (navigationBarColor != 0) {
            mNavigationBarColor = new ColorDrawable(navigationBarColor);
            addSystemBarNodeIfNeeded();
        } else {
            mNavigationBarColor = null;
        }
    }

    private void addSystemBarNodeIfNeeded() {
@@ -119,13 +139,22 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
    }

    /**
     * Call this function asynchronously when the window size has been changed. The change will
     * be picked up once per frame and the frame will be re-rendered accordingly.
     * Call this function asynchronously when the window size has been changed or when the insets
     * have changed or whether window switched between a fullscreen or non-fullscreen layout.
     * The change will be picked up once per frame and the frame will be re-rendered accordingly.
     *
     * @param newTargetBounds The new target bounds.
     * @param fullscreen Whether the window is currently drawing in fullscreen.
     * @param systemInsets The current visible system insets for the window.
     * @param stableInsets The stable insets for the window.
     */
    public void setTargetRect(Rect newTargetBounds) {
    public void setTargetRect(Rect newTargetBounds, boolean fullscreen, Rect systemInsets,
            Rect stableInsets) {
        synchronized (this) {
            mFullscreen = fullscreen;
            mTargetRect.set(newTargetBounds);
            mSystemInsets.set(systemInsets);
            mStableInsets.set(stableInsets);
            // Notify of a bounds change.
            pingRenderLocked();
        }
@@ -204,16 +233,23 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
                return;
            }
            mNewTargetRect.set(mTargetRect);
            if (!mNewTargetRect.equals(mOldTargetRect) || mReportNextDraw) {
            if (!mNewTargetRect.equals(mOldTargetRect)
                    || mOldFullscreen != mFullscreen
                    || !mStableInsets.equals(mOldStableInsets)
                    || !mSystemInsets.equals(mOldSystemInsets)
                    || mReportNextDraw) {
                mOldFullscreen = mFullscreen;
                mOldTargetRect.set(mNewTargetRect);
                changeWindowSizeLocked(mNewTargetRect);
                mOldSystemInsets.set(mSystemInsets);
                mOldStableInsets.set(mStableInsets);
                redrawLocked(mNewTargetRect, mFullscreen, mSystemInsets, mStableInsets);
            }
        }
    }

    /**
     * The content is about to be drawn and we got the location of where it will be shown.
     * If a "changeWindowSizeLocked" call has already been processed, we will re-issue the call
     * If a "redrawLocked" call has already been processed, we will re-issue the call
     * if the previous call was ignored since the size was unknown.
     * @param xOffset The x offset where the content is drawn to.
     * @param yOffset The y offset where the content is drawn to.
@@ -235,8 +271,8 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
                    mLastYOffset,
                    mLastXOffset + mLastContentWidth,
                    mLastYOffset + mLastCaptionHeight + mLastContentHeight);
            // If this was the first call and changeWindowSizeLocked got already called prior
            // to us, we should re-issue a changeWindowSizeLocked now.
            // If this was the first call and redrawLocked got already called prior
            // to us, we should re-issue a redrawLocked now.
            return firstCall
                    && (mLastCaptionHeight != 0 || !mDecorView.isShowingCaption());
        }
@@ -251,16 +287,20 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
    }

    /**
     * Resizing the frame to fit the new window size.
     * Redraws the background, the caption and the system inset backgrounds if something changed.
     *
     * @param newBounds The window bounds which needs to be drawn.
     * @param fullscreen Whether the window is currently drawing in fullscreen.
     * @param systemInsets The current visible system insets for the window.
     * @param stableInsets The stable insets for the window.
     */
    private void changeWindowSizeLocked(Rect newBounds) {
    private void redrawLocked(Rect newBounds, boolean fullscreen, Rect systemInsets,
            Rect stableInsets) {

        // While a configuration change is taking place the view hierarchy might become
        // inaccessible. For that case we remember the previous metrics to avoid flashes.
        // Note that even when there is no visible caption, the caption child will exist.
        final int captionHeight = mDecorView.getCaptionHeight();
        final int statusBarHeight = mDecorView.getStatusBarHeight();

        // The caption height will probably never dynamically change while we are resizing.
        // Once set to something other then 0 it should be kept that way.
@@ -302,14 +342,7 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
        }
        mFrameAndBackdropNode.end(canvas);

        if (mSystemBarBackgroundNode != null && mStatusBarColor != null) {
            canvas = mSystemBarBackgroundNode.start(width, height);
            mSystemBarBackgroundNode.setLeftTopRightBottom(left, top, left + width, top + height);
            mStatusBarColor.setBounds(0, 0, left + width, statusBarHeight);
            mStatusBarColor.draw(canvas);
            mSystemBarBackgroundNode.end(canvas);
            mRenderer.drawRenderNode(mSystemBarBackgroundNode);
        }
        drawColorViews(left, top, width, height, fullscreen, systemInsets, stableInsets);

        // We need to render the node explicitly
        mRenderer.drawRenderNode(mFrameAndBackdropNode);
@@ -317,6 +350,39 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
        reportDrawIfNeeded();
    }

    private void drawColorViews(int left, int top, int width, int height,
            boolean fullscreen, Rect systemInsets, Rect stableInsets) {
        if (mSystemBarBackgroundNode == null) {
            return;
        }
        DisplayListCanvas canvas = mSystemBarBackgroundNode.start(width, height);
        mSystemBarBackgroundNode.setLeftTopRightBottom(left, top, left + width, top + height);
        final int topInset = DecorView.getColorViewTopInset(mStableInsets.top, mSystemInsets.top);
        final int bottomInset = DecorView.getColorViewBottomInset(stableInsets.bottom,
                systemInsets.bottom);
        final int rightInset = DecorView.getColorViewRightInset(stableInsets.right,
                systemInsets.right);
        if (mStatusBarColor != null) {
            mStatusBarColor.setBounds(0, 0, left + width, topInset);
            mStatusBarColor.draw(canvas);
        }

        // We only want to draw the navigation bar if our window is currently fullscreen because we
        // don't want the navigation bar background be moving around when resizing in docked mode.
        // However, we need it for the transitions into/out of docked mode.
        if (mNavigationBarColor != null && fullscreen) {
            final int size = DecorView.getNavBarSize(bottomInset, rightInset);
            if (DecorView.isNavBarToRightEdge(bottomInset, rightInset)) {
                mNavigationBarColor.setBounds(width - size, 0, width, height);
            } else {
                mNavigationBarColor.setBounds(0, height - size, width, height);
            }
            mNavigationBarColor.draw(canvas);
        }
        mSystemBarBackgroundNode.end(canvas);
        mRenderer.drawRenderNode(mSystemBarBackgroundNode);
    }

    /** Notify view root that a frame has been drawn by us, if it has requested so. */
    private void reportDrawIfNeeded() {
        if (mReportNextDraw) {
+37 −16
Original line number Diff line number Diff line
@@ -922,6 +922,26 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
        return false;
    }

    static int getColorViewTopInset(int stableTop, int systemTop) {
        return Math.min(stableTop, systemTop);
    }

    static int getColorViewBottomInset(int stableBottom, int systemBottom) {
        return Math.min(stableBottom, systemBottom);
    }

    static int getColorViewRightInset(int stableRight, int systemRight) {
        return Math.min(stableRight, systemRight);
    }

    static boolean isNavBarToRightEdge(int bottomInset, int rightInset) {
        return bottomInset == 0 && rightInset > 0;
    }

    static int getNavBarSize(int bottomInset, int rightInset) {
        return isNavBarToRightEdge(bottomInset, rightInset) ? rightInset : bottomInset;
    }

    WindowInsets updateColorViews(WindowInsets insets, boolean animate) {
        WindowManager.LayoutParams attrs = mWindow.getAttributes();
        int sysUiVisibility = attrs.systemUiVisibility | getWindowSystemUiVisibility();
@@ -933,11 +953,11 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
            mLastWindowFlags = attrs.flags;

            if (insets != null) {
                mLastTopInset = Math.min(insets.getStableInsetTop(),
                mLastTopInset = getColorViewTopInset(insets.getStableInsetTop(),
                        insets.getSystemWindowInsetTop());
                mLastBottomInset = Math.min(insets.getStableInsetBottom(),
                mLastBottomInset = getColorViewBottomInset(insets.getStableInsetBottom(),
                        insets.getSystemWindowInsetBottom());
                mLastRightInset = Math.min(insets.getStableInsetRight(),
                mLastRightInset = getColorViewRightInset(insets.getStableInsetRight(),
                        insets.getSystemWindowInsetRight());

                // Don't animate if the presence of stable insets has changed, because that
@@ -956,8 +976,8 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
                mLastHasRightStableInset = hasRightStableInset;
            }

            boolean navBarToRightEdge = mLastBottomInset == 0 && mLastRightInset > 0;
            int navBarSize = navBarToRightEdge ? mLastRightInset : mLastBottomInset;
            boolean navBarToRightEdge = isNavBarToRightEdge(mLastBottomInset, mLastRightInset);
            int navBarSize = getNavBarSize(mLastBottomInset, mLastRightInset);
            updateColorViewInt(mNavigationColorViewState, sysUiVisibility,
                    mWindow.mNavigationBarColor, navBarSize, navBarToRightEdge,
                    0 /* rightInset */, animate && !disallowAnimate, false /* force */);
@@ -1041,14 +1061,14 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
     */
    private void updateColorViewInt(final ColorViewState state, int sysUiVis, int color,
            int size, boolean verticalBar, int rightMargin, boolean animate, boolean force) {
        state.present = size > 0 && (sysUiVis & state.systemUiHideFlag) == 0
        state.present = (sysUiVis & state.systemUiHideFlag) == 0
                && (mWindow.getAttributes().flags & state.hideWindowFlag) == 0
                && ((mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
                        || force);
        boolean show = state.present
                && (color & Color.BLACK) != 0
                && ((mWindow.getAttributes().flags & state.translucentFlag) == 0  || force);
        boolean showView = show && !isResizing();
        boolean showView = show && !isResizing() && size > 0;

        boolean visibilityChanged = false;
        View view = state.view;
@@ -1672,7 +1692,8 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
            loadBackgroundDrawablesIfNeeded();
            mBackdropFrameRenderer.onResourcesLoaded(
                    this, mResizingBackgroundDrawable, mCaptionBackgroundDrawable,
                    mUserCaptionBackgroundDrawable, getCurrentColor(mStatusColorViewState));
                    mUserCaptionBackgroundDrawable, getCurrentColor(mStatusColorViewState),
                    getCurrentColor(mNavigationColorViewState));
        }

        mDecorCaptionView = createDecorCaptionView(inflater);
@@ -1854,14 +1875,16 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
    }

    @Override
    public void onWindowSizeIsChanging(Rect newBounds) {
    public void onWindowSizeIsChanging(Rect newBounds, boolean fullscreen, Rect systemInsets,
            Rect stableInsets) {
        if (mBackdropFrameRenderer != null) {
            mBackdropFrameRenderer.setTargetRect(newBounds);
            mBackdropFrameRenderer.setTargetRect(newBounds, fullscreen, systemInsets, stableInsets);
        }
    }

    @Override
    public void onWindowDragResizeStart(Rect initialBounds) {
    public void onWindowDragResizeStart(Rect initialBounds, boolean fullscreen, Rect systemInsets,
            Rect stableInsets) {
        if (mWindow.isDestroyed()) {
            // If the owner's window is gone, we should not be able to come here anymore.
            releaseThreadedRenderer();
@@ -1875,7 +1898,9 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
            loadBackgroundDrawablesIfNeeded();
            mBackdropFrameRenderer = new BackdropFrameRenderer(this, renderer,
                    initialBounds, mResizingBackgroundDrawable, mCaptionBackgroundDrawable,
                    mUserCaptionBackgroundDrawable, getCurrentColor(mStatusColorViewState));
                    mUserCaptionBackgroundDrawable, getCurrentColor(mStatusColorViewState),
                    getCurrentColor(mNavigationColorViewState), fullscreen, systemInsets,
                    stableInsets);

            // Get rid of the shadow while we are resizing. Shadow drawing takes considerable time.
            // If we want to get the shadow shown while resizing, we would need to elevate a new
@@ -1971,10 +1996,6 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
        return isShowingCaption() ? mDecorCaptionView.getCaptionHeight() : 0;
    }

    int getStatusBarHeight() {
        return mStatusColorViewState.view != null ? mStatusColorViewState.view.getHeight() : 0;
    }

    /**
     * Converts a DIP measure into physical pixels.
     * @param dip The dip value.
Loading