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

Commit a91b6af7 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes I841d2621,I456f6695

* changes:
  Fix a couple of issues with insets
  Implement WindowInsets.isVisible
parents 334ddaa5 a2759b2a
Loading
Loading
Loading
Loading
+20 −5
Original line number Diff line number Diff line
@@ -16,7 +16,10 @@

package android.view;

import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
import static android.view.WindowInsets.Type.SIZE;
import static android.view.WindowInsets.Type.indexOf;

import android.annotation.IntDef;
@@ -124,9 +127,10 @@ public class InsetsState implements Parcelable {
            @Nullable @InsetSide SparseIntArray typeSideMap) {
        Insets[] typeInsetsMap = new Insets[Type.SIZE];
        Insets[] typeMaxInsetsMap = new Insets[Type.SIZE];
        boolean[] typeVisibilityMap = new boolean[SIZE];
        final Rect relativeFrame = new Rect(frame);
        final Rect relativeFrameMax = new Rect(frame);
        if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_IME
        if (ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL
                && legacyContentInsets != null && legacyStableInsets != null) {
            WindowInsets.assignCompatInsets(typeInsetsMap, legacyContentInsets);
            WindowInsets.assignCompatInsets(typeMaxInsetsMap, legacyStableInsets);
@@ -136,22 +140,29 @@ public class InsetsState implements Parcelable {
            if (source == null) {
                continue;
            }
            if (ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL
                    && (type == TYPE_TOP_BAR || type == TYPE_NAVIGATION_BAR)) {
                typeVisibilityMap[indexOf(toPublicType(type))] = source.isVisible();
                continue;
            }

            processSource(source, relativeFrame, false /* ignoreVisibility */, typeInsetsMap,
                    typeSideMap);
                    typeSideMap, typeVisibilityMap);

            // IME won't be reported in max insets as the size depends on the EditorInfo of the IME
            // target.
            if (source.getType() != TYPE_IME) {
                processSource(source, relativeFrameMax, true /* ignoreVisibility */,
                        typeMaxInsetsMap, null /* typeSideMap */);
                        typeMaxInsetsMap, null /* typeSideMap */, null /* typeVisibilityMap */);
            }
        }
        return new WindowInsets(typeInsetsMap, typeMaxInsetsMap, isScreenRound,
        return new WindowInsets(typeInsetsMap, typeMaxInsetsMap, typeVisibilityMap, isScreenRound,
                alwaysConsumeNavBar, cutout);
    }

    private void processSource(InsetsSource source, Rect relativeFrame, boolean ignoreVisibility,
            Insets[] typeInsetsMap, @Nullable @InsetSide SparseIntArray typeSideMap) {
            Insets[] typeInsetsMap, @Nullable @InsetSide SparseIntArray typeSideMap,
            @Nullable boolean[] typeVisibilityMap) {
        Insets insets = source.calculateInsets(relativeFrame, ignoreVisibility);

        int index = indexOf(toPublicType(source.getType()));
@@ -162,6 +173,10 @@ public class InsetsState implements Parcelable {
            typeInsetsMap[index] = Insets.max(existing, insets);
        }

        if (typeVisibilityMap != null) {
            typeVisibilityMap[index] = source.isVisible();
        }

        if (typeSideMap != null && !Insets.NONE.equals(insets)) {
            @InsetSide int insetSide = getInsetSide(insets);
            if (insetSide != INSET_SIDE_UNKNWON) {
+79 −9
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ public final class WindowInsets {

    private final Insets[] mTypeInsetsMap;
    private final Insets[] mTypeMaxInsetsMap;
    private final boolean[] mTypeVisibilityMap;

    @Nullable private Rect mTempRect;
    private final boolean mIsRound;
@@ -106,6 +107,7 @@ public final class WindowInsets {
    public WindowInsets(Rect systemWindowInsetsRect, Rect stableInsetsRect,
            boolean isRound, boolean alwaysConsumeNavBar, DisplayCutout displayCutout) {
        this(createCompatTypeMap(systemWindowInsetsRect), createCompatTypeMap(stableInsetsRect),
                createCompatVisibilityMap(createCompatTypeMap(systemWindowInsetsRect)),
                isRound, alwaysConsumeNavBar, displayCutout);
    }

@@ -122,7 +124,9 @@ public final class WindowInsets {
     * @hide
     */
    public WindowInsets(@Nullable Insets[] typeInsetsMap,
            @Nullable Insets[] typeMaxInsetsMap, boolean isRound,
            @Nullable Insets[] typeMaxInsetsMap,
            boolean[] typeVisibilityMap,
            boolean isRound,
            boolean alwaysConsumeNavBar, DisplayCutout displayCutout) {
        mSystemWindowInsetsConsumed = typeInsetsMap == null;
        mTypeInsetsMap = mSystemWindowInsetsConsumed
@@ -134,6 +138,7 @@ public final class WindowInsets {
                ? new Insets[SIZE]
                : typeMaxInsetsMap.clone();

        mTypeVisibilityMap = typeVisibilityMap;
        mIsRound = isRound;
        mAlwaysConsumeNavBar = alwaysConsumeNavBar;

@@ -148,8 +153,8 @@ public final class WindowInsets {
     * @param src Source to copy insets from
     */
    public WindowInsets(WindowInsets src) {
        this(src.mTypeInsetsMap, src.mTypeMaxInsetsMap, src.mIsRound, src.mAlwaysConsumeNavBar,
                displayCutoutCopyConstructorArgument(src));
        this(src.mTypeInsetsMap, src.mTypeMaxInsetsMap, src.mTypeVisibilityMap, src.mIsRound,
                src.mAlwaysConsumeNavBar, displayCutoutCopyConstructorArgument(src));
    }

    private static DisplayCutout displayCutoutCopyConstructorArgument(WindowInsets w) {
@@ -200,7 +205,7 @@ public final class WindowInsets {
    /** @hide */
    @UnsupportedAppUsage
    public WindowInsets(Rect systemWindowInsets) {
        this(createCompatTypeMap(systemWindowInsets), null, false, false, null);
        this(createCompatTypeMap(systemWindowInsets), null, new boolean[SIZE], false, false, null);
    }

    /**
@@ -225,6 +230,20 @@ public final class WindowInsets {
        typeInsetMap[indexOf(SIDE_BARS)] = Insets.of(insets.left, 0, insets.right, insets.bottom);
    }

    private static boolean[] createCompatVisibilityMap(@Nullable Insets[] typeInsetMap) {
        boolean[] typeVisibilityMap = new boolean[SIZE];
        if (typeInsetMap == null) {
            return typeVisibilityMap;
        }
        for (int i = FIRST; i <= LAST; i = i << 1) {
            int index = indexOf(i);
            if (!Insets.NONE.equals(typeInsetMap[index])) {
                typeVisibilityMap[index] = true;
            }
        }
        return typeVisibilityMap;
    }

    /**
     * Used to provide a safe copy of the system window insets to pass through
     * to the existing fitSystemWindows method and other similar internals.
@@ -296,6 +315,27 @@ public final class WindowInsets {
        return getInsets(mTypeMaxInsetsMap, typeMask);
    }

    /**
     * Returns whether a set of windows that may cause insets is currently visible on screen,
     * regardless of whether it actually overlaps with this window.
     *
     * @param typeMask Bit mask of {@link InsetType}s to query visibility status.
     * @return {@code true} if and only if all windows included in {@code typeMask} are currently
     *         visible on screen.
     * @hide pending unhide
     */
    public boolean isVisible(@InsetType int typeMask) {
        for (int i = FIRST; i <= LAST; i = i << 1) {
            if ((typeMask & i) == 0) {
                continue;
            }
            if (!mTypeVisibilityMap[indexOf(i)]) {
                return false;
            }
        }
        return true;
    }

    /**
     * Returns the left system window inset in pixels.
     *
@@ -392,6 +432,7 @@ public final class WindowInsets {
    public WindowInsets consumeDisplayCutout() {
        return new WindowInsets(mSystemWindowInsetsConsumed ? null : mTypeInsetsMap,
                mStableInsetsConsumed ? null : mTypeMaxInsetsMap,
                mTypeVisibilityMap,
                mIsRound, mAlwaysConsumeNavBar,
                null /* displayCutout */);
    }
@@ -437,6 +478,7 @@ public final class WindowInsets {
    @NonNull
    public WindowInsets consumeSystemWindowInsets() {
        return new WindowInsets(null, mStableInsetsConsumed ? null : mTypeMaxInsetsMap,
                mTypeVisibilityMap,
                mIsRound, mAlwaysConsumeNavBar,
                displayCutoutCopyConstructorArgument(this));
    }
@@ -594,7 +636,7 @@ public final class WindowInsets {
    @NonNull
    public WindowInsets consumeStableInsets() {
        return new WindowInsets(mSystemWindowInsetsConsumed ? null : mTypeInsetsMap, null,
                mIsRound, mAlwaysConsumeNavBar,
                mTypeVisibilityMap, mIsRound, mAlwaysConsumeNavBar,
                displayCutoutCopyConstructorArgument(this));
    }

@@ -671,6 +713,7 @@ public final class WindowInsets {
                mStableInsetsConsumed
                        ? null
                        : insetInsets(mTypeMaxInsetsMap, left, top, right, bottom),
                mTypeVisibilityMap,
                mIsRound, mAlwaysConsumeNavBar,
                mDisplayCutoutConsumed
                        ? null
@@ -692,14 +735,15 @@ public final class WindowInsets {
                && mDisplayCutoutConsumed == that.mDisplayCutoutConsumed
                && Arrays.equals(mTypeInsetsMap, that.mTypeInsetsMap)
                && Arrays.equals(mTypeMaxInsetsMap, that.mTypeMaxInsetsMap)
                && Arrays.equals(mTypeVisibilityMap, that.mTypeVisibilityMap)
                && Objects.equals(mDisplayCutout, that.mDisplayCutout);
    }

    @Override
    public int hashCode() {
        return Objects.hash(Arrays.hashCode(mTypeInsetsMap), Arrays.hashCode(mTypeMaxInsetsMap),
                mIsRound, mDisplayCutout, mAlwaysConsumeNavBar, mSystemWindowInsetsConsumed,
                mStableInsetsConsumed, mDisplayCutoutConsumed);
                Arrays.hashCode(mTypeVisibilityMap), mIsRound, mDisplayCutout, mAlwaysConsumeNavBar,
                mSystemWindowInsetsConsumed, mStableInsetsConsumed, mDisplayCutoutConsumed);
    }


@@ -754,6 +798,7 @@ public final class WindowInsets {

        private final Insets[] mTypeInsetsMap;
        private final Insets[] mTypeMaxInsetsMap;
        private final boolean[] mTypeVisibilityMap;
        private boolean mSystemInsetsConsumed = true;
        private boolean mStableInsetsConsumed = true;

@@ -768,6 +813,7 @@ public final class WindowInsets {
        public Builder() {
            mTypeInsetsMap = new Insets[SIZE];
            mTypeMaxInsetsMap = new Insets[SIZE];
            mTypeVisibilityMap = new boolean[SIZE];
        }

        /**
@@ -778,6 +824,7 @@ public final class WindowInsets {
        public Builder(WindowInsets insets) {
            mTypeInsetsMap = insets.mTypeInsetsMap.clone();
            mTypeMaxInsetsMap = insets.mTypeMaxInsetsMap.clone();
            mTypeVisibilityMap = insets.mTypeVisibilityMap.clone();
            mSystemInsetsConsumed = insets.mSystemWindowInsetsConsumed;
            mStableInsetsConsumed = insets.mStableInsetsConsumed;
            mDisplayCutout = displayCutoutCopyConstructorArgument(insets);
@@ -861,6 +908,29 @@ public final class WindowInsets {
            return this;
        }

        /**
         * Sets whether windows that can cause insets are currently visible on screen.
         *
         *
         * @see #isVisible(int)
         *
         * @param typeMask The bitmask of {@link InsetType} to set the visibility for.
         * @param visible Whether to mark the windows as visible or not.
         *
         * @return itself
         * @hide pending unhide
         */
        @NonNull
        public Builder setVisible(@InsetType int typeMask, boolean visible) {
            for (int i = FIRST; i <= LAST; i = i << 1) {
                if ((typeMask & i) == 0) {
                    continue;
                }
                mTypeVisibilityMap[indexOf(i)] = visible;
            }
            return this;
        }

        /**
         * Sets the stable insets in pixels.
         *
@@ -916,8 +986,8 @@ public final class WindowInsets {
        @NonNull
        public WindowInsets build() {
            return new WindowInsets(mSystemInsetsConsumed ? null : mTypeInsetsMap,
                    mStableInsetsConsumed ? null : mTypeMaxInsetsMap, mIsRound,
                    mAlwaysConsumeNavBar, mDisplayCutout);
                    mStableInsetsConsumed ? null : mTypeMaxInsetsMap, mTypeVisibilityMap,
                    mIsRound, mAlwaysConsumeNavBar, mDisplayCutout);
        }
    }

+26 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.sideBars;
import static android.view.WindowInsets.Type.topBar;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import android.graphics.Insets;
@@ -73,4 +74,29 @@ public class WindowInsetsTest {
        assertEquals(Insets.of(0, 50, 0, 0), insets.getInsets(topBar()));
        assertEquals(Insets.of(0, 0, 30, 10), insets.getInsets(sideBars()));
    }

    // TODO: Move this to CTS once API made public
    @Test
    public void visibility() {
        Builder b = new WindowInsets.Builder();
        b.setInsets(sideBars(), Insets.of(0, 0, 0, 100));
        b.setInsets(ime(), Insets.of(0, 0, 0, 300));
        b.setVisible(sideBars(), true);
        b.setVisible(ime(), true);
        WindowInsets insets = b.build();
        assertTrue(insets.isVisible(sideBars()));
        assertTrue(insets.isVisible(sideBars() | ime()));
        assertFalse(insets.isVisible(sideBars() | topBar()));
    }

    // TODO: Move this to CTS once API made public
    @Test
    public void consume_doesntChangeVisibility() {
        Builder b = new WindowInsets.Builder();
        b.setInsets(ime(), Insets.of(0, 0, 0, 300));
        b.setVisible(ime(), true);
        WindowInsets insets = b.build();
        insets = insets.consumeSystemWindowInsets();
        assertTrue(insets.isVisible(ime()));
    }
}
+0 −5
Original line number Diff line number Diff line
@@ -1057,11 +1057,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
     */
    void setInsetProvider(@InternalInsetType int type, WindowState win,
            @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider) {
        if (ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL) {
            if (type == TYPE_TOP_BAR || type == TYPE_NAVIGATION_BAR) {
                return;
            }
        }
        mInsetsStateController.getSourceProvider(type).setWindow(win, frameProvider);
    }

+33 −3
Original line number Diff line number Diff line
@@ -16,7 +16,13 @@

package com.android.server.wm;

import static android.view.InsetsState.TYPE_IME;
import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
import static android.view.InsetsState.TYPE_TOP_BAR;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
import static android.view.ViewRootImpl.sNewInsetsMode;

import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -59,6 +65,7 @@ class InsetsSourceProvider {
     */
    private boolean mServerVisible;

    private final boolean mControllable;

    InsetsSourceProvider(InsetsSource source, InsetsStateController stateController,
            DisplayContent displayContent) {
@@ -66,12 +73,28 @@ class InsetsSourceProvider {
        mSource = source;
        mDisplayContent = displayContent;
        mStateController = stateController;

        final int type = source.getType();
        if (type == TYPE_TOP_BAR || type == TYPE_NAVIGATION_BAR) {
            mControllable = sNewInsetsMode == NEW_INSETS_MODE_FULL;
        } else if (type == TYPE_IME) {
            mControllable = sNewInsetsMode >= NEW_INSETS_MODE_IME;
        } else {
            mControllable = false;
        }
    }

    InsetsSource getSource() {
        return mSource;
    }

    /**
     * @return Whether the current flag configuration allows to control this source.
     */
    boolean isControllable() {
        return mControllable;
    }

    /**
     * Updates the window that currently backs this source.
     *
@@ -91,6 +114,9 @@ class InsetsSourceProvider {
            mSource.setFrame(new Rect());
        } else {
            mWin.setInsetProvider(this);
            if (mControllingWin != null) {
                updateControlForTarget(mControllingWin, true /* force */);
            }
        }
    }

@@ -113,8 +139,12 @@ class InsetsSourceProvider {
                && !mWin.mGivenInsetsPending);
    }

    void updateControlForTarget(@Nullable WindowState target) {
        if (target == mControllingWin) {
    void updateControlForTarget(@Nullable WindowState target, boolean force) {
        if (mWin == null) {
            mControllingWin = target;
            return;
        }
        if (target == mControllingWin && !force) {
            return;
        }
        if (target == null) {
@@ -161,7 +191,7 @@ class InsetsSourceProvider {
    }

    boolean isClientVisible() {
        return ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE || mClientVisible;
        return sNewInsetsMode == NEW_INSETS_MODE_NONE || mClientVisible;
    }

    private class ControlAdapter implements AnimationAdapter {
Loading