Home | History | Annotate | Download | only in view
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 
     18 package android.view;
     19 
     20 import static android.view.WindowInsets.Type.FIRST;
     21 import static android.view.WindowInsets.Type.IME;
     22 import static android.view.WindowInsets.Type.LAST;
     23 import static android.view.WindowInsets.Type.MANDATORY_SYSTEM_GESTURES;
     24 import static android.view.WindowInsets.Type.SIDE_BARS;
     25 import static android.view.WindowInsets.Type.SIZE;
     26 import static android.view.WindowInsets.Type.SYSTEM_GESTURES;
     27 import static android.view.WindowInsets.Type.TAPPABLE_ELEMENT;
     28 import static android.view.WindowInsets.Type.TOP_BAR;
     29 import static android.view.WindowInsets.Type.all;
     30 import static android.view.WindowInsets.Type.compatSystemInsets;
     31 import static android.view.WindowInsets.Type.indexOf;
     32 
     33 import android.annotation.IntDef;
     34 import android.annotation.IntRange;
     35 import android.annotation.NonNull;
     36 import android.annotation.Nullable;
     37 import android.annotation.UnsupportedAppUsage;
     38 import android.graphics.Insets;
     39 import android.graphics.Rect;
     40 import android.util.SparseArray;
     41 import android.view.WindowInsets.Type.InsetType;
     42 import android.view.inputmethod.EditorInfo;
     43 import android.view.inputmethod.InputMethod;
     44 
     45 import com.android.internal.util.Preconditions;
     46 
     47 import java.lang.annotation.Retention;
     48 import java.lang.annotation.RetentionPolicy;
     49 import java.util.Arrays;
     50 import java.util.Objects;
     51 
     52 /**
     53  * Describes a set of insets for window content.
     54  *
     55  * <p>WindowInsets are immutable and may be expanded to include more inset types in the future.
     56  * To adjust insets, use one of the supplied clone methods to obtain a new WindowInsets instance
     57  * with the adjusted properties.</p>
     58  *
     59  * <p>Note: Before {@link android.os.Build.VERSION_CODES#P P}, WindowInsets instances were only
     60  * immutable during a single layout pass (i.e. would return the same values between
     61  * {@link View#onApplyWindowInsets} and {@link View#onLayout}, but could return other values
     62  * otherwise). Starting with {@link android.os.Build.VERSION_CODES#P P}, WindowInsets are
     63  * always immutable and implement equality.
     64  *
     65  * @see View.OnApplyWindowInsetsListener
     66  * @see View#onApplyWindowInsets(WindowInsets)
     67  */
     68 public final class WindowInsets {
     69 
     70     private final Insets[] mTypeInsetsMap;
     71     private final Insets[] mTypeMaxInsetsMap;
     72     private final boolean[] mTypeVisibilityMap;
     73 
     74     @Nullable private Rect mTempRect;
     75     private final boolean mIsRound;
     76     @Nullable private final DisplayCutout mDisplayCutout;
     77 
     78     /**
     79      * In multi-window we force show the navigation bar. Because we don't want that the surface size
     80      * changes in this mode, we instead have a flag whether the navigation bar size should always
     81      * be consumed, so the app is treated like there is no virtual navigation bar at all.
     82      */
     83     private final boolean mAlwaysConsumeSystemBars;
     84 
     85     private final boolean mSystemWindowInsetsConsumed;
     86     private final boolean mStableInsetsConsumed;
     87     private final boolean mDisplayCutoutConsumed;
     88 
     89     /**
     90      * Since new insets may be added in the future that existing apps couldn't
     91      * know about, this fully empty constant shouldn't be made available to apps
     92      * since it would allow them to inadvertently consume unknown insets by returning it.
     93      * @hide
     94      */
     95     @UnsupportedAppUsage
     96     public static final WindowInsets CONSUMED;
     97 
     98     static {
     99         CONSUMED = new WindowInsets((Rect) null, null, false, false, null);
    100     }
    101 
    102     /**
    103      * Construct a new WindowInsets from individual insets.
    104      *
    105      * A {@code null} inset indicates that the respective inset is consumed.
    106      *
    107      * @hide
    108      * @deprecated Use {@link WindowInsets(SparseArray, SparseArray, boolean, boolean, DisplayCutout)}
    109      */
    110     public WindowInsets(Rect systemWindowInsetsRect, Rect stableInsetsRect,
    111             boolean isRound, boolean alwaysConsumeSystemBars, DisplayCutout displayCutout) {
    112         this(createCompatTypeMap(systemWindowInsetsRect), createCompatTypeMap(stableInsetsRect),
    113                 createCompatVisibilityMap(createCompatTypeMap(systemWindowInsetsRect)),
    114                 isRound, alwaysConsumeSystemBars, displayCutout);
    115     }
    116 
    117     /**
    118      * Construct a new WindowInsets from individual insets.
    119      *
    120      * {@code typeInsetsMap} and {@code typeMaxInsetsMap} are a map of indexOf(type) -> insets that
    121      * contain the information what kind of system bars causes how much insets. The insets in this
    122      * map are non-additive; i.e. they have the same origin. In other words: If two system bars
    123      * overlap on one side, the insets of the larger bar will also include the insets of the smaller
    124      * bar.
    125      *
    126      * {@code null} type inset map indicates that the respective inset is fully consumed.
    127      * @hide
    128      */
    129     public WindowInsets(@Nullable Insets[] typeInsetsMap,
    130             @Nullable Insets[] typeMaxInsetsMap,
    131             boolean[] typeVisibilityMap,
    132             boolean isRound,
    133             boolean alwaysConsumeSystemBars, DisplayCutout displayCutout) {
    134         mSystemWindowInsetsConsumed = typeInsetsMap == null;
    135         mTypeInsetsMap = mSystemWindowInsetsConsumed
    136                 ? new Insets[SIZE]
    137                 : typeInsetsMap.clone();
    138 
    139         mStableInsetsConsumed = typeMaxInsetsMap == null;
    140         mTypeMaxInsetsMap = mStableInsetsConsumed
    141                 ? new Insets[SIZE]
    142                 : typeMaxInsetsMap.clone();
    143 
    144         mTypeVisibilityMap = typeVisibilityMap;
    145         mIsRound = isRound;
    146         mAlwaysConsumeSystemBars = alwaysConsumeSystemBars;
    147 
    148         mDisplayCutoutConsumed = displayCutout == null;
    149         mDisplayCutout = (mDisplayCutoutConsumed || displayCutout.isEmpty())
    150                 ? null : displayCutout;
    151     }
    152 
    153     /**
    154      * Construct a new WindowInsets, copying all values from a source WindowInsets.
    155      *
    156      * @param src Source to copy insets from
    157      */
    158     public WindowInsets(WindowInsets src) {
    159         this(src.mSystemWindowInsetsConsumed ? null : src.mTypeInsetsMap,
    160                 src.mStableInsetsConsumed ? null : src.mTypeMaxInsetsMap,
    161                 src.mTypeVisibilityMap, src.mIsRound,
    162                 src.mAlwaysConsumeSystemBars, displayCutoutCopyConstructorArgument(src));
    163     }
    164 
    165     private static DisplayCutout displayCutoutCopyConstructorArgument(WindowInsets w) {
    166         if (w.mDisplayCutoutConsumed) {
    167             return null;
    168         } else if (w.mDisplayCutout == null) {
    169             return DisplayCutout.NO_CUTOUT;
    170         } else {
    171             return w.mDisplayCutout;
    172         }
    173     }
    174 
    175     /**
    176      * @return The insets that include system bars indicated by {@code typeMask}, taken from
    177      *         {@code typeInsetMap}.
    178      */
    179     private static Insets getInsets(Insets[] typeInsetsMap, @InsetType int typeMask) {
    180         Insets result = null;
    181         for (int i = FIRST; i <= LAST; i = i << 1) {
    182             if ((typeMask & i) == 0) {
    183                 continue;
    184             }
    185             Insets insets = typeInsetsMap[indexOf(i)];
    186             if (insets == null) {
    187                 continue;
    188             }
    189             if (result == null) {
    190                 result = insets;
    191             } else {
    192                 result = Insets.max(result, insets);
    193             }
    194         }
    195         return result == null ? Insets.NONE : result;
    196     }
    197 
    198     /**
    199      * Sets all entries in {@code typeInsetsMap} that belong to {@code typeMask} to {@code insets},
    200      */
    201     private static void setInsets(Insets[] typeInsetsMap, @InsetType int typeMask, Insets insets) {
    202         for (int i = FIRST; i <= LAST; i = i << 1) {
    203             if ((typeMask & i) == 0) {
    204                 continue;
    205             }
    206             typeInsetsMap[indexOf(i)] = insets;
    207         }
    208     }
    209 
    210     /** @hide */
    211     @UnsupportedAppUsage
    212     public WindowInsets(Rect systemWindowInsets) {
    213         this(createCompatTypeMap(systemWindowInsets), null, new boolean[SIZE], false, false, null);
    214     }
    215 
    216     /**
    217      * Creates a indexOf(type) -> inset map for which the {@code insets} is just mapped to
    218      * {@link InsetType#topBar()} and {@link InsetType#sideBars()}, depending on the location of the
    219      * inset.
    220      */
    221     private static Insets[] createCompatTypeMap(@Nullable Rect insets) {
    222         if (insets == null) {
    223             return null;
    224         }
    225         Insets[] typeInsetMap = new Insets[SIZE];
    226         assignCompatInsets(typeInsetMap, insets);
    227         return typeInsetMap;
    228     }
    229 
    230     /**
    231      * @hide
    232      */
    233     static void assignCompatInsets(Insets[] typeInsetMap, Rect insets) {
    234         typeInsetMap[indexOf(TOP_BAR)] = Insets.of(0, insets.top, 0, 0);
    235         typeInsetMap[indexOf(SIDE_BARS)] = Insets.of(insets.left, 0, insets.right, insets.bottom);
    236     }
    237 
    238     private static boolean[] createCompatVisibilityMap(@Nullable Insets[] typeInsetMap) {
    239         boolean[] typeVisibilityMap = new boolean[SIZE];
    240         if (typeInsetMap == null) {
    241             return typeVisibilityMap;
    242         }
    243         for (int i = FIRST; i <= LAST; i = i << 1) {
    244             int index = indexOf(i);
    245             if (!Insets.NONE.equals(typeInsetMap[index])) {
    246                 typeVisibilityMap[index] = true;
    247             }
    248         }
    249         return typeVisibilityMap;
    250     }
    251 
    252     /**
    253      * Used to provide a safe copy of the system window insets to pass through
    254      * to the existing fitSystemWindows method and other similar internals.
    255      * @hide
    256      *
    257      * @deprecated use {@link #getSystemWindowInsets()} instead.
    258      */
    259     @Deprecated
    260     @NonNull
    261     public Rect getSystemWindowInsetsAsRect() {
    262         if (mTempRect == null) {
    263             mTempRect = new Rect();
    264         }
    265         Insets insets = getSystemWindowInsets();
    266         mTempRect.set(insets.left, insets.top, insets.right, insets.bottom);
    267         return mTempRect;
    268     }
    269 
    270     /**
    271      * Returns the system window insets in pixels.
    272      *
    273      * <p>The system window inset represents the area of a full-screen window that is
    274      * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
    275      * </p>
    276      *
    277      * @return The system window insets
    278      */
    279     @NonNull
    280     public Insets getSystemWindowInsets() {
    281         return getInsets(mTypeInsetsMap, compatSystemInsets());
    282     }
    283 
    284     /**
    285      * Returns the insets of a specific set of windows causing insets, denoted by the
    286      * {@code typeMask} bit mask of {@link InsetType}s.
    287      *
    288      * @param typeMask Bit mask of {@link InsetType}s to query the insets for.
    289      * @return The insets.
    290      *
    291      * @hide pending unhide
    292      */
    293     public Insets getInsets(@InsetType int typeMask) {
    294         return getInsets(mTypeInsetsMap, typeMask);
    295     }
    296 
    297     /**
    298      * Returns the maximum amount of insets a specific set of windows can cause, denoted by the
    299      * {@code typeMask} bit mask of {@link InsetType}s.
    300      *
    301      * <p>The maximum insets represents the area of a a window that that <b>may</b> be partially
    302      * or fully obscured by the system window identified by {@code type}. This value does not
    303      * change based on the visibility state of those elements. for example, if the status bar is
    304      * normally shown, but temporarily hidden, the maximum inset will still provide the inset
    305      * associated with the status bar being shown.</p>
    306      *
    307      * @param typeMask Bit mask of {@link InsetType}s to query the insets for.
    308      * @return The insets.
    309      *
    310      * @throws IllegalArgumentException If the caller tries to query {@link Type#ime()}. Maximum
    311      *                                  insets are not available for this type as the height of the
    312      *                                  IME is dynamic depending on the {@link EditorInfo} of the
    313      *                                  currently focused view, as well as the UI state of the IME.
    314      * @hide pending unhide
    315      */
    316     public Insets getMaxInsets(@InsetType int typeMask) throws IllegalArgumentException {
    317         if ((typeMask & IME) != 0) {
    318             throw new IllegalArgumentException("Unable to query the maximum insets for IME");
    319         }
    320         return getInsets(mTypeMaxInsetsMap, typeMask);
    321     }
    322 
    323     /**
    324      * Returns whether a set of windows that may cause insets is currently visible on screen,
    325      * regardless of whether it actually overlaps with this window.
    326      *
    327      * @param typeMask Bit mask of {@link InsetType}s to query visibility status.
    328      * @return {@code true} if and only if all windows included in {@code typeMask} are currently
    329      *         visible on screen.
    330      * @hide pending unhide
    331      */
    332     public boolean isVisible(@InsetType int typeMask) {
    333         for (int i = FIRST; i <= LAST; i = i << 1) {
    334             if ((typeMask & i) == 0) {
    335                 continue;
    336             }
    337             if (!mTypeVisibilityMap[indexOf(i)]) {
    338                 return false;
    339             }
    340         }
    341         return true;
    342     }
    343 
    344     /**
    345      * Returns the left system window inset in pixels.
    346      *
    347      * <p>The system window inset represents the area of a full-screen window that is
    348      * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
    349      * </p>
    350      *
    351      * @return The left system window inset
    352      */
    353     public int getSystemWindowInsetLeft() {
    354         return getSystemWindowInsets().left;
    355     }
    356 
    357     /**
    358      * Returns the top system window inset in pixels.
    359      *
    360      * <p>The system window inset represents the area of a full-screen window that is
    361      * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
    362      * </p>
    363      *
    364      * @return The top system window inset
    365      */
    366     public int getSystemWindowInsetTop() {
    367         return getSystemWindowInsets().top;
    368     }
    369 
    370     /**
    371      * Returns the right system window inset in pixels.
    372      *
    373      * <p>The system window inset represents the area of a full-screen window that is
    374      * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
    375      * </p>
    376      *
    377      * @return The right system window inset
    378      */
    379     public int getSystemWindowInsetRight() {
    380         return getSystemWindowInsets().right;
    381     }
    382 
    383     /**
    384      * Returns the bottom system window inset in pixels.
    385      *
    386      * <p>The system window inset represents the area of a full-screen window that is
    387      * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
    388      * </p>
    389      *
    390      * @return The bottom system window inset
    391      */
    392     public int getSystemWindowInsetBottom() {
    393         return getSystemWindowInsets().bottom;
    394     }
    395 
    396     /**
    397      * Returns true if this WindowInsets has nonzero system window insets.
    398      *
    399      * <p>The system window inset represents the area of a full-screen window that is
    400      * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
    401      * </p>
    402      *
    403      * @return true if any of the system window inset values are nonzero
    404      */
    405     public boolean hasSystemWindowInsets() {
    406         return !getSystemWindowInsets().equals(Insets.NONE);
    407     }
    408 
    409     /**
    410      * Returns true if this WindowInsets has any nonzero insets.
    411      *
    412      * @return true if any inset values are nonzero
    413      */
    414     public boolean hasInsets() {
    415         return !getInsets(mTypeInsetsMap, all()).equals(Insets.NONE)
    416                 || !getInsets(mTypeMaxInsetsMap, all()).equals(Insets.NONE)
    417                 || mDisplayCutout != null;
    418     }
    419 
    420     /**
    421      * Returns the display cutout if there is one.
    422      *
    423      * @return the display cutout or null if there is none
    424      * @see DisplayCutout
    425      */
    426     @Nullable
    427     public DisplayCutout getDisplayCutout() {
    428         return mDisplayCutout;
    429     }
    430 
    431     /**
    432      * Returns a copy of this WindowInsets with the cutout fully consumed.
    433      *
    434      * @return A modified copy of this WindowInsets
    435      */
    436     @NonNull
    437     public WindowInsets consumeDisplayCutout() {
    438         return new WindowInsets(mSystemWindowInsetsConsumed ? null : mTypeInsetsMap,
    439                 mStableInsetsConsumed ? null : mTypeMaxInsetsMap,
    440                 mTypeVisibilityMap,
    441                 mIsRound, mAlwaysConsumeSystemBars,
    442                 null /* displayCutout */);
    443     }
    444 
    445 
    446     /**
    447      * Check if these insets have been fully consumed.
    448      *
    449      * <p>Insets are considered "consumed" if the applicable <code>consume*</code> methods
    450      * have been called such that all insets have been set to zero. This affects propagation of
    451      * insets through the view hierarchy; insets that have not been fully consumed will continue
    452      * to propagate down to child views.</p>
    453      *
    454      * <p>The result of this method is equivalent to the return value of
    455      * {@link View#fitSystemWindows(android.graphics.Rect)}.</p>
    456      *
    457      * @return true if the insets have been fully consumed.
    458      */
    459     public boolean isConsumed() {
    460         return mSystemWindowInsetsConsumed && mStableInsetsConsumed
    461                 && mDisplayCutoutConsumed;
    462     }
    463 
    464     /**
    465      * Returns true if the associated window has a round shape.
    466      *
    467      * <p>A round window's left, top, right and bottom edges reach all the way to the
    468      * associated edges of the window but the corners may not be visible. Views responding
    469      * to round insets should take care to not lay out critical elements within the corners
    470      * where they may not be accessible.</p>
    471      *
    472      * @return True if the window is round
    473      */
    474     public boolean isRound() {
    475         return mIsRound;
    476     }
    477 
    478     /**
    479      * Returns a copy of this WindowInsets with the system window insets fully consumed.
    480      *
    481      * @return A modified copy of this WindowInsets
    482      */
    483     @NonNull
    484     public WindowInsets consumeSystemWindowInsets() {
    485         return new WindowInsets(null, mStableInsetsConsumed ? null : mTypeMaxInsetsMap,
    486                 mTypeVisibilityMap,
    487                 mIsRound, mAlwaysConsumeSystemBars,
    488                 displayCutoutCopyConstructorArgument(this));
    489     }
    490 
    491     // TODO(b/119190588): replace @code with @link below
    492     /**
    493      * Returns a copy of this WindowInsets with selected system window insets replaced
    494      * with new values.
    495      *
    496      * <p>Note: If the system window insets are already consumed, this method will return them
    497      * unchanged on {@link android.os.Build.VERSION_CODES#Q Q} and later. Prior to
    498      * {@link android.os.Build.VERSION_CODES#Q Q}, the new values were applied regardless of
    499      * whether they were consumed, and this method returns invalid non-zero consumed insets.
    500      *
    501      * @param left New left inset in pixels
    502      * @param top New top inset in pixels
    503      * @param right New right inset in pixels
    504      * @param bottom New bottom inset in pixels
    505      * @return A modified copy of this WindowInsets
    506      * @deprecated use {@code Builder#Builder(WindowInsets)} with
    507      *             {@link Builder#setSystemWindowInsets(Insets)} instead.
    508      */
    509     @Deprecated
    510     @NonNull
    511     public WindowInsets replaceSystemWindowInsets(int left, int top, int right, int bottom) {
    512         // Compat edge case: what should this do if the insets have already been consumed?
    513         // On platforms prior to Q, the behavior was to override the insets with non-zero values,
    514         // but leave them consumed, which is invalid (consumed insets must be zero).
    515         // The behavior is now keeping them consumed and discarding the new insets.
    516         if (mSystemWindowInsetsConsumed) {
    517             return this;
    518         }
    519         return new Builder(this).setSystemWindowInsets(Insets.of(left, top, right, bottom)).build();
    520     }
    521 
    522     // TODO(b/119190588): replace @code with @link below
    523     /**
    524      * Returns a copy of this WindowInsets with selected system window insets replaced
    525      * with new values.
    526      *
    527      * <p>Note: If the system window insets are already consumed, this method will return them
    528      * unchanged on {@link android.os.Build.VERSION_CODES#Q Q} and later. Prior to
    529      * {@link android.os.Build.VERSION_CODES#Q Q}, the new values were applied regardless of
    530      * whether they were consumed, and this method returns invalid non-zero consumed insets.
    531      *
    532      * @param systemWindowInsets New system window insets. Each field is the inset in pixels
    533      *                           for that edge
    534      * @return A modified copy of this WindowInsets
    535      * @deprecated use {@code Builder#Builder(WindowInsets)} with
    536      *             {@link Builder#setSystemWindowInsets(Insets)} instead.
    537      */
    538     @Deprecated
    539     @NonNull
    540     public WindowInsets replaceSystemWindowInsets(Rect systemWindowInsets) {
    541         return replaceSystemWindowInsets(systemWindowInsets.left, systemWindowInsets.top,
    542                 systemWindowInsets.right, systemWindowInsets.bottom);
    543     }
    544 
    545     /**
    546      * Returns the stable insets in pixels.
    547      *
    548      * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
    549      * partially or fully obscured by the system UI elements.  This value does not change
    550      * based on the visibility state of those elements; for example, if the status bar is
    551      * normally shown, but temporarily hidden, the stable inset will still provide the inset
    552      * associated with the status bar being shown.</p>
    553      *
    554      * @return The stable insets
    555      */
    556     @NonNull
    557     public Insets getStableInsets() {
    558         return getInsets(mTypeMaxInsetsMap, compatSystemInsets());
    559     }
    560 
    561     /**
    562      * Returns the top stable inset in pixels.
    563      *
    564      * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
    565      * partially or fully obscured by the system UI elements.  This value does not change
    566      * based on the visibility state of those elements; for example, if the status bar is
    567      * normally shown, but temporarily hidden, the stable inset will still provide the inset
    568      * associated with the status bar being shown.</p>
    569      *
    570      * @return The top stable inset
    571      */
    572     public int getStableInsetTop() {
    573         return getStableInsets().top;
    574     }
    575 
    576     /**
    577      * Returns the left stable inset in pixels.
    578      *
    579      * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
    580      * partially or fully obscured by the system UI elements.  This value does not change
    581      * based on the visibility state of those elements; for example, if the status bar is
    582      * normally shown, but temporarily hidden, the stable inset will still provide the inset
    583      * associated with the status bar being shown.</p>
    584      *
    585      * @return The left stable inset
    586      */
    587     public int getStableInsetLeft() {
    588         return getStableInsets().left;
    589     }
    590 
    591     /**
    592      * Returns the right stable inset in pixels.
    593      *
    594      * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
    595      * partially or fully obscured by the system UI elements.  This value does not change
    596      * based on the visibility state of those elements; for example, if the status bar is
    597      * normally shown, but temporarily hidden, the stable inset will still provide the inset
    598      * associated with the status bar being shown.</p>
    599      *
    600      * @return The right stable inset
    601      */
    602     public int getStableInsetRight() {
    603         return getStableInsets().right;
    604     }
    605 
    606     /**
    607      * Returns the bottom stable inset in pixels.
    608      *
    609      * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
    610      * partially or fully obscured by the system UI elements.  This value does not change
    611      * based on the visibility state of those elements; for example, if the status bar is
    612      * normally shown, but temporarily hidden, the stable inset will still provide the inset
    613      * associated with the status bar being shown.</p>
    614      *
    615      * @return The bottom stable inset
    616      */
    617     public int getStableInsetBottom() {
    618         return getStableInsets().bottom;
    619     }
    620 
    621     /**
    622      * Returns true if this WindowInsets has nonzero stable insets.
    623      *
    624      * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
    625      * partially or fully obscured by the system UI elements.  This value does not change
    626      * based on the visibility state of those elements; for example, if the status bar is
    627      * normally shown, but temporarily hidden, the stable inset will still provide the inset
    628      * associated with the status bar being shown.</p>
    629      *
    630      * @return true if any of the stable inset values are nonzero
    631      */
    632     public boolean hasStableInsets() {
    633         return !getStableInsets().equals(Insets.NONE);
    634     }
    635 
    636     /**
    637      * Returns the system gesture insets.
    638      *
    639      * <p>The system gesture insets represent the area of a window where system gestures have
    640      * priority and may consume some or all touch input, e.g. due to the a system bar
    641      * occupying it, or it being reserved for touch-only gestures.
    642      *
    643      * <p>An app can declare priority over system gestures with
    644      * {@link View#setSystemGestureExclusionRects} outside of the
    645      * {@link #getMandatorySystemGestureInsets() mandatory system gesture insets}.
    646      *
    647      * <p>Simple taps are guaranteed to reach the window even within the system gesture insets,
    648      * as long as they are outside the {@link #getTappableElementInsets() system window insets}.
    649      *
    650      * <p>When {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} is requested, an inset will be returned
    651      * even when the system gestures are inactive due to
    652      * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} or
    653      * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}.
    654      *
    655      * <p>This inset is consumed together with the {@link #getSystemWindowInsets()
    656      * system window insets} by {@link #consumeSystemWindowInsets()}.
    657      *
    658      * @see #getMandatorySystemGestureInsets
    659      */
    660     @NonNull
    661     public Insets getSystemGestureInsets() {
    662         return getInsets(mTypeInsetsMap, SYSTEM_GESTURES);
    663     }
    664 
    665     /**
    666      * Returns the mandatory system gesture insets.
    667      *
    668      * <p>The mandatory system gesture insets represent the area of a window where mandatory system
    669      * gestures have priority and may consume some or all touch input, e.g. due to the a system bar
    670      * occupying it, or it being reserved for touch-only gestures.
    671      *
    672      * <p>In contrast to {@link #getSystemGestureInsets regular system gestures}, <b>mandatory</b>
    673      * system gestures cannot be overriden by {@link View#setSystemGestureExclusionRects}.
    674      *
    675      * <p>Simple taps are guaranteed to reach the window even within the system gesture insets,
    676      * as long as they are outside the {@link #getTappableElementInsets() system window insets}.
    677      *
    678      * <p>When {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} is requested, an inset will be returned
    679      * even when the system gestures are inactive due to
    680      * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} or
    681      * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}.
    682      *
    683      * <p>This inset is consumed together with the {@link #getSystemWindowInsets()
    684      * system window insets} by {@link #consumeSystemWindowInsets()}.
    685      *
    686      * @see #getSystemGestureInsets
    687      */
    688     @NonNull
    689     public Insets getMandatorySystemGestureInsets() {
    690         return getInsets(mTypeInsetsMap, MANDATORY_SYSTEM_GESTURES);
    691     }
    692 
    693     /**
    694      * Returns the tappable element insets.
    695      *
    696      * <p>The tappable element insets represent how much tappable elements <b>must at least</b> be
    697      * inset to remain both tappable and visually unobstructed by persistent system windows.
    698      *
    699      * <p>This may be smaller than {@link #getSystemWindowInsets()} if the system window is
    700      * largely transparent and lets through simple taps (but not necessarily more complex gestures).
    701      *
    702      * <p>Note that generally, tappable elements <strong>should</strong> be aligned with the
    703      * {@link #getSystemWindowInsets() system window insets} instead to avoid overlapping with the
    704      * system bars.
    705      *
    706      * <p>When {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} is requested, an inset will be returned
    707      * even when the area covered by the inset would be tappable due to
    708      * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} or
    709      * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}.
    710      *
    711      * <p>This inset is consumed together with the {@link #getSystemWindowInsets()
    712      * system window insets} by {@link #consumeSystemWindowInsets()}.
    713      */
    714     @NonNull
    715     public Insets getTappableElementInsets() {
    716         return getInsets(mTypeInsetsMap, TAPPABLE_ELEMENT);
    717     }
    718 
    719     /**
    720      * Returns a copy of this WindowInsets with the stable insets fully consumed.
    721      *
    722      * @return A modified copy of this WindowInsets
    723      */
    724     @NonNull
    725     public WindowInsets consumeStableInsets() {
    726         return new WindowInsets(mSystemWindowInsetsConsumed ? null : mTypeInsetsMap, null,
    727                 mTypeVisibilityMap, mIsRound, mAlwaysConsumeSystemBars,
    728                 displayCutoutCopyConstructorArgument(this));
    729     }
    730 
    731     /**
    732      * @hide
    733      */
    734     public boolean shouldAlwaysConsumeSystemBars() {
    735         return mAlwaysConsumeSystemBars;
    736     }
    737 
    738     @Override
    739     public String toString() {
    740         return "WindowInsets{systemWindowInsets=" + getSystemWindowInsets()
    741                 + " stableInsets=" + getStableInsets()
    742                 + " sysGestureInsets=" + getSystemGestureInsets()
    743                 + (mDisplayCutout != null ? " cutout=" + mDisplayCutout : "")
    744                 + (isRound() ? " round" : "")
    745                 + "}";
    746     }
    747 
    748     /**
    749      * Returns a copy of this instance inset in the given directions.
    750      *
    751      * @see #inset(int, int, int, int)
    752      * @deprecated use {@link #inset(Insets)}
    753      * @hide
    754      */
    755     @Deprecated
    756     @NonNull
    757     public WindowInsets inset(Rect r) {
    758         return inset(r.left, r.top, r.right, r.bottom);
    759     }
    760 
    761     /**
    762      * Returns a copy of this instance inset in the given directions.
    763      *
    764      * @see #inset(int, int, int, int)
    765      * @hide
    766      */
    767     @NonNull
    768     public WindowInsets inset(Insets insets) {
    769         return inset(insets.left, insets.top, insets.right, insets.bottom);
    770     }
    771 
    772     /**
    773      * Returns a copy of this instance inset in the given directions.
    774      *
    775      * This is intended for dispatching insets to areas of the window that are smaller than the
    776      * current area.
    777      *
    778      * <p>Example:
    779      * <pre>
    780      * childView.dispatchApplyWindowInsets(insets.inset(
    781      *         childMarginLeft, childMarginTop, childMarginBottom, childMarginRight));
    782      * </pre>
    783      *
    784      * @param left the amount of insets to remove from the left. Must be non-negative.
    785      * @param top the amount of insets to remove from the top. Must be non-negative.
    786      * @param right the amount of insets to remove from the right. Must be non-negative.
    787      * @param bottom the amount of insets to remove from the bottom. Must be non-negative.
    788      *
    789      * @return the inset insets
    790      */
    791     @NonNull
    792     public WindowInsets inset(@IntRange(from = 0) int left, @IntRange(from = 0) int top,
    793             @IntRange(from = 0) int right, @IntRange(from = 0) int bottom) {
    794         Preconditions.checkArgumentNonnegative(left);
    795         Preconditions.checkArgumentNonnegative(top);
    796         Preconditions.checkArgumentNonnegative(right);
    797         Preconditions.checkArgumentNonnegative(bottom);
    798 
    799         return new WindowInsets(
    800                 mSystemWindowInsetsConsumed
    801                         ? null
    802                         : insetInsets(mTypeInsetsMap, left, top, right, bottom),
    803                 mStableInsetsConsumed
    804                         ? null
    805                         : insetInsets(mTypeMaxInsetsMap, left, top, right, bottom),
    806                 mTypeVisibilityMap,
    807                 mIsRound, mAlwaysConsumeSystemBars,
    808                 mDisplayCutoutConsumed
    809                         ? null
    810                         : mDisplayCutout == null
    811                                 ? DisplayCutout.NO_CUTOUT
    812                                 : mDisplayCutout.inset(left, top, right, bottom));
    813     }
    814 
    815     @Override
    816     public boolean equals(Object o) {
    817         if (this == o) return true;
    818         if (o == null || !(o instanceof WindowInsets)) return false;
    819         WindowInsets that = (WindowInsets) o;
    820 
    821         return mIsRound == that.mIsRound
    822                 && mAlwaysConsumeSystemBars == that.mAlwaysConsumeSystemBars
    823                 && mSystemWindowInsetsConsumed == that.mSystemWindowInsetsConsumed
    824                 && mStableInsetsConsumed == that.mStableInsetsConsumed
    825                 && mDisplayCutoutConsumed == that.mDisplayCutoutConsumed
    826                 && Arrays.equals(mTypeInsetsMap, that.mTypeInsetsMap)
    827                 && Arrays.equals(mTypeMaxInsetsMap, that.mTypeMaxInsetsMap)
    828                 && Arrays.equals(mTypeVisibilityMap, that.mTypeVisibilityMap)
    829                 && Objects.equals(mDisplayCutout, that.mDisplayCutout);
    830     }
    831 
    832     @Override
    833     public int hashCode() {
    834         return Objects.hash(Arrays.hashCode(mTypeInsetsMap), Arrays.hashCode(mTypeMaxInsetsMap),
    835                 Arrays.hashCode(mTypeVisibilityMap), mIsRound, mDisplayCutout,
    836                 mAlwaysConsumeSystemBars, mSystemWindowInsetsConsumed, mStableInsetsConsumed,
    837                 mDisplayCutoutConsumed);
    838     }
    839 
    840 
    841     /**
    842      * Insets every inset in {@code typeInsetsMap} by the specified left, top, right, bottom.
    843      *
    844      * @return {@code typeInsetsMap} if no inset was modified; a copy of the map with the modified
    845      *          insets otherwise.
    846      */
    847     private static Insets[] insetInsets(
    848             Insets[] typeInsetsMap, int left, int top, int right, int bottom) {
    849         boolean cloned = false;
    850         for (int i = 0; i < SIZE; i++) {
    851             Insets insets = typeInsetsMap[i];
    852             if (insets == null) {
    853                 continue;
    854             }
    855             Insets insetInsets = insetInsets(insets, left, top, right, bottom);
    856             if (insetInsets != insets) {
    857                 if (!cloned) {
    858                     typeInsetsMap = typeInsetsMap.clone();
    859                     cloned = true;
    860                 }
    861                 typeInsetsMap[i] = insetInsets;
    862             }
    863         }
    864         return typeInsetsMap;
    865     }
    866 
    867     private static Insets insetInsets(Insets insets, int left, int top, int right, int bottom) {
    868         int newLeft = Math.max(0, insets.left - left);
    869         int newTop = Math.max(0, insets.top - top);
    870         int newRight = Math.max(0, insets.right - right);
    871         int newBottom = Math.max(0, insets.bottom - bottom);
    872         if (newLeft == left && newTop == top && newRight == right && newBottom == bottom) {
    873             return insets;
    874         }
    875         return Insets.of(newLeft, newTop, newRight, newBottom);
    876     }
    877 
    878     /**
    879      * @return whether system window insets have been consumed.
    880      */
    881     boolean isSystemWindowInsetsConsumed() {
    882         return mSystemWindowInsetsConsumed;
    883     }
    884 
    885     /**
    886      * Builder for WindowInsets.
    887      */
    888     public static final class Builder {
    889 
    890         private final Insets[] mTypeInsetsMap;
    891         private final Insets[] mTypeMaxInsetsMap;
    892         private final boolean[] mTypeVisibilityMap;
    893         private boolean mSystemInsetsConsumed = true;
    894         private boolean mStableInsetsConsumed = true;
    895 
    896         private DisplayCutout mDisplayCutout;
    897 
    898         private boolean mIsRound;
    899         private boolean mAlwaysConsumeSystemBars;
    900 
    901         /**
    902          * Creates a builder where all insets are initially consumed.
    903          */
    904         public Builder() {
    905             mTypeInsetsMap = new Insets[SIZE];
    906             mTypeMaxInsetsMap = new Insets[SIZE];
    907             mTypeVisibilityMap = new boolean[SIZE];
    908         }
    909 
    910         /**
    911          * Creates a builder where all insets are initialized from {@link WindowInsets}.
    912          *
    913          * @param insets the instance to initialize from.
    914          */
    915         public Builder(@NonNull WindowInsets insets) {
    916             mTypeInsetsMap = insets.mTypeInsetsMap.clone();
    917             mTypeMaxInsetsMap = insets.mTypeMaxInsetsMap.clone();
    918             mTypeVisibilityMap = insets.mTypeVisibilityMap.clone();
    919             mSystemInsetsConsumed = insets.mSystemWindowInsetsConsumed;
    920             mStableInsetsConsumed = insets.mStableInsetsConsumed;
    921             mDisplayCutout = displayCutoutCopyConstructorArgument(insets);
    922             mIsRound = insets.mIsRound;
    923             mAlwaysConsumeSystemBars = insets.mAlwaysConsumeSystemBars;
    924         }
    925 
    926         /**
    927          * Sets system window insets in pixels.
    928          *
    929          * <p>The system window inset represents the area of a full-screen window that is
    930          * partially or fully obscured by the status bar, navigation bar, IME or other system
    931          * windows.</p>
    932          *
    933          * @see #getSystemWindowInsets()
    934          * @return itself
    935          */
    936         @NonNull
    937         public Builder setSystemWindowInsets(@NonNull Insets systemWindowInsets) {
    938             Preconditions.checkNotNull(systemWindowInsets);
    939             assignCompatInsets(mTypeInsetsMap, systemWindowInsets.toRect());
    940             mSystemInsetsConsumed = false;
    941             return this;
    942         }
    943 
    944         /**
    945          * Sets system gesture insets in pixels.
    946          *
    947          * <p>The system gesture insets represent the area of a window where system gestures have
    948          * priority and may consume some or all touch input, e.g. due to the a system bar
    949          * occupying it, or it being reserved for touch-only gestures.
    950          *
    951          * @see #getSystemGestureInsets()
    952          * @return itself
    953          */
    954         @NonNull
    955         public Builder setSystemGestureInsets(@NonNull Insets insets) {
    956             WindowInsets.setInsets(mTypeInsetsMap, SYSTEM_GESTURES, insets);
    957             return this;
    958         }
    959 
    960         /**
    961          * Sets mandatory system gesture insets in pixels.
    962          *
    963          * <p>The mandatory system gesture insets represent the area of a window where mandatory
    964          * system gestures have priority and may consume some or all touch input, e.g. due to the a
    965          * system bar occupying it, or it being reserved for touch-only gestures.
    966          *
    967          * <p>In contrast to {@link #setSystemGestureInsets regular system gestures},
    968          * <b>mandatory</b> system gestures cannot be overriden by
    969          * {@link View#setSystemGestureExclusionRects}.
    970          *
    971          * @see #getMandatorySystemGestureInsets()
    972          * @return itself
    973          */
    974         @NonNull
    975         public Builder setMandatorySystemGestureInsets(@NonNull Insets insets) {
    976             WindowInsets.setInsets(mTypeInsetsMap, MANDATORY_SYSTEM_GESTURES, insets);
    977             return this;
    978         }
    979 
    980         /**
    981          * Sets tappable element insets in pixels.
    982          *
    983          * <p>The tappable element insets represent how much tappable elements <b>must at least</b>
    984          * be inset to remain both tappable and visually unobstructed by persistent system windows.
    985          *
    986          * @see #getTappableElementInsets()
    987          * @return itself
    988          */
    989         @NonNull
    990         public Builder setTappableElementInsets(@NonNull Insets insets) {
    991             WindowInsets.setInsets(mTypeInsetsMap, TAPPABLE_ELEMENT, insets);
    992             return this;
    993         }
    994 
    995         /**
    996          * Sets the insets of a specific window type in pixels.
    997          *
    998          * <p>The insets represents the area of a a window that is partially or fully obscured by
    999          * the system windows identified by {@code typeMask}.
   1000          * </p>
   1001          *
   1002          * @see #getInsets(int)
   1003          *
   1004          * @param typeMask The bitmask of {@link InsetType} to set the insets for.
   1005          * @param insets The insets to set.
   1006          *
   1007          * @return itself
   1008          * @hide pending unhide
   1009          */
   1010         @NonNull
   1011         public Builder setInsets(@InsetType int typeMask, @NonNull Insets insets) {
   1012             Preconditions.checkNotNull(insets);
   1013             WindowInsets.setInsets(mTypeInsetsMap, typeMask, insets);
   1014             mSystemInsetsConsumed = false;
   1015             return this;
   1016         }
   1017 
   1018         /**
   1019          * Sets the maximum amount of insets a specific window type in pixels.
   1020          *
   1021          * <p>The maximum insets represents the area of a a window that that <b>may</b> be partially
   1022          * or fully obscured by the system windows identified by {@code typeMask}. This value does
   1023          * not change based on the visibility state of those elements. for example, if the status
   1024          * bar is normally shown, but temporarily hidden, the maximum inset will still provide the
   1025          * inset associated with the status bar being shown.</p>
   1026          *
   1027          * @see #getMaxInsets(int)
   1028          *
   1029          * @param typeMask The bitmask of {@link InsetType} to set the insets for.
   1030          * @param insets The insets to set.
   1031          *
   1032          * @return itself
   1033          *
   1034          * @throws IllegalArgumentException If {@code typeMask} contains {@link Type#ime()}. Maximum
   1035          *                                  insets are not available for this type as the height of
   1036          *                                  the IME is dynamic depending on the {@link EditorInfo}
   1037          *                                  of the currently focused view, as well as the UI
   1038          *                                  state of the IME.
   1039          * @hide pending unhide
   1040          */
   1041         @NonNull
   1042         public Builder setMaxInsets(@InsetType int typeMask, @NonNull Insets insets)
   1043                 throws IllegalArgumentException{
   1044             if (typeMask == IME) {
   1045                 throw new IllegalArgumentException("Maximum inset not available for IME");
   1046             }
   1047             Preconditions.checkNotNull(insets);
   1048             WindowInsets.setInsets(mTypeMaxInsetsMap, typeMask, insets);
   1049             mStableInsetsConsumed = false;
   1050             return this;
   1051         }
   1052 
   1053         /**
   1054          * Sets whether windows that can cause insets are currently visible on screen.
   1055          *
   1056          *
   1057          * @see #isVisible(int)
   1058          *
   1059          * @param typeMask The bitmask of {@link InsetType} to set the visibility for.
   1060          * @param visible Whether to mark the windows as visible or not.
   1061          *
   1062          * @return itself
   1063          * @hide pending unhide
   1064          */
   1065         @NonNull
   1066         public Builder setVisible(@InsetType int typeMask, boolean visible) {
   1067             for (int i = FIRST; i <= LAST; i = i << 1) {
   1068                 if ((typeMask & i) == 0) {
   1069                     continue;
   1070                 }
   1071                 mTypeVisibilityMap[indexOf(i)] = visible;
   1072             }
   1073             return this;
   1074         }
   1075 
   1076         /**
   1077          * Sets the stable insets in pixels.
   1078          *
   1079          * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
   1080          * partially or fully obscured by the system UI elements.  This value does not change
   1081          * based on the visibility state of those elements; for example, if the status bar is
   1082          * normally shown, but temporarily hidden, the stable inset will still provide the inset
   1083          * associated with the status bar being shown.</p>
   1084          *
   1085          * @see #getStableInsets()
   1086          * @return itself
   1087          */
   1088         @NonNull
   1089         public Builder setStableInsets(@NonNull Insets stableInsets) {
   1090             Preconditions.checkNotNull(stableInsets);
   1091             assignCompatInsets(mTypeMaxInsetsMap, stableInsets.toRect());
   1092             mStableInsetsConsumed = false;
   1093             return this;
   1094         }
   1095 
   1096         /**
   1097          * Sets the display cutout.
   1098          *
   1099          * @see #getDisplayCutout()
   1100          * @param displayCutout the display cutout or null if there is none
   1101          * @return itself
   1102          */
   1103         @NonNull
   1104         public Builder setDisplayCutout(@Nullable DisplayCutout displayCutout) {
   1105             mDisplayCutout = displayCutout != null ? displayCutout : DisplayCutout.NO_CUTOUT;
   1106             return this;
   1107         }
   1108 
   1109         /** @hide */
   1110         @NonNull
   1111         public Builder setRound(boolean round) {
   1112             mIsRound = round;
   1113             return this;
   1114         }
   1115 
   1116         /** @hide */
   1117         @NonNull
   1118         public Builder setAlwaysConsumeSystemBars(boolean alwaysConsumeSystemBars) {
   1119             mAlwaysConsumeSystemBars = alwaysConsumeSystemBars;
   1120             return this;
   1121         }
   1122 
   1123         /**
   1124          * Builds a {@link WindowInsets} instance.
   1125          *
   1126          * @return the {@link WindowInsets} instance.
   1127          */
   1128         @NonNull
   1129         public WindowInsets build() {
   1130             return new WindowInsets(mSystemInsetsConsumed ? null : mTypeInsetsMap,
   1131                     mStableInsetsConsumed ? null : mTypeMaxInsetsMap, mTypeVisibilityMap,
   1132                     mIsRound, mAlwaysConsumeSystemBars, mDisplayCutout);
   1133         }
   1134     }
   1135 
   1136     /**
   1137      * Class that defines different types of sources causing window insets.
   1138      * @hide pending unhide
   1139      */
   1140     public static final class Type {
   1141 
   1142         static final int FIRST = 1 << 0;
   1143         static final int TOP_BAR = FIRST;
   1144 
   1145         static final int IME = 1 << 1;
   1146         static final int SIDE_BARS = 1 << 2;
   1147 
   1148         static final int SYSTEM_GESTURES = 1 << 3;
   1149         static final int MANDATORY_SYSTEM_GESTURES = 1 << 4;
   1150         static final int TAPPABLE_ELEMENT = 1 << 5;
   1151 
   1152         static final int LAST = 1 << 6;
   1153         static final int SIZE = 7;
   1154         static final int WINDOW_DECOR = LAST;
   1155 
   1156         static int indexOf(@InsetType int type) {
   1157             switch (type) {
   1158                 case TOP_BAR:
   1159                     return 0;
   1160                 case IME:
   1161                     return 1;
   1162                 case SIDE_BARS:
   1163                     return 2;
   1164                 case SYSTEM_GESTURES:
   1165                     return 3;
   1166                 case MANDATORY_SYSTEM_GESTURES:
   1167                     return 4;
   1168                 case TAPPABLE_ELEMENT:
   1169                     return 5;
   1170                 case WINDOW_DECOR:
   1171                     return 6;
   1172                 default:
   1173                     throw new IllegalArgumentException("type needs to be >= FIRST and <= LAST,"
   1174                             + " type=" + type);
   1175             }
   1176         }
   1177 
   1178         private Type() {
   1179         }
   1180 
   1181         /** @hide */
   1182         @Retention(RetentionPolicy.SOURCE)
   1183         @IntDef(flag = true, value = { TOP_BAR, IME, SIDE_BARS, WINDOW_DECOR, SYSTEM_GESTURES,
   1184                 MANDATORY_SYSTEM_GESTURES, TAPPABLE_ELEMENT})
   1185         public @interface InsetType {
   1186         }
   1187 
   1188         /**
   1189          * @return An inset type representing the top bar of a window, which can be the status
   1190          *         bar on handheld-like devices as well as a caption bar.
   1191          */
   1192         public static @InsetType int topBar() {
   1193             return TOP_BAR;
   1194         }
   1195 
   1196         /**
   1197          * @return An inset type representing the window of an {@link InputMethod}.
   1198          */
   1199         public static @InsetType int ime() {
   1200             return IME;
   1201         }
   1202 
   1203         /**
   1204          * @return An inset type representing any system bars that are not {@link #topBar()}.
   1205          */
   1206         public static @InsetType int sideBars() {
   1207             return SIDE_BARS;
   1208         }
   1209 
   1210         /**
   1211          * @return An inset type representing decor that is being app-controlled.
   1212          */
   1213         public static @InsetType int windowDecor() {
   1214             return WINDOW_DECOR;
   1215         }
   1216 
   1217         /**
   1218          * Returns an inset type representing the system gesture insets.
   1219          *
   1220          * <p>The system gesture insets represent the area of a window where system gestures have
   1221          * priority and may consume some or all touch input, e.g. due to the a system bar
   1222          * occupying it, or it being reserved for touch-only gestures.
   1223          *
   1224          * <p>Simple taps are guaranteed to reach the window even within the system gesture insets,
   1225          * as long as they are outside the {@link #getSystemWindowInsets() system window insets}.
   1226          *
   1227          * <p>When {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} is requested, an inset will be returned
   1228          * even when the system gestures are inactive due to
   1229          * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} or
   1230          * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}.
   1231          *
   1232          * @see #getSystemGestureInsets()
   1233          */
   1234         public static @InsetType int systemGestures() {
   1235             return SYSTEM_GESTURES;
   1236         }
   1237 
   1238         /**
   1239          * @see #getMandatorySystemGestureInsets
   1240          */
   1241         public static @InsetType int mandatorySystemGestures() {
   1242             return MANDATORY_SYSTEM_GESTURES;
   1243         }
   1244 
   1245         /**
   1246          * @see #getTappableElementInsets
   1247          */
   1248         public static @InsetType int tappableElement() {
   1249             return TAPPABLE_ELEMENT;
   1250         }
   1251 
   1252         /**
   1253          * @return All system bars. Includes {@link #topBar()} as well as {@link #sideBars()}, but
   1254          *         not {@link #ime()}.
   1255          */
   1256         public static @InsetType int systemBars() {
   1257             return TOP_BAR | SIDE_BARS;
   1258         }
   1259 
   1260         /**
   1261          * @return Inset types representing the list of bars that traditionally were denoted as
   1262          *         system insets.
   1263          * @hide
   1264          */
   1265         static @InsetType int compatSystemInsets() {
   1266             return TOP_BAR | SIDE_BARS | IME;
   1267         }
   1268 
   1269         /**
   1270          * @return All inset types combined.
   1271          *
   1272          * TODO: Figure out if this makes sense at all, mixing e.g {@link #systemGestures()} and
   1273          *       {@link #ime()} does not seem very useful.
   1274          */
   1275         public static @InsetType int all() {
   1276             return 0xFFFFFFFF;
   1277         }
   1278     }
   1279 }
   1280