• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Surface.ROTATION_0;
21 import static android.view.WindowInsets.Type.DISPLAY_CUTOUT;
22 import static android.view.WindowInsets.Type.FIRST;
23 import static android.view.WindowInsets.Type.IME;
24 import static android.view.WindowInsets.Type.LAST;
25 import static android.view.WindowInsets.Type.MANDATORY_SYSTEM_GESTURES;
26 import static android.view.WindowInsets.Type.NAVIGATION_BARS;
27 import static android.view.WindowInsets.Type.SIZE;
28 import static android.view.WindowInsets.Type.STATUS_BARS;
29 import static android.view.WindowInsets.Type.SYSTEM_GESTURES;
30 import static android.view.WindowInsets.Type.TAPPABLE_ELEMENT;
31 import static android.view.WindowInsets.Type.all;
32 import static android.view.WindowInsets.Type.ime;
33 import static android.view.WindowInsets.Type.indexOf;
34 import static android.view.WindowInsets.Type.systemBars;
35 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
36 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
37 
38 import android.annotation.IntDef;
39 import android.annotation.IntRange;
40 import android.annotation.NonNull;
41 import android.annotation.Nullable;
42 import android.compat.annotation.UnsupportedAppUsage;
43 import android.content.Intent;
44 import android.graphics.Insets;
45 import android.graphics.Rect;
46 import android.util.SparseArray;
47 import android.view.View.OnApplyWindowInsetsListener;
48 import android.view.WindowInsets.Type.InsetsType;
49 import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
50 import android.view.inputmethod.EditorInfo;
51 import android.view.inputmethod.InputMethod;
52 
53 import com.android.internal.annotations.VisibleForTesting;
54 import com.android.internal.util.Preconditions;
55 
56 import java.lang.annotation.Retention;
57 import java.lang.annotation.RetentionPolicy;
58 import java.util.Arrays;
59 import java.util.Objects;
60 
61 /**
62  * Describes a set of insets for window content.
63  *
64  * <p>WindowInsets are immutable and may be expanded to include more inset types in the future.
65  * To adjust insets, use one of the supplied clone methods to obtain a new WindowInsets instance
66  * with the adjusted properties.</p>
67  *
68  * <p>Note: Before {@link android.os.Build.VERSION_CODES#P P}, WindowInsets instances were only
69  * immutable during a single layout pass (i.e. would return the same values between
70  * {@link View#onApplyWindowInsets} and {@link View#onLayout}, but could return other values
71  * otherwise). Starting with {@link android.os.Build.VERSION_CODES#P P}, WindowInsets are
72  * always immutable and implement equality.
73  *
74  * @see View.OnApplyWindowInsetsListener
75  * @see View#onApplyWindowInsets(WindowInsets)
76  */
77 public final class WindowInsets {
78 
79     private final Insets[] mTypeInsetsMap;
80     private final Insets[] mTypeMaxInsetsMap;
81     private final boolean[] mTypeVisibilityMap;
82 
83     @Nullable private Rect mTempRect;
84     private final boolean mIsRound;
85     @Nullable private final DisplayCutout mDisplayCutout;
86     @Nullable private final RoundedCorners mRoundedCorners;
87     @Nullable private final PrivacyIndicatorBounds mPrivacyIndicatorBounds;
88 
89     /**
90      * In multi-window we force show the navigation bar. Because we don't want that the surface size
91      * changes in this mode, we instead have a flag whether the navigation bar size should always
92      * be consumed, so the app is treated like there is no virtual navigation bar at all.
93      */
94     private final boolean mAlwaysConsumeSystemBars;
95 
96     private final boolean mSystemWindowInsetsConsumed;
97     private final boolean mStableInsetsConsumed;
98     private final boolean mDisplayCutoutConsumed;
99 
100     private final int mCompatInsetsTypes;
101     private final boolean mCompatIgnoreVisibility;
102 
103     /**
104      * A {@link WindowInsets} instance for which {@link #isConsumed()} returns {@code true}.
105      * <p>
106      * This can be used during insets dispatch in the view hierarchy by returning this value from
107      * {@link View#onApplyWindowInsets(WindowInsets)} or
108      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets)} to stop dispatch
109      * the insets to its children to avoid traversing the entire view hierarchy.
110      * <p>
111      * The application should return this instance once it has taken care of all insets on a certain
112      * level in the view hierarchy, and doesn't need to dispatch to its children anymore for better
113      * performance.
114      *
115      * @see #isConsumed()
116      */
117     public static final @NonNull WindowInsets CONSUMED;
118 
119     static {
120         CONSUMED = new WindowInsets((Rect) null, null, false, false, null);
121     }
122 
123     /**
124      * Construct a new WindowInsets from individual insets.
125      *
126      * A {@code null} inset indicates that the respective inset is consumed.
127      *
128      * @hide
129      * @deprecated Use {@link WindowInsets(SparseArray, SparseArray, boolean, boolean, DisplayCutout)}
130      */
131     @Deprecated
WindowInsets(Rect systemWindowInsetsRect, Rect stableInsetsRect, boolean isRound, boolean alwaysConsumeSystemBars, DisplayCutout displayCutout)132     public WindowInsets(Rect systemWindowInsetsRect, Rect stableInsetsRect, boolean isRound,
133             boolean alwaysConsumeSystemBars, DisplayCutout displayCutout) {
134         this(createCompatTypeMap(systemWindowInsetsRect), createCompatTypeMap(stableInsetsRect),
135                 createCompatVisibilityMap(createCompatTypeMap(systemWindowInsetsRect)),
136                 isRound, alwaysConsumeSystemBars, displayCutout, null, null,
137                 systemBars(), false /* compatIgnoreVisibility */);
138     }
139 
140     /**
141      * Construct a new WindowInsets from individual insets.
142      *
143      * {@code typeInsetsMap} and {@code typeMaxInsetsMap} are a map of indexOf(type) -> insets that
144      * contain the information what kind of system bars causes how much insets. The insets in this
145      * map are non-additive; i.e. they have the same origin. In other words: If two system bars
146      * overlap on one side, the insets of the larger bar will also include the insets of the smaller
147      * bar.
148      *
149      * {@code null} type inset map indicates that the respective inset is fully consumed.
150      * @hide
151      */
WindowInsets(@ullable Insets[] typeInsetsMap, @Nullable Insets[] typeMaxInsetsMap, boolean[] typeVisibilityMap, boolean isRound, boolean alwaysConsumeSystemBars, DisplayCutout displayCutout, RoundedCorners roundedCorners, PrivacyIndicatorBounds privacyIndicatorBounds, @InsetsType int compatInsetsTypes, boolean compatIgnoreVisibility)152     public WindowInsets(@Nullable Insets[] typeInsetsMap,
153             @Nullable Insets[] typeMaxInsetsMap,
154             boolean[] typeVisibilityMap,
155             boolean isRound,
156             boolean alwaysConsumeSystemBars, DisplayCutout displayCutout,
157             RoundedCorners roundedCorners,
158             PrivacyIndicatorBounds privacyIndicatorBounds,
159             @InsetsType int compatInsetsTypes, boolean compatIgnoreVisibility) {
160         mSystemWindowInsetsConsumed = typeInsetsMap == null;
161         mTypeInsetsMap = mSystemWindowInsetsConsumed
162                 ? new Insets[SIZE]
163                 : typeInsetsMap.clone();
164 
165         mStableInsetsConsumed = typeMaxInsetsMap == null;
166         mTypeMaxInsetsMap = mStableInsetsConsumed
167                 ? new Insets[SIZE]
168                 : typeMaxInsetsMap.clone();
169 
170         mTypeVisibilityMap = typeVisibilityMap;
171         mIsRound = isRound;
172         mAlwaysConsumeSystemBars = alwaysConsumeSystemBars;
173         mCompatInsetsTypes = compatInsetsTypes;
174         mCompatIgnoreVisibility = compatIgnoreVisibility;
175 
176         mDisplayCutoutConsumed = displayCutout == null;
177         mDisplayCutout = (mDisplayCutoutConsumed || displayCutout.isEmpty())
178                 ? null : displayCutout;
179 
180         mRoundedCorners = roundedCorners;
181         mPrivacyIndicatorBounds = privacyIndicatorBounds;
182     }
183 
184     /**
185      * Construct a new WindowInsets, copying all values from a source WindowInsets.
186      *
187      * @param src Source to copy insets from
188      */
WindowInsets(WindowInsets src)189     public WindowInsets(WindowInsets src) {
190         this(src.mSystemWindowInsetsConsumed ? null : src.mTypeInsetsMap,
191                 src.mStableInsetsConsumed ? null : src.mTypeMaxInsetsMap,
192                 src.mTypeVisibilityMap, src.mIsRound,
193                 src.mAlwaysConsumeSystemBars, displayCutoutCopyConstructorArgument(src),
194                 src.mRoundedCorners,
195                 src.mPrivacyIndicatorBounds,
196                 src.mCompatInsetsTypes,
197                 src.mCompatIgnoreVisibility);
198     }
199 
displayCutoutCopyConstructorArgument(WindowInsets w)200     private static DisplayCutout displayCutoutCopyConstructorArgument(WindowInsets w) {
201         if (w.mDisplayCutoutConsumed) {
202             return null;
203         } else if (w.mDisplayCutout == null) {
204             return DisplayCutout.NO_CUTOUT;
205         } else {
206             return w.mDisplayCutout;
207         }
208     }
209 
210     /**
211      * @return The insets that include system bars indicated by {@code typeMask}, taken from
212      *         {@code typeInsetsMap}.
213      */
getInsets(Insets[] typeInsetsMap, @InsetsType int typeMask)214     static Insets getInsets(Insets[] typeInsetsMap, @InsetsType int typeMask) {
215         Insets result = null;
216         for (int i = FIRST; i <= LAST; i = i << 1) {
217             if ((typeMask & i) == 0) {
218                 continue;
219             }
220             Insets insets = typeInsetsMap[indexOf(i)];
221             if (insets == null) {
222                 continue;
223             }
224             if (result == null) {
225                 result = insets;
226             } else {
227                 result = Insets.max(result, insets);
228             }
229         }
230         return result == null ? Insets.NONE : result;
231     }
232 
233     /**
234      * Sets all entries in {@code typeInsetsMap} that belong to {@code typeMask} to {@code insets},
235      */
setInsets(Insets[] typeInsetsMap, @InsetsType int typeMask, Insets insets)236     private static void setInsets(Insets[] typeInsetsMap, @InsetsType int typeMask, Insets insets) {
237         for (int i = FIRST; i <= LAST; i = i << 1) {
238             if ((typeMask & i) == 0) {
239                 continue;
240             }
241             typeInsetsMap[indexOf(i)] = insets;
242         }
243     }
244 
245     /** @hide */
246     @UnsupportedAppUsage
WindowInsets(Rect systemWindowInsets)247     public WindowInsets(Rect systemWindowInsets) {
248         this(createCompatTypeMap(systemWindowInsets), null, new boolean[SIZE], false, false, null,
249                 null, null, systemBars(), false /* compatIgnoreVisibility */);
250     }
251 
252     /**
253      * Creates a indexOf(type) -> inset map for which the {@code insets} is just mapped to
254      * {@link Type#statusBars()} and {@link Type#navigationBars()}, depending on the
255      * location of the inset.
256      */
createCompatTypeMap(@ullable Rect insets)257     private static Insets[] createCompatTypeMap(@Nullable Rect insets) {
258         if (insets == null) {
259             return null;
260         }
261         Insets[] typeInsetsMap = new Insets[SIZE];
262         assignCompatInsets(typeInsetsMap, insets);
263         return typeInsetsMap;
264     }
265 
266     /**
267      * @hide
268      */
269     @VisibleForTesting
assignCompatInsets(Insets[] typeInsetsMap, Rect insets)270     public static void assignCompatInsets(Insets[] typeInsetsMap, Rect insets) {
271         typeInsetsMap[indexOf(STATUS_BARS)] = Insets.of(0, insets.top, 0, 0);
272         typeInsetsMap[indexOf(NAVIGATION_BARS)] =
273                 Insets.of(insets.left, 0, insets.right, insets.bottom);
274     }
275 
createCompatVisibilityMap(@ullable Insets[] typeInsetsMap)276     private static boolean[] createCompatVisibilityMap(@Nullable Insets[] typeInsetsMap) {
277         boolean[] typeVisibilityMap = new boolean[SIZE];
278         if (typeInsetsMap == null) {
279             return typeVisibilityMap;
280         }
281         for (int i = FIRST; i <= LAST; i = i << 1) {
282             int index = indexOf(i);
283             if (!Insets.NONE.equals(typeInsetsMap[index])) {
284                 typeVisibilityMap[index] = true;
285             }
286         }
287         return typeVisibilityMap;
288     }
289 
290     /**
291      * Used to provide a safe copy of the system window insets to pass through
292      * to the existing fitSystemWindows method and other similar internals.
293      * @hide
294      *
295      * @deprecated use {@link #getSystemWindowInsets()} instead.
296      */
297     @Deprecated
298     @NonNull
getSystemWindowInsetsAsRect()299     public Rect getSystemWindowInsetsAsRect() {
300         if (mTempRect == null) {
301             mTempRect = new Rect();
302         }
303         Insets insets = getSystemWindowInsets();
304         mTempRect.set(insets.left, insets.top, insets.right, insets.bottom);
305         return mTempRect;
306     }
307 
308     /**
309      * Returns the system window insets in pixels.
310      *
311      * <p>The system window inset represents the area of a full-screen window that is
312      * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
313      * </p>
314      *
315      * @return The system window insets
316      * @deprecated Use {@link #getInsets(int)} with {@link Type#systemBars()}
317      * instead.
318      */
319     @Deprecated
320     @NonNull
getSystemWindowInsets()321     public Insets getSystemWindowInsets() {
322         Insets result = mCompatIgnoreVisibility
323                 ? getInsetsIgnoringVisibility(mCompatInsetsTypes & ~ime())
324                 : getInsets(mCompatInsetsTypes);
325 
326         // We can't query max insets for IME, so we need to add it manually after.
327         if ((mCompatInsetsTypes & ime()) != 0 && mCompatIgnoreVisibility) {
328             result = Insets.max(result, getInsets(ime()));
329         }
330         return result;
331     }
332 
333     /**
334      * Returns the insets of a specific set of windows causing insets, denoted by the
335      * {@code typeMask} bit mask of {@link Type}s.
336      *
337      * @param typeMask Bit mask of {@link Type}s to query the insets for.
338      * @return The insets.
339      */
340     @NonNull
getInsets(@nsetsType int typeMask)341     public Insets getInsets(@InsetsType int typeMask) {
342         return getInsets(mTypeInsetsMap, typeMask);
343     }
344 
345     /**
346      * Returns the insets a specific set of windows can cause, denoted by the
347      * {@code typeMask} bit mask of {@link Type}s, regardless of whether that type is
348      * currently visible or not.
349      *
350      * <p>The insets represents the area of a a window that that <b>may</b> be partially
351      * or fully obscured by the system window identified by {@code type}. This value does not
352      * change based on the visibility state of those elements. For example, if the status bar is
353      * normally shown, but temporarily hidden, the inset returned here will still provide the inset
354      * associated with the status bar being shown.</p>
355      *
356      * @param typeMask Bit mask of {@link Type}s to query the insets for.
357      * @return The insets.
358      *
359      * @throws IllegalArgumentException If the caller tries to query {@link Type#ime()}. Insets are
360      *                                  not available if the IME isn't visible as the height of the
361      *                                  IME is dynamic depending on the {@link EditorInfo} of the
362      *                                  currently focused view, as well as the UI state of the IME.
363      */
364     @NonNull
getInsetsIgnoringVisibility(@nsetsType int typeMask)365     public Insets getInsetsIgnoringVisibility(@InsetsType int typeMask) {
366         if ((typeMask & IME) != 0) {
367             throw new IllegalArgumentException("Unable to query the maximum insets for IME");
368         }
369         return getInsets(mTypeMaxInsetsMap, typeMask);
370     }
371 
372     /**
373      * Returns whether a set of windows that may cause insets is currently visible on screen,
374      * regardless of whether it actually overlaps with this window.
375      *
376      * @param typeMask Bit mask of {@link Type}s to query visibility status.
377      * @return {@code true} if and only if all windows included in {@code typeMask} are currently
378      *         visible on screen.
379      */
isVisible(@nsetsType int typeMask)380     public boolean isVisible(@InsetsType int typeMask) {
381         for (int i = FIRST; i <= LAST; i = i << 1) {
382             if ((typeMask & i) == 0) {
383                 continue;
384             }
385             if (!mTypeVisibilityMap[indexOf(i)]) {
386                 return false;
387             }
388         }
389         return true;
390     }
391 
392     /**
393      * Returns the left system window inset in pixels.
394      *
395      * <p>The system window inset represents the area of a full-screen window that is
396      * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
397      * </p>
398      *
399      * @return The left system window inset
400      * @deprecated Use {@link #getInsets(int)} with {@link Type#systemBars()}
401      * instead.
402      */
403     @Deprecated
getSystemWindowInsetLeft()404     public int getSystemWindowInsetLeft() {
405         return getSystemWindowInsets().left;
406     }
407 
408     /**
409      * Returns the top system window inset in pixels.
410      *
411      * <p>The system window inset represents the area of a full-screen window that is
412      * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
413      * </p>
414      *
415      * @return The top system window inset
416      * @deprecated Use {@link #getInsets(int)} with {@link Type#systemBars()}
417      * instead.
418      */
419     @Deprecated
getSystemWindowInsetTop()420     public int getSystemWindowInsetTop() {
421         return getSystemWindowInsets().top;
422     }
423 
424     /**
425      * Returns the right system window inset in pixels.
426      *
427      * <p>The system window inset represents the area of a full-screen window that is
428      * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
429      * </p>
430      *
431      * @return The right system window inset
432      * @deprecated Use {@link #getInsets(int)} with {@link Type#systemBars()}
433      * instead.
434      */
435     @Deprecated
getSystemWindowInsetRight()436     public int getSystemWindowInsetRight() {
437         return getSystemWindowInsets().right;
438     }
439 
440     /**
441      * Returns the bottom system window inset in pixels.
442      *
443      * <p>The system window inset represents the area of a full-screen window that is
444      * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
445      * </p>
446      *
447      * @return The bottom system window inset
448      * @deprecated Use {@link #getInsets(int)} with {@link Type#systemBars()}
449      * instead.
450      */
451     @Deprecated
getSystemWindowInsetBottom()452     public int getSystemWindowInsetBottom() {
453         return getSystemWindowInsets().bottom;
454     }
455 
456     /**
457      * Returns true if this WindowInsets has nonzero system window insets.
458      *
459      * <p>The system window inset represents the area of a full-screen window that is
460      * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
461      * </p>
462      *
463      * @return true if any of the system window inset values are nonzero
464      * @deprecated Use {@link #getInsets(int)} with {@link Type#systemBars()}
465      * instead.
466      */
467     @Deprecated
hasSystemWindowInsets()468     public boolean hasSystemWindowInsets() {
469         return !getSystemWindowInsets().equals(Insets.NONE);
470     }
471 
472     /**
473      * Returns true if this WindowInsets has any nonzero insets.
474      *
475      * @return true if any inset values are nonzero
476      */
hasInsets()477     public boolean hasInsets() {
478         return !getInsets(mTypeInsetsMap, all()).equals(Insets.NONE)
479                 || !getInsets(mTypeMaxInsetsMap, all()).equals(Insets.NONE)
480                 || mDisplayCutout != null || mRoundedCorners != null;
481     }
482 
483     /**
484      * Returns the display cutout if there is one.
485      *
486      * <p>Note: the display cutout will already be {@link #consumeDisplayCutout consumed} during
487      * dispatch to {@link View#onApplyWindowInsets}, unless the window has requested a
488      * {@link WindowManager.LayoutParams#layoutInDisplayCutoutMode} other than
489      * {@link WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER never} or
490      * {@link WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT default}.
491      *
492      * @return the display cutout or null if there is none
493      * @see DisplayCutout
494      */
495     @Nullable
getDisplayCutout()496     public DisplayCutout getDisplayCutout() {
497         return mDisplayCutout;
498     }
499 
500     /**
501      * Returns the {@link RoundedCorner} of the given position if there is one.
502      *
503      * @param position the position of the rounded corner on the display. The value should be one of
504      *                 the following:
505      *                 {@link RoundedCorner#POSITION_TOP_LEFT},
506      *                 {@link RoundedCorner#POSITION_TOP_RIGHT},
507      *                 {@link RoundedCorner#POSITION_BOTTOM_RIGHT},
508      *                 {@link RoundedCorner#POSITION_BOTTOM_LEFT}.
509      * @return the rounded corner of the given position. Returns {@code null} if there is none or
510      *         the rounded corner area is not inside the application's bounds.
511      */
512     @Nullable
getRoundedCorner(@oundedCorner.Position int position)513     public RoundedCorner getRoundedCorner(@RoundedCorner.Position int position) {
514         return mRoundedCorners == null ? null : mRoundedCorners.getRoundedCorner(position);
515     }
516 
517     /**
518      * Returns the {@link Rect} of the maximum bounds of the system privacy indicator, for the
519      * current orientation, in relative coordinates, or null if the bounds have not been loaded yet.
520      * The privacy indicator shows over apps when an app uses the microphone or camera permissions,
521      * while an app is in immersive mode.
522      *
523      * @return A rectangle representing the maximum bounds of the indicator
524      */
getPrivacyIndicatorBounds()525     public @Nullable Rect getPrivacyIndicatorBounds() {
526         return mPrivacyIndicatorBounds == null ? null
527                 : mPrivacyIndicatorBounds.getStaticPrivacyIndicatorBounds();
528     }
529 
530     /**
531      * Returns a copy of this WindowInsets with the cutout fully consumed.
532      *
533      * @return A modified copy of this WindowInsets
534      * @deprecated Consuming of different parts individually of a {@link WindowInsets} instance is
535      * deprecated, since {@link WindowInsets} contains many different insets. Use {@link #CONSUMED}
536      * instead to stop dispatching insets.
537      */
538     @Deprecated
539     @NonNull
consumeDisplayCutout()540     public WindowInsets consumeDisplayCutout() {
541         return new WindowInsets(mSystemWindowInsetsConsumed ? null : mTypeInsetsMap,
542                 mStableInsetsConsumed ? null : mTypeMaxInsetsMap,
543                 mTypeVisibilityMap,
544                 mIsRound, mAlwaysConsumeSystemBars,
545                 null /* displayCutout */, mRoundedCorners, mPrivacyIndicatorBounds,
546                 mCompatInsetsTypes, mCompatIgnoreVisibility);
547     }
548 
549 
550     /**
551      * Check if these insets have been fully consumed.
552      *
553      * <p>Insets are considered "consumed" if the applicable <code>consume*</code> methods
554      * have been called such that all insets have been set to zero. This affects propagation of
555      * insets through the view hierarchy; insets that have not been fully consumed will continue
556      * to propagate down to child views.</p>
557      *
558      * <p>The result of this method is equivalent to the return value of
559      * {@link View#fitSystemWindows(android.graphics.Rect)}.</p>
560      *
561      * @return true if the insets have been fully consumed.
562      */
isConsumed()563     public boolean isConsumed() {
564         return mSystemWindowInsetsConsumed && mStableInsetsConsumed
565                 && mDisplayCutoutConsumed;
566     }
567 
568     /**
569      * Returns true if the associated window has a round shape.
570      *
571      * <p>A round window's left, top, right and bottom edges reach all the way to the
572      * associated edges of the window but the corners may not be visible. Views responding
573      * to round insets should take care to not lay out critical elements within the corners
574      * where they may not be accessible.</p>
575      *
576      * @return True if the window is round
577      */
isRound()578     public boolean isRound() {
579         return mIsRound;
580     }
581 
582     /**
583      * Returns a copy of this WindowInsets with the system window insets fully consumed.
584      *
585      * @return A modified copy of this WindowInsets
586      * @deprecated Consuming of different parts individually of a {@link WindowInsets} instance is
587      * deprecated, since {@link WindowInsets} contains many different insets. Use {@link #CONSUMED}
588      * instead to stop dispatching insets.
589      */
590     @Deprecated
591     @NonNull
consumeSystemWindowInsets()592     public WindowInsets consumeSystemWindowInsets() {
593         return new WindowInsets(null, null,
594                 mTypeVisibilityMap,
595                 mIsRound, mAlwaysConsumeSystemBars,
596                 displayCutoutCopyConstructorArgument(this),
597                 mRoundedCorners, mPrivacyIndicatorBounds, mCompatInsetsTypes,
598                 mCompatIgnoreVisibility);
599     }
600 
601     // TODO(b/119190588): replace @code with @link below
602     /**
603      * Returns a copy of this WindowInsets with selected system window insets replaced
604      * with new values.
605      *
606      * <p>Note: If the system window insets are already consumed, this method will return them
607      * unchanged on {@link android.os.Build.VERSION_CODES#Q Q} and later. Prior to
608      * {@link android.os.Build.VERSION_CODES#Q Q}, the new values were applied regardless of
609      * whether they were consumed, and this method returns invalid non-zero consumed insets.
610      *
611      * @param left New left inset in pixels
612      * @param top New top inset in pixels
613      * @param right New right inset in pixels
614      * @param bottom New bottom inset in pixels
615      * @return A modified copy of this WindowInsets
616      * @deprecated use {@code Builder#Builder(WindowInsets)} with
617      *             {@link Builder#setSystemWindowInsets(Insets)} instead.
618      */
619     @Deprecated
620     @NonNull
replaceSystemWindowInsets(int left, int top, int right, int bottom)621     public WindowInsets replaceSystemWindowInsets(int left, int top, int right, int bottom) {
622         // Compat edge case: what should this do if the insets have already been consumed?
623         // On platforms prior to Q, the behavior was to override the insets with non-zero values,
624         // but leave them consumed, which is invalid (consumed insets must be zero).
625         // The behavior is now keeping them consumed and discarding the new insets.
626         if (mSystemWindowInsetsConsumed) {
627             return this;
628         }
629         return new Builder(this).setSystemWindowInsets(Insets.of(left, top, right, bottom)).build();
630     }
631 
632     // TODO(b/119190588): replace @code with @link below
633     /**
634      * Returns a copy of this WindowInsets with selected system window insets replaced
635      * with new values.
636      *
637      * <p>Note: If the system window insets are already consumed, this method will return them
638      * unchanged on {@link android.os.Build.VERSION_CODES#Q Q} and later. Prior to
639      * {@link android.os.Build.VERSION_CODES#Q Q}, the new values were applied regardless of
640      * whether they were consumed, and this method returns invalid non-zero consumed insets.
641      *
642      * @param systemWindowInsets New system window insets. Each field is the inset in pixels
643      *                           for that edge
644      * @return A modified copy of this WindowInsets
645      * @deprecated use {@code Builder#Builder(WindowInsets)} with
646      *             {@link Builder#setSystemWindowInsets(Insets)} instead.
647      */
648     @Deprecated
649     @NonNull
replaceSystemWindowInsets(Rect systemWindowInsets)650     public WindowInsets replaceSystemWindowInsets(Rect systemWindowInsets) {
651         return replaceSystemWindowInsets(systemWindowInsets.left, systemWindowInsets.top,
652                 systemWindowInsets.right, systemWindowInsets.bottom);
653     }
654 
655     /**
656      * Returns the stable insets in pixels.
657      *
658      * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
659      * partially or fully obscured by the system UI elements.  This value does not change
660      * based on the visibility state of those elements; for example, if the status bar is
661      * normally shown, but temporarily hidden, the stable inset will still provide the inset
662      * associated with the status bar being shown.</p>
663      *
664      * @return The stable insets
665      * @deprecated Use {@link #getInsetsIgnoringVisibility(int)} with {@link Type#systemBars()}
666      * instead.
667      */
668     @Deprecated
669     @NonNull
getStableInsets()670     public Insets getStableInsets() {
671         return getInsets(mTypeMaxInsetsMap, mCompatInsetsTypes);
672     }
673 
674     /**
675      * Returns the top stable inset in pixels.
676      *
677      * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
678      * partially or fully obscured by the system UI elements.  This value does not change
679      * based on the visibility state of those elements; for example, if the status bar is
680      * normally shown, but temporarily hidden, the stable inset will still provide the inset
681      * associated with the status bar being shown.</p>
682      *
683      * @return The top stable inset
684      * @deprecated Use {@link #getInsetsIgnoringVisibility(int)} with {@link Type#systemBars()}
685      * instead.
686      */
687     @Deprecated
getStableInsetTop()688     public int getStableInsetTop() {
689         return getStableInsets().top;
690     }
691 
692     /**
693      * Returns the left stable inset in pixels.
694      *
695      * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
696      * partially or fully obscured by the system UI elements.  This value does not change
697      * based on the visibility state of those elements; for example, if the status bar is
698      * normally shown, but temporarily hidden, the stable inset will still provide the inset
699      * associated with the status bar being shown.</p>
700      *
701      * @return The left stable inset
702      * @deprecated Use {@link #getInsetsIgnoringVisibility(int)} with {@link Type#systemBars()}
703      * instead.
704      */
705     @Deprecated
getStableInsetLeft()706     public int getStableInsetLeft() {
707         return getStableInsets().left;
708     }
709 
710     /**
711      * Returns the right stable inset in pixels.
712      *
713      * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
714      * partially or fully obscured by the system UI elements.  This value does not change
715      * based on the visibility state of those elements; for example, if the status bar is
716      * normally shown, but temporarily hidden, the stable inset will still provide the inset
717      * associated with the status bar being shown.</p>
718      *
719      * @return The right stable inset
720      * @deprecated Use {@link #getInsetsIgnoringVisibility(int)} with {@link Type#systemBars()}
721      * instead.
722      */
723     @Deprecated
getStableInsetRight()724     public int getStableInsetRight() {
725         return getStableInsets().right;
726     }
727 
728     /**
729      * Returns the bottom stable inset in pixels.
730      *
731      * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
732      * partially or fully obscured by the system UI elements.  This value does not change
733      * based on the visibility state of those elements; for example, if the status bar is
734      * normally shown, but temporarily hidden, the stable inset will still provide the inset
735      * associated with the status bar being shown.</p>
736      *
737      * @return The bottom stable inset
738      * @deprecated Use {@link #getInsetsIgnoringVisibility(int)} with {@link Type#systemBars()}
739      * instead.
740      */
741     @Deprecated
getStableInsetBottom()742     public int getStableInsetBottom() {
743         return getStableInsets().bottom;
744     }
745 
746     /**
747      * Returns true if this WindowInsets has nonzero stable insets.
748      *
749      * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
750      * partially or fully obscured by the system UI elements.  This value does not change
751      * based on the visibility state of those elements; for example, if the status bar is
752      * normally shown, but temporarily hidden, the stable inset will still provide the inset
753      * associated with the status bar being shown.</p>
754      *
755      * @return true if any of the stable inset values are nonzero
756      * @deprecated Use {@link #getInsetsIgnoringVisibility(int)} with {@link Type#systemBars()}
757      * instead.
758      */
759     @Deprecated
hasStableInsets()760     public boolean hasStableInsets() {
761         return !getStableInsets().equals(Insets.NONE);
762     }
763 
764     /**
765      * Returns the system gesture insets.
766      *
767      * <p>The system gesture insets represent the area of a window where system gestures have
768      * priority and may consume some or all touch input, e.g. due to the a system bar
769      * occupying it, or it being reserved for touch-only gestures.
770      *
771      * <p>An app can declare priority over system gestures with
772      * {@link View#setSystemGestureExclusionRects} outside of the
773      * {@link #getMandatorySystemGestureInsets() mandatory system gesture insets}.
774      *
775      * <p>Note: the system will put a limit of <code>200dp</code> on the vertical extent of the
776      * exclusions it takes into account. The limit does not apply while the navigation
777      * bar is {@link View#SYSTEM_UI_FLAG_IMMERSIVE_STICKY stickily} hidden, nor to the
778      * {@link android.inputmethodservice.InputMethodService input method} and
779      * {@link Intent#CATEGORY_HOME home activity}.
780      * </p>
781      *
782      *
783      * <p>Simple taps are guaranteed to reach the window even within the system gesture insets,
784      * as long as they are outside the {@link #getTappableElementInsets() system window insets}.
785      *
786      * <p>When {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} is requested, an inset will be returned
787      * even when the system gestures are inactive due to
788      * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} or
789      * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}.
790      *
791      * <p>This inset is consumed together with the {@link #getSystemWindowInsets()
792      * system window insets} by {@link #consumeSystemWindowInsets()}.
793      *
794      * @see #getMandatorySystemGestureInsets
795      * @deprecated Use {@link #getInsets(int)} with {@link Type#systemGestures()} instead.
796      */
797     @Deprecated
798     @NonNull
getSystemGestureInsets()799     public Insets getSystemGestureInsets() {
800         return getInsets(mTypeInsetsMap, SYSTEM_GESTURES);
801     }
802 
803     /**
804      * Returns the mandatory system gesture insets.
805      *
806      * <p>The mandatory system gesture insets represent the area of a window where mandatory system
807      * gestures have priority and may consume some or all touch input, e.g. due to the a system bar
808      * occupying it, or it being reserved for touch-only gestures.
809      *
810      * <p>In contrast to {@link #getSystemGestureInsets regular system gestures}, <b>mandatory</b>
811      * system gestures cannot be overriden by {@link View#setSystemGestureExclusionRects}.
812      *
813      * <p>Simple taps are guaranteed to reach the window even within the system gesture insets,
814      * as long as they are outside the {@link #getTappableElementInsets() system window insets}.
815      *
816      * <p>When {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} is requested, an inset will be returned
817      * even when the system gestures are inactive due to
818      * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} or
819      * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}.
820      *
821      * <p>This inset is consumed together with the {@link #getSystemWindowInsets()
822      * system window insets} by {@link #consumeSystemWindowInsets()}.
823      *
824      * @see #getSystemGestureInsets
825      * @deprecated Use {@link #getInsets(int)} with {@link Type#mandatorySystemGestures()} instead.
826      */
827     @Deprecated
828     @NonNull
getMandatorySystemGestureInsets()829     public Insets getMandatorySystemGestureInsets() {
830         return getInsets(mTypeInsetsMap, MANDATORY_SYSTEM_GESTURES);
831     }
832 
833     /**
834      * Returns the tappable element insets.
835      *
836      * <p>The tappable element insets represent how much tappable elements <b>must at least</b> be
837      * inset to remain both tappable and visually unobstructed by persistent system windows.
838      *
839      * <p>This may be smaller than {@link #getSystemWindowInsets()} if the system window is
840      * largely transparent and lets through simple taps (but not necessarily more complex gestures).
841      *
842      * <p>Note that generally, tappable elements <strong>should</strong> be aligned with the
843      * {@link #getSystemWindowInsets() system window insets} instead to avoid overlapping with the
844      * system bars.
845      *
846      * <p>When {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} is requested, an inset will be returned
847      * even when the area covered by the inset would be tappable due to
848      * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} or
849      * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}.
850      *
851      * <p>This inset is consumed together with the {@link #getSystemWindowInsets()
852      * system window insets} by {@link #consumeSystemWindowInsets()}.
853      *
854      * @deprecated Use {@link #getInsets(int)} with {@link Type#tappableElement()} instead.
855      */
856     @Deprecated
857     @NonNull
getTappableElementInsets()858     public Insets getTappableElementInsets() {
859         return getInsets(mTypeInsetsMap, TAPPABLE_ELEMENT);
860     }
861 
862     /**
863      * Returns a copy of this WindowInsets with the stable insets fully consumed.
864      *
865      * @return A modified copy of this WindowInsets
866      * @deprecated Consuming of different parts individually of a {@link WindowInsets} instance is
867      * deprecated, since {@link WindowInsets} contains many different insets. Use {@link #CONSUMED}
868      * instead to stop dispatching insets. On {@link android.os.Build.VERSION_CODES#R R}, this
869      * method has no effect.
870      */
871     @Deprecated
872     @NonNull
consumeStableInsets()873     public WindowInsets consumeStableInsets() {
874         return this;
875     }
876 
877     /**
878      * @hide
879      */
shouldAlwaysConsumeSystemBars()880     public boolean shouldAlwaysConsumeSystemBars() {
881         return mAlwaysConsumeSystemBars;
882     }
883 
884     @Override
toString()885     public String toString() {
886         StringBuilder result = new StringBuilder("WindowInsets{\n    ");
887         for (int i = 0; i < SIZE; i++) {
888             Insets insets = mTypeInsetsMap[i];
889             Insets maxInsets = mTypeMaxInsetsMap[i];
890             boolean visible = mTypeVisibilityMap[i];
891             if (!Insets.NONE.equals(insets) || !Insets.NONE.equals(maxInsets) || visible) {
892                 result.append(Type.toString(1 << i)).append("=").append(insets)
893                         .append(" max=").append(maxInsets)
894                         .append(" vis=").append(visible)
895                         .append("\n    ");
896             }
897         }
898 
899         result.append(mDisplayCutout != null ? "cutout=" + mDisplayCutout : "");
900         result.append("\n    ");
901         result.append(mRoundedCorners != null ? "roundedCorners=" + mRoundedCorners : "");
902         result.append("\n    ");
903         result.append(mPrivacyIndicatorBounds != null ? "privacyIndicatorBounds="
904                 + mPrivacyIndicatorBounds : "");
905         result.append("\n    ");
906         result.append(isRound() ? "round" : "");
907         result.append("}");
908         return result.toString();
909     }
910 
911     /**
912      * Returns a copy of this instance inset in the given directions.
913      *
914      * @see #inset(int, int, int, int)
915      * @deprecated use {@link #inset(Insets)}
916      * @hide
917      */
918     @Deprecated
919     @NonNull
inset(Rect r)920     public WindowInsets inset(Rect r) {
921         return inset(r.left, r.top, r.right, r.bottom);
922     }
923 
924     /**
925      * Returns a copy of this instance inset in the given directions.
926      *
927      * This is intended for dispatching insets to areas of the window that are smaller than the
928      * current area.
929      *
930      * <p>Example:
931      * <pre>
932      * childView.dispatchApplyWindowInsets(insets.inset(childMargins));
933      * </pre>
934      *
935      * @param insets the amount of insets to remove from all sides.
936      *
937      * @see #inset(int, int, int, int)
938      */
939     @NonNull
inset(@onNull Insets insets)940     public WindowInsets inset(@NonNull Insets insets) {
941         Objects.requireNonNull(insets);
942         return inset(insets.left, insets.top, insets.right, insets.bottom);
943     }
944 
945     /**
946      * Returns a copy of this instance inset in the given directions.
947      *
948      * This is intended for dispatching insets to areas of the window that are smaller than the
949      * current area.
950      *
951      * <p>Example:
952      * <pre>
953      * childView.dispatchApplyWindowInsets(insets.inset(
954      *         childMarginLeft, childMarginTop, childMarginBottom, childMarginRight));
955      * </pre>
956      *
957      * @param left the amount of insets to remove from the left. Must be non-negative.
958      * @param top the amount of insets to remove from the top. Must be non-negative.
959      * @param right the amount of insets to remove from the right. Must be non-negative.
960      * @param bottom the amount of insets to remove from the bottom. Must be non-negative.
961      *
962      * @return the inset insets
963      *
964      * @see #inset(Insets)
965      */
966     @NonNull
inset(@ntRangefrom = 0) int left, @IntRange(from = 0) int top, @IntRange(from = 0) int right, @IntRange(from = 0) int bottom)967     public WindowInsets inset(@IntRange(from = 0) int left, @IntRange(from = 0) int top,
968             @IntRange(from = 0) int right, @IntRange(from = 0) int bottom) {
969         Preconditions.checkArgumentNonnegative(left);
970         Preconditions.checkArgumentNonnegative(top);
971         Preconditions.checkArgumentNonnegative(right);
972         Preconditions.checkArgumentNonnegative(bottom);
973 
974         return insetUnchecked(left, top, right, bottom);
975     }
976 
977     /**
978      * @see #inset(int, int, int, int)
979      * @hide
980      */
981     @NonNull
insetUnchecked(int left, int top, int right, int bottom)982     public WindowInsets insetUnchecked(int left, int top, int right, int bottom) {
983         return new WindowInsets(
984                 mSystemWindowInsetsConsumed
985                         ? null
986                         : insetInsets(mTypeInsetsMap, left, top, right, bottom),
987                 mStableInsetsConsumed
988                         ? null
989                         : insetInsets(mTypeMaxInsetsMap, left, top, right, bottom),
990                 mTypeVisibilityMap,
991                 mIsRound, mAlwaysConsumeSystemBars,
992                 mDisplayCutoutConsumed
993                         ? null
994                         : mDisplayCutout == null
995                                 ? DisplayCutout.NO_CUTOUT
996                                 : mDisplayCutout.inset(left, top, right, bottom),
997                 mRoundedCorners == null
998                         ? RoundedCorners.NO_ROUNDED_CORNERS
999                         : mRoundedCorners.inset(left, top, right, bottom),
1000                 mPrivacyIndicatorBounds == null
1001                         ? null
1002                         : mPrivacyIndicatorBounds.inset(left, top, right, bottom),
1003                 mCompatInsetsTypes, mCompatIgnoreVisibility);
1004     }
1005 
1006     @Override
equals(@ullable Object o)1007     public boolean equals(@Nullable Object o) {
1008         if (this == o) return true;
1009         if (o == null || !(o instanceof WindowInsets)) return false;
1010         WindowInsets that = (WindowInsets) o;
1011 
1012         return mIsRound == that.mIsRound
1013                 && mAlwaysConsumeSystemBars == that.mAlwaysConsumeSystemBars
1014                 && mSystemWindowInsetsConsumed == that.mSystemWindowInsetsConsumed
1015                 && mStableInsetsConsumed == that.mStableInsetsConsumed
1016                 && mDisplayCutoutConsumed == that.mDisplayCutoutConsumed
1017                 && Arrays.equals(mTypeInsetsMap, that.mTypeInsetsMap)
1018                 && Arrays.equals(mTypeMaxInsetsMap, that.mTypeMaxInsetsMap)
1019                 && Arrays.equals(mTypeVisibilityMap, that.mTypeVisibilityMap)
1020                 && Objects.equals(mDisplayCutout, that.mDisplayCutout)
1021                 && Objects.equals(mRoundedCorners, that.mRoundedCorners)
1022                 && Objects.equals(mPrivacyIndicatorBounds, that.mPrivacyIndicatorBounds);
1023     }
1024 
1025     @Override
hashCode()1026     public int hashCode() {
1027         return Objects.hash(Arrays.hashCode(mTypeInsetsMap), Arrays.hashCode(mTypeMaxInsetsMap),
1028                 Arrays.hashCode(mTypeVisibilityMap), mIsRound, mDisplayCutout, mRoundedCorners,
1029                 mAlwaysConsumeSystemBars, mSystemWindowInsetsConsumed, mStableInsetsConsumed,
1030                 mDisplayCutoutConsumed, mPrivacyIndicatorBounds);
1031     }
1032 
1033 
1034     /**
1035      * Insets every inset in {@code typeInsetsMap} by the specified left, top, right, bottom.
1036      *
1037      * @return {@code typeInsetsMap} if no inset was modified; a copy of the map with the modified
1038      *          insets otherwise.
1039      */
insetInsets( Insets[] typeInsetsMap, int left, int top, int right, int bottom)1040     private static Insets[] insetInsets(
1041             Insets[] typeInsetsMap, int left, int top, int right, int bottom) {
1042         boolean cloned = false;
1043         for (int i = 0; i < SIZE; i++) {
1044             Insets insets = typeInsetsMap[i];
1045             if (insets == null) {
1046                 continue;
1047             }
1048             Insets insetInsets = insetInsets(insets, left, top, right, bottom);
1049             if (insetInsets != insets) {
1050                 if (!cloned) {
1051                     typeInsetsMap = typeInsetsMap.clone();
1052                     cloned = true;
1053                 }
1054                 typeInsetsMap[i] = insetInsets;
1055             }
1056         }
1057         return typeInsetsMap;
1058     }
1059 
insetInsets(Insets insets, int left, int top, int right, int bottom)1060     static Insets insetInsets(Insets insets, int left, int top, int right, int bottom) {
1061         int newLeft = Math.max(0, insets.left - left);
1062         int newTop = Math.max(0, insets.top - top);
1063         int newRight = Math.max(0, insets.right - right);
1064         int newBottom = Math.max(0, insets.bottom - bottom);
1065         if (newLeft == left && newTop == top && newRight == right && newBottom == bottom) {
1066             return insets;
1067         }
1068         return Insets.of(newLeft, newTop, newRight, newBottom);
1069     }
1070 
1071     /**
1072      * @return whether system window insets have been consumed.
1073      */
isSystemWindowInsetsConsumed()1074     boolean isSystemWindowInsetsConsumed() {
1075         return mSystemWindowInsetsConsumed;
1076     }
1077 
1078     /**
1079      * Builder for WindowInsets.
1080      */
1081     public static final class Builder {
1082 
1083         private final Insets[] mTypeInsetsMap;
1084         private final Insets[] mTypeMaxInsetsMap;
1085         private final boolean[] mTypeVisibilityMap;
1086         private boolean mSystemInsetsConsumed = true;
1087         private boolean mStableInsetsConsumed = true;
1088 
1089         private DisplayCutout mDisplayCutout;
1090         private RoundedCorners mRoundedCorners = RoundedCorners.NO_ROUNDED_CORNERS;
1091 
1092         private boolean mIsRound;
1093         private boolean mAlwaysConsumeSystemBars;
1094 
1095         private PrivacyIndicatorBounds mPrivacyIndicatorBounds = new PrivacyIndicatorBounds();
1096 
1097         /**
1098          * Creates a builder where all insets are initially consumed.
1099          */
Builder()1100         public Builder() {
1101             mTypeInsetsMap = new Insets[SIZE];
1102             mTypeMaxInsetsMap = new Insets[SIZE];
1103             mTypeVisibilityMap = new boolean[SIZE];
1104         }
1105 
1106         /**
1107          * Creates a builder where all insets are initialized from {@link WindowInsets}.
1108          *
1109          * @param insets the instance to initialize from.
1110          */
Builder(@onNull WindowInsets insets)1111         public Builder(@NonNull WindowInsets insets) {
1112             mTypeInsetsMap = insets.mTypeInsetsMap.clone();
1113             mTypeMaxInsetsMap = insets.mTypeMaxInsetsMap.clone();
1114             mTypeVisibilityMap = insets.mTypeVisibilityMap.clone();
1115             mSystemInsetsConsumed = insets.mSystemWindowInsetsConsumed;
1116             mStableInsetsConsumed = insets.mStableInsetsConsumed;
1117             mDisplayCutout = displayCutoutCopyConstructorArgument(insets);
1118             mRoundedCorners = insets.mRoundedCorners;
1119             mIsRound = insets.mIsRound;
1120             mAlwaysConsumeSystemBars = insets.mAlwaysConsumeSystemBars;
1121             mPrivacyIndicatorBounds = insets.mPrivacyIndicatorBounds;
1122         }
1123 
1124         /**
1125          * Sets system window insets in pixels.
1126          *
1127          * <p>The system window inset represents the area of a full-screen window that is
1128          * partially or fully obscured by the status bar, navigation bar, IME or other system
1129          * windows.</p>
1130          *
1131          * @see #getSystemWindowInsets()
1132          * @return itself
1133          * @deprecated Use {@link #setInsets(int, Insets)} with {@link Type#systemBars()}.
1134          */
1135         @Deprecated
1136         @NonNull
setSystemWindowInsets(@onNull Insets systemWindowInsets)1137         public Builder setSystemWindowInsets(@NonNull Insets systemWindowInsets) {
1138             Preconditions.checkNotNull(systemWindowInsets);
1139             assignCompatInsets(mTypeInsetsMap, systemWindowInsets.toRect());
1140             mSystemInsetsConsumed = false;
1141             return this;
1142         }
1143 
1144         /**
1145          * Sets system gesture insets in pixels.
1146          *
1147          * <p>The system gesture insets represent the area of a window where system gestures have
1148          * priority and may consume some or all touch input, e.g. due to the a system bar
1149          * occupying it, or it being reserved for touch-only gestures.
1150          *
1151          * @see #getSystemGestureInsets()
1152          * @return itself
1153          * @deprecated Use {@link #setInsets(int, Insets)} with {@link Type#systemGestures()}.
1154          */
1155         @Deprecated
1156         @NonNull
setSystemGestureInsets(@onNull Insets insets)1157         public Builder setSystemGestureInsets(@NonNull Insets insets) {
1158             WindowInsets.setInsets(mTypeInsetsMap, SYSTEM_GESTURES, insets);
1159             return this;
1160         }
1161 
1162         /**
1163          * Sets mandatory system gesture insets in pixels.
1164          *
1165          * <p>The mandatory system gesture insets represent the area of a window where mandatory
1166          * system gestures have priority and may consume some or all touch input, e.g. due to the a
1167          * system bar occupying it, or it being reserved for touch-only gestures.
1168          *
1169          * <p>In contrast to {@link #setSystemGestureInsets regular system gestures},
1170          * <b>mandatory</b> system gestures cannot be overriden by
1171          * {@link View#setSystemGestureExclusionRects}.
1172          *
1173          * @see #getMandatorySystemGestureInsets()
1174          * @return itself
1175          * @deprecated Use {@link #setInsets(int, Insets)} with
1176          *             {@link Type#mandatorySystemGestures()}.
1177          */
1178         @Deprecated
1179         @NonNull
setMandatorySystemGestureInsets(@onNull Insets insets)1180         public Builder setMandatorySystemGestureInsets(@NonNull Insets insets) {
1181             WindowInsets.setInsets(mTypeInsetsMap, MANDATORY_SYSTEM_GESTURES, insets);
1182             return this;
1183         }
1184 
1185         /**
1186          * Sets tappable element insets in pixels.
1187          *
1188          * <p>The tappable element insets represent how much tappable elements <b>must at least</b>
1189          * be inset to remain both tappable and visually unobstructed by persistent system windows.
1190          *
1191          * @see #getTappableElementInsets()
1192          * @return itself
1193          * @deprecated Use {@link #setInsets(int, Insets)} with {@link Type#tappableElement()}.
1194          */
1195         @Deprecated
1196         @NonNull
setTappableElementInsets(@onNull Insets insets)1197         public Builder setTappableElementInsets(@NonNull Insets insets) {
1198             WindowInsets.setInsets(mTypeInsetsMap, TAPPABLE_ELEMENT, insets);
1199             return this;
1200         }
1201 
1202         /**
1203          * Sets the insets of a specific window type in pixels.
1204          *
1205          * <p>The insets represents the area of a a window that is partially or fully obscured by
1206          * the system windows identified by {@code typeMask}.
1207          * </p>
1208          *
1209          * @see #getInsets(int)
1210          *
1211          * @param typeMask The bitmask of {@link Type} to set the insets for.
1212          * @param insets The insets to set.
1213          *
1214          * @return itself
1215          */
1216         @NonNull
setInsets(@nsetsType int typeMask, @NonNull Insets insets)1217         public Builder setInsets(@InsetsType int typeMask, @NonNull Insets insets) {
1218             Preconditions.checkNotNull(insets);
1219             WindowInsets.setInsets(mTypeInsetsMap, typeMask, insets);
1220             mSystemInsetsConsumed = false;
1221             return this;
1222         }
1223 
1224         /**
1225          * Sets the insets a specific window type in pixels, while ignoring its visibility state.
1226          *
1227          * <p>The insets represents the area of a a window that that <b>may</b> be partially
1228          * or fully obscured by the system window identified by {@code type}. This value does not
1229          * change based on the visibility state of those elements. For example, if the status bar is
1230          * normally shown, but temporarily hidden, the inset returned here will still provide the
1231          * inset associated with the status bar being shown.</p>
1232          *
1233          * @see #getInsetsIgnoringVisibility(int)
1234          *
1235          * @param typeMask The bitmask of {@link Type} to set the insets for.
1236          * @param insets The insets to set.
1237          *
1238          * @return itself
1239          *
1240          * @throws IllegalArgumentException If {@code typeMask} contains {@link Type#ime()}. Maximum
1241          *                                  insets are not available for this type as the height of
1242          *                                  the IME is dynamic depending on the {@link EditorInfo}
1243          *                                  of the currently focused view, as well as the UI
1244          *                                  state of the IME.
1245          */
1246         @NonNull
setInsetsIgnoringVisibility(@nsetsType int typeMask, @NonNull Insets insets)1247         public Builder setInsetsIgnoringVisibility(@InsetsType int typeMask, @NonNull Insets insets)
1248                 throws IllegalArgumentException{
1249             if (typeMask == IME) {
1250                 throw new IllegalArgumentException("Maximum inset not available for IME");
1251             }
1252             Preconditions.checkNotNull(insets);
1253             WindowInsets.setInsets(mTypeMaxInsetsMap, typeMask, insets);
1254             mStableInsetsConsumed = false;
1255             return this;
1256         }
1257 
1258         /**
1259          * Sets whether windows that can cause insets are currently visible on screen.
1260          *
1261          *
1262          * @see #isVisible(int)
1263          *
1264          * @param typeMask The bitmask of {@link Type} to set the visibility for.
1265          * @param visible Whether to mark the windows as visible or not.
1266          *
1267          * @return itself
1268          */
1269         @NonNull
setVisible(@nsetsType int typeMask, boolean visible)1270         public Builder setVisible(@InsetsType int typeMask, boolean visible) {
1271             for (int i = FIRST; i <= LAST; i = i << 1) {
1272                 if ((typeMask & i) == 0) {
1273                     continue;
1274                 }
1275                 mTypeVisibilityMap[indexOf(i)] = visible;
1276             }
1277             return this;
1278         }
1279 
1280         /**
1281          * Sets the stable insets in pixels.
1282          *
1283          * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
1284          * partially or fully obscured by the system UI elements.  This value does not change
1285          * based on the visibility state of those elements; for example, if the status bar is
1286          * normally shown, but temporarily hidden, the stable inset will still provide the inset
1287          * associated with the status bar being shown.</p>
1288          *
1289          * @see #getStableInsets()
1290          * @return itself
1291          * @deprecated Use {@link #setInsetsIgnoringVisibility(int, Insets)} with
1292          *             {@link Type#systemBars()}.
1293          */
1294         @Deprecated
1295         @NonNull
setStableInsets(@onNull Insets stableInsets)1296         public Builder setStableInsets(@NonNull Insets stableInsets) {
1297             Preconditions.checkNotNull(stableInsets);
1298             assignCompatInsets(mTypeMaxInsetsMap, stableInsets.toRect());
1299             mStableInsetsConsumed = false;
1300             return this;
1301         }
1302 
1303         /**
1304          * Sets the display cutout.
1305          *
1306          * @see #getDisplayCutout()
1307          * @param displayCutout the display cutout or null if there is none
1308          * @return itself
1309          */
1310         @NonNull
setDisplayCutout(@ullable DisplayCutout displayCutout)1311         public Builder setDisplayCutout(@Nullable DisplayCutout displayCutout) {
1312             mDisplayCutout = displayCutout != null ? displayCutout : DisplayCutout.NO_CUTOUT;
1313             if (!mDisplayCutout.isEmpty()) {
1314                 final Insets safeInsets = Insets.of(mDisplayCutout.getSafeInsets());
1315                 final int index = indexOf(DISPLAY_CUTOUT);
1316                 mTypeInsetsMap[index] = safeInsets;
1317                 mTypeMaxInsetsMap[index] = safeInsets;
1318                 mTypeVisibilityMap[index] = true;
1319             }
1320             return this;
1321         }
1322 
1323         /** @hide */
1324         @NonNull
setRoundedCorners(RoundedCorners roundedCorners)1325         public Builder setRoundedCorners(RoundedCorners roundedCorners) {
1326             mRoundedCorners = roundedCorners != null
1327                     ? roundedCorners : RoundedCorners.NO_ROUNDED_CORNERS;
1328             return this;
1329         }
1330 
1331         /**
1332          * Sets the rounded corner of given position.
1333          *
1334          * @see #getRoundedCorner(int)
1335          * @param position the position of this rounded corner
1336          * @param roundedCorner the rounded corner or null if there is none
1337          * @return itself
1338          */
1339         @NonNull
setRoundedCorner(@oundedCorner.Position int position, @Nullable RoundedCorner roundedCorner)1340         public Builder setRoundedCorner(@RoundedCorner.Position int position,
1341                 @Nullable RoundedCorner roundedCorner) {
1342             mRoundedCorners.setRoundedCorner(position, roundedCorner);
1343             return this;
1344         }
1345 
1346         /** @hide */
1347         @NonNull
setPrivacyIndicatorBounds(@ullable PrivacyIndicatorBounds bounds)1348         public Builder setPrivacyIndicatorBounds(@Nullable PrivacyIndicatorBounds bounds) {
1349             mPrivacyIndicatorBounds = bounds;
1350             return this;
1351         }
1352 
1353         /**
1354          * Sets the bounds of the system privacy indicator.
1355          *
1356          * @param bounds The bounds of the system privacy indicator
1357          */
1358         @NonNull
setPrivacyIndicatorBounds(@ullable Rect bounds)1359         public Builder setPrivacyIndicatorBounds(@Nullable Rect bounds) {
1360             //TODO 188788786: refactor the indicator bounds
1361             Rect[] boundsArr = { bounds, bounds, bounds, bounds };
1362             mPrivacyIndicatorBounds = new PrivacyIndicatorBounds(boundsArr, ROTATION_0);
1363             return this;
1364         }
1365 
1366         /** @hide */
1367         @NonNull
setRound(boolean round)1368         public Builder setRound(boolean round) {
1369             mIsRound = round;
1370             return this;
1371         }
1372 
1373         /** @hide */
1374         @NonNull
setAlwaysConsumeSystemBars(boolean alwaysConsumeSystemBars)1375         public Builder setAlwaysConsumeSystemBars(boolean alwaysConsumeSystemBars) {
1376             mAlwaysConsumeSystemBars = alwaysConsumeSystemBars;
1377             return this;
1378         }
1379 
1380         /**
1381          * Builds a {@link WindowInsets} instance.
1382          *
1383          * @return the {@link WindowInsets} instance.
1384          */
1385         @NonNull
build()1386         public WindowInsets build() {
1387             return new WindowInsets(mSystemInsetsConsumed ? null : mTypeInsetsMap,
1388                     mStableInsetsConsumed ? null : mTypeMaxInsetsMap, mTypeVisibilityMap,
1389                     mIsRound, mAlwaysConsumeSystemBars, mDisplayCutout, mRoundedCorners,
1390                     mPrivacyIndicatorBounds, systemBars(), false /* compatIgnoreVisibility */);
1391         }
1392     }
1393 
1394     /**
1395      * Class that defines different types of sources causing window insets.
1396      */
1397     public static final class Type {
1398 
1399         static final int FIRST = 1 << 0;
1400         static final int STATUS_BARS = FIRST;
1401         static final int NAVIGATION_BARS = 1 << 1;
1402         static final int CAPTION_BAR = 1 << 2;
1403 
1404         static final int IME = 1 << 3;
1405 
1406         static final int SYSTEM_GESTURES = 1 << 4;
1407         static final int MANDATORY_SYSTEM_GESTURES = 1 << 5;
1408         static final int TAPPABLE_ELEMENT = 1 << 6;
1409 
1410         static final int DISPLAY_CUTOUT = 1 << 7;
1411 
1412         static final int LAST = 1 << 8;
1413         static final int SIZE = 9;
1414         static final int WINDOW_DECOR = LAST;
1415 
indexOf(@nsetsType int type)1416         static int indexOf(@InsetsType int type) {
1417             switch (type) {
1418                 case STATUS_BARS:
1419                     return 0;
1420                 case NAVIGATION_BARS:
1421                     return 1;
1422                 case CAPTION_BAR:
1423                     return 2;
1424                 case IME:
1425                     return 3;
1426                 case SYSTEM_GESTURES:
1427                     return 4;
1428                 case MANDATORY_SYSTEM_GESTURES:
1429                     return 5;
1430                 case TAPPABLE_ELEMENT:
1431                     return 6;
1432                 case DISPLAY_CUTOUT:
1433                     return 7;
1434                 case WINDOW_DECOR:
1435                     return 8;
1436                 default:
1437                     throw new IllegalArgumentException("type needs to be >= FIRST and <= LAST,"
1438                             + " type=" + type);
1439             }
1440         }
1441 
toString(@nsetsType int types)1442         static String toString(@InsetsType int types) {
1443             StringBuilder result = new StringBuilder();
1444             if ((types & STATUS_BARS) != 0) {
1445                 result.append("statusBars |");
1446             }
1447             if ((types & NAVIGATION_BARS) != 0) {
1448                 result.append("navigationBars |");
1449             }
1450             if ((types & CAPTION_BAR) != 0) {
1451                 result.append("captionBar |");
1452             }
1453             if ((types & IME) != 0) {
1454                 result.append("ime |");
1455             }
1456             if ((types & SYSTEM_GESTURES) != 0) {
1457                 result.append("systemGestures |");
1458             }
1459             if ((types & MANDATORY_SYSTEM_GESTURES) != 0) {
1460                 result.append("mandatorySystemGestures |");
1461             }
1462             if ((types & TAPPABLE_ELEMENT) != 0) {
1463                 result.append("tappableElement |");
1464             }
1465             if ((types & DISPLAY_CUTOUT) != 0) {
1466                 result.append("displayCutout |");
1467             }
1468             if ((types & WINDOW_DECOR) != 0) {
1469                 result.append("windowDecor |");
1470             }
1471             if (result.length() > 0) {
1472                 result.delete(result.length() - 2, result.length());
1473             }
1474             return result.toString();
1475         }
1476 
Type()1477         private Type() {
1478         }
1479 
1480         /** @hide */
1481         @Retention(RetentionPolicy.SOURCE)
1482         @IntDef(flag = true, value = {STATUS_BARS, NAVIGATION_BARS, CAPTION_BAR, IME, WINDOW_DECOR,
1483                 SYSTEM_GESTURES, MANDATORY_SYSTEM_GESTURES, TAPPABLE_ELEMENT, DISPLAY_CUTOUT})
1484         public @interface InsetsType {
1485         }
1486 
1487         /**
1488          * @return An insets type representing any system bars for displaying status.
1489          */
statusBars()1490         public static @InsetsType int statusBars() {
1491             return STATUS_BARS;
1492         }
1493 
1494         /**
1495          * @return An insets type representing any system bars for navigation.
1496          */
navigationBars()1497         public static @InsetsType int navigationBars() {
1498             return NAVIGATION_BARS;
1499         }
1500 
1501         /**
1502          * @return An insets type representing the window of a caption bar.
1503          */
captionBar()1504         public static @InsetsType int captionBar() {
1505             return CAPTION_BAR;
1506         }
1507 
1508         /**
1509          * @return An insets type representing the window of an {@link InputMethod}.
1510          */
ime()1511         public static @InsetsType int ime() {
1512             return IME;
1513         }
1514 
1515         /**
1516          * Returns an insets type representing the system gesture insets.
1517          *
1518          * <p>The system gesture insets represent the area of a window where system gestures have
1519          * priority and may consume some or all touch input, e.g. due to the a system bar
1520          * occupying it, or it being reserved for touch-only gestures.
1521          *
1522          * <p>Simple taps are guaranteed to reach the window even within the system gesture insets,
1523          * as long as they are outside the {@link #getSystemWindowInsets() system window insets}.
1524          *
1525          * <p>When {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} is requested, an inset will be returned
1526          * even when the system gestures are inactive due to
1527          * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} or
1528          * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}.
1529          *
1530          * @see #getSystemGestureInsets()
1531          */
systemGestures()1532         public static @InsetsType int systemGestures() {
1533             return SYSTEM_GESTURES;
1534         }
1535 
1536         /**
1537          * @see #getMandatorySystemGestureInsets
1538          */
mandatorySystemGestures()1539         public static @InsetsType int mandatorySystemGestures() {
1540             return MANDATORY_SYSTEM_GESTURES;
1541         }
1542 
1543         /**
1544          * @see #getTappableElementInsets
1545          */
tappableElement()1546         public static @InsetsType int tappableElement() {
1547             return TAPPABLE_ELEMENT;
1548         }
1549 
1550         /**
1551          * Returns an insets type representing the area that used by {@link DisplayCutout}.
1552          *
1553          * <p>This is equivalent to the safe insets on {@link #getDisplayCutout()}.
1554          *
1555          * <p>Note: During dispatch to {@link View#onApplyWindowInsets}, if the window is using
1556          * the {@link WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT default}
1557          * {@link WindowManager.LayoutParams#layoutInDisplayCutoutMode}, {@link #getDisplayCutout()}
1558          * will return {@code null} even if the window overlaps a display cutout area, in which case
1559          * the {@link #displayCutout() displayCutout() inset} will still report the accurate value.
1560          *
1561          * @see DisplayCutout#getSafeInsetLeft()
1562          * @see DisplayCutout#getSafeInsetTop()
1563          * @see DisplayCutout#getSafeInsetRight()
1564          * @see DisplayCutout#getSafeInsetBottom()
1565          */
displayCutout()1566         public static @InsetsType int displayCutout() {
1567             return DISPLAY_CUTOUT;
1568         }
1569 
1570         /**
1571          * @return All system bars. Includes {@link #statusBars()}, {@link #captionBar()} as well as
1572          *         {@link #navigationBars()}, but not {@link #ime()}.
1573          */
systemBars()1574         public static @InsetsType int systemBars() {
1575             return STATUS_BARS | NAVIGATION_BARS | CAPTION_BAR;
1576         }
1577 
1578         /**
1579          * @return All inset types combined.
1580          *
1581          * @hide
1582          */
all()1583         public static @InsetsType int all() {
1584             return 0xFFFFFFFF;
1585         }
1586 
1587         /**
1588          * Checks whether the specified type is considered to be part of visible insets.
1589          * @hide
1590          */
isVisibleInsetsType(int type, @SoftInputModeFlags int softInputModeFlags)1591         public static boolean isVisibleInsetsType(int type,
1592                 @SoftInputModeFlags int softInputModeFlags) {
1593             int softInputMode = softInputModeFlags & SOFT_INPUT_MASK_ADJUST;
1594             return (type & Type.systemBars()) != 0
1595                     || (softInputMode != SOFT_INPUT_ADJUST_NOTHING && (type & Type.ime()) != 0);
1596         }
1597     }
1598 
1599     /**
1600      * Class that defines different sides for insets.
1601      */
1602     public static final class Side {
1603 
1604         public static final int LEFT = 1 << 0;
1605         public static final int TOP = 1 << 1;
1606         public static final int RIGHT = 1 << 2;
1607         public static final int BOTTOM = 1 << 3;
1608 
Side()1609         private Side() {
1610         }
1611 
1612         /** @hide */
1613         @Retention(RetentionPolicy.SOURCE)
1614         @IntDef(flag = true, value = {LEFT, TOP, RIGHT, BOTTOM})
1615         public @interface InsetsSide {}
1616 
1617         /**
1618          * @return all four sides.
1619          */
all()1620         public static @InsetsSide int all() {
1621             return LEFT | TOP | RIGHT | BOTTOM;
1622         }
1623     }
1624 }
1625