• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 package android.view;
18 
19 import android.annotation.IntRange;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.graphics.Insets;
23 import android.graphics.Rect;
24 import android.os.IBinder;
25 import android.os.Parcel;
26 import android.os.Parcelable;
27 import android.view.InsetsSource.Flags;
28 import android.view.WindowInsets.Type.InsetsType;
29 
30 import java.util.Arrays;
31 import java.util.Objects;
32 
33 /**
34  * Insets provided by a window.
35  *
36  * The insets frame will by default as the window frame size. If the providers are set, the
37  * calculation result based on the source size will be used as the insets frame.
38  *
39  * The InsetsFrameProvider should be self-contained. Nothing describing the window itself, such as
40  * contentInsets, visibleInsets, etc. won't affect the insets providing to other windows when this
41  * is set.
42  * @hide
43  */
44 public class InsetsFrameProvider implements Parcelable {
45 
46     /**
47      * Uses the display frame as the source.
48      */
49     public static final int SOURCE_DISPLAY = 0;
50 
51     /**
52      * Uses the window bounds as the source.
53      */
54     public static final int SOURCE_CONTAINER_BOUNDS = 1;
55 
56     /**
57      * Uses the window frame as the source.
58      */
59     public static final int SOURCE_FRAME = 2;
60 
61     /**
62      * Uses {@link #mArbitraryRectangle} as the source.
63      */
64     public static final int SOURCE_ARBITRARY_RECTANGLE = 3;
65 
66     private final int mId;
67 
68     /**
69      * The selection of the starting rectangle to be converted into source frame.
70      */
71     private int mSource = SOURCE_FRAME;
72 
73     /**
74      * This is used as the source frame only if SOURCE_ARBITRARY_RECTANGLE is applied.
75      */
76     private Rect mArbitraryRectangle;
77 
78     /**
79      * Modifies the starting rectangle selected by {@link #mSource}.
80      *
81      * For example, when the given source frame is (0, 0) - (100, 200), and the insetsSize is null,
82      * the source frame will be directly used as the final insets frame. If the insetsSize is set to
83      * (0, 0, 0, 50) instead, the insets frame will be a frame starting from the bottom side of the
84      * source frame with height of 50, i.e., (0, 150) - (100, 200).
85      */
86     private Insets mInsetsSize = null;
87 
88     /**
89      * Various behavioral options/flags. Default is none.
90      *
91      * @see Flags
92      */
93     private @Flags int mFlags;
94 
95     /**
96      * If null, the size set in insetsSize will be applied to all window types. If it contains
97      * element of some types, the insets reported to the window with that types will be overridden.
98      */
99     private InsetsSizeOverride[] mInsetsSizeOverrides = null;
100 
101     /**
102      * This field, if set, is indicating the insets needs to be at least the given size inside the
103      * display cutout safe area. This will be compared to the insets size calculated based on other
104      * attributes, and will be applied when this is larger. This is independent of the
105      * PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT in LayoutParams, as this is not going to change
106      * the layout of the window, but only change the insets frame. This can be applied to insets
107      * calculated based on all three source frames.
108      *
109      * Be cautious, this will not be in effect for the window types whose insets size is overridden.
110      */
111     private Insets mMinimalInsetsSizeInDisplayCutoutSafe = null;
112 
113     /**
114      * Indicates the bounding rectangles within the provided insets frame, in relative coordinates
115      * to the source frame.
116      */
117     private Rect[] mBoundingRects = null;
118 
119     /**
120      * Creates an InsetsFrameProvider which describes what frame an insets source should have.
121      *
122      * @param owner the owner of this provider. We might have multiple sources with the same type on
123      *              a display, this is used to identify them.
124      * @param index the index of this provider. An owner might provide multiple sources with the
125      *              same type, this is used to identify them.
126      *              The value must be in a range of [0, 2047].
127      * @param type the {@link InsetsType}.
128      * @see InsetsSource#createId(Object, int, int)
129      */
InsetsFrameProvider(Object owner, @IntRange(from = 0, to = 2047) int index, @InsetsType int type)130     public InsetsFrameProvider(Object owner, @IntRange(from = 0, to = 2047) int index,
131             @InsetsType int type) {
132         mId = InsetsSource.createId(owner, index, type);
133     }
134 
135     /**
136      * Returns an unique integer which identifies the insets source.
137      */
getId()138     public int getId() {
139         return mId;
140     }
141 
142     /**
143      * Returns the index specified in {@link #InsetsFrameProvider(IBinder, int, int)}.
144      */
getIndex()145     public int getIndex() {
146         return InsetsSource.getIndex(mId);
147     }
148 
149     /**
150      * Returns the {@link InsetsType} specified in {@link #InsetsFrameProvider(IBinder, int, int)}.
151      */
getType()152     public int getType() {
153         return InsetsSource.getType(mId);
154     }
155 
setSource(int source)156     public InsetsFrameProvider setSource(int source) {
157         mSource = source;
158         return this;
159     }
160 
getSource()161     public int getSource() {
162         return mSource;
163     }
164 
165     /** Set the flags of this provider. */
setFlags(@lags int flags)166     public InsetsFrameProvider setFlags(@Flags int flags) {
167         mFlags = flags;
168         return this;
169     }
170 
setFlags(@lags int flags, @Flags int mask)171     public InsetsFrameProvider setFlags(@Flags int flags, @Flags int mask) {
172         mFlags = (mFlags & ~mask) | (flags & mask);
173         return this;
174     }
175 
getFlags()176     public @Flags int getFlags() {
177         return mFlags;
178     }
179 
hasFlags(@lags int mask)180     public boolean hasFlags(@Flags int mask) {
181         return (mFlags & mask) == mask;
182     }
183 
setInsetsSize(Insets insetsSize)184     public InsetsFrameProvider setInsetsSize(Insets insetsSize) {
185         mInsetsSize = insetsSize;
186         return this;
187     }
188 
getInsetsSize()189     public Insets getInsetsSize() {
190         return mInsetsSize;
191     }
192 
setArbitraryRectangle(Rect rect)193     public InsetsFrameProvider setArbitraryRectangle(Rect rect) {
194         mArbitraryRectangle = new Rect(rect);
195         return this;
196     }
197 
getArbitraryRectangle()198     public Rect getArbitraryRectangle() {
199         return mArbitraryRectangle;
200     }
201 
setInsetsSizeOverrides(InsetsSizeOverride[] insetsSizeOverrides)202     public InsetsFrameProvider setInsetsSizeOverrides(InsetsSizeOverride[] insetsSizeOverrides) {
203         mInsetsSizeOverrides = insetsSizeOverrides;
204         return this;
205     }
206 
getInsetsSizeOverrides()207     public InsetsSizeOverride[] getInsetsSizeOverrides() {
208         return mInsetsSizeOverrides;
209     }
210 
setMinimalInsetsSizeInDisplayCutoutSafe( Insets minimalInsetsSizeInDisplayCutoutSafe)211     public InsetsFrameProvider setMinimalInsetsSizeInDisplayCutoutSafe(
212             Insets minimalInsetsSizeInDisplayCutoutSafe) {
213         mMinimalInsetsSizeInDisplayCutoutSafe = minimalInsetsSizeInDisplayCutoutSafe;
214         return this;
215     }
216 
getMinimalInsetsSizeInDisplayCutoutSafe()217     public Insets getMinimalInsetsSizeInDisplayCutoutSafe() {
218         return mMinimalInsetsSizeInDisplayCutoutSafe;
219     }
220 
221     /**
222      * Sets the bounding rectangles within and relative to the source frame.
223      */
setBoundingRects(@ullable Rect[] boundingRects)224     public InsetsFrameProvider setBoundingRects(@Nullable Rect[] boundingRects) {
225         mBoundingRects = boundingRects == null ? null : boundingRects.clone();
226         return this;
227     }
228 
229     /**
230      * Returns the arbitrary bounding rects, or null if none were set.
231      */
232     @Nullable
getBoundingRects()233     public Rect[] getBoundingRects() {
234         return mBoundingRects;
235     }
236 
237     @Override
describeContents()238     public int describeContents() {
239         return 0;
240     }
241 
242     @Override
toString()243     public String toString() {
244         final StringBuilder sb = new StringBuilder("InsetsFrameProvider: {");
245         sb.append("id=#").append(Integer.toHexString(mId));
246         sb.append(", index=").append(getIndex());
247         sb.append(", type=").append(WindowInsets.Type.toString(getType()));
248         sb.append(", source=").append(sourceToString(mSource));
249         sb.append(", flags=[").append(InsetsSource.flagsToString(mFlags)).append("]");
250         if (mInsetsSize != null) {
251             sb.append(", insetsSize=").append(mInsetsSize);
252         }
253         if (mInsetsSizeOverrides != null) {
254             sb.append(", insetsSizeOverrides=").append(Arrays.toString(mInsetsSizeOverrides));
255         }
256         if (mArbitraryRectangle != null) {
257             sb.append(", mArbitraryRectangle=").append(mArbitraryRectangle.toShortString());
258         }
259         if (mMinimalInsetsSizeInDisplayCutoutSafe != null) {
260             sb.append(", mMinimalInsetsSizeInDisplayCutoutSafe=")
261                     .append(mMinimalInsetsSizeInDisplayCutoutSafe);
262         }
263         if (mBoundingRects != null) {
264             sb.append(", mBoundingRects=").append(Arrays.toString(mBoundingRects));
265         }
266         sb.append("}");
267         return sb.toString();
268     }
269 
sourceToString(int source)270     private static String sourceToString(int source) {
271         switch (source) {
272             case SOURCE_DISPLAY:
273                 return "DISPLAY";
274             case SOURCE_CONTAINER_BOUNDS:
275                 return "CONTAINER_BOUNDS";
276             case SOURCE_FRAME:
277                 return "FRAME";
278             case SOURCE_ARBITRARY_RECTANGLE:
279                 return "ARBITRARY_RECTANGLE";
280         }
281         return "UNDEFINED";
282     }
283 
InsetsFrameProvider(Parcel in)284     public InsetsFrameProvider(Parcel in) {
285         mId = in.readInt();
286         mSource = in.readInt();
287         mFlags = in.readInt();
288         mInsetsSize = in.readTypedObject(Insets.CREATOR);
289         mInsetsSizeOverrides = in.createTypedArray(InsetsSizeOverride.CREATOR);
290         mArbitraryRectangle = in.readTypedObject(Rect.CREATOR);
291         mMinimalInsetsSizeInDisplayCutoutSafe = in.readTypedObject(Insets.CREATOR);
292         mBoundingRects = in.createTypedArray(Rect.CREATOR);
293     }
294 
295     @Override
writeToParcel(Parcel out, int flags)296     public void writeToParcel(Parcel out, int flags) {
297         out.writeInt(mId);
298         out.writeInt(mSource);
299         out.writeInt(mFlags);
300         out.writeTypedObject(mInsetsSize, flags);
301         out.writeTypedArray(mInsetsSizeOverrides, flags);
302         out.writeTypedObject(mArbitraryRectangle, flags);
303         out.writeTypedObject(mMinimalInsetsSizeInDisplayCutoutSafe, flags);
304         out.writeTypedArray(mBoundingRects, flags);
305     }
306 
idEquals(InsetsFrameProvider o)307     public boolean idEquals(InsetsFrameProvider o) {
308         return mId == o.mId;
309     }
310 
311     @Override
equals(Object o)312     public boolean equals(Object o) {
313         if (this == o) {
314             return true;
315         }
316         if (o == null || getClass() != o.getClass()) {
317             return false;
318         }
319         final InsetsFrameProvider other = (InsetsFrameProvider) o;
320         return mId == other.mId && mSource == other.mSource && mFlags == other.mFlags
321                 && Objects.equals(mInsetsSize, other.mInsetsSize)
322                 && Arrays.equals(mInsetsSizeOverrides, other.mInsetsSizeOverrides)
323                 && Objects.equals(mArbitraryRectangle, other.mArbitraryRectangle)
324                 && Objects.equals(mMinimalInsetsSizeInDisplayCutoutSafe,
325                         other.mMinimalInsetsSizeInDisplayCutoutSafe)
326                 && Arrays.equals(mBoundingRects, other.mBoundingRects);
327     }
328 
329     @Override
hashCode()330     public int hashCode() {
331         return Objects.hash(mId, mSource, mFlags, mInsetsSize,
332                 Arrays.hashCode(mInsetsSizeOverrides), mArbitraryRectangle,
333                 mMinimalInsetsSizeInDisplayCutoutSafe, Arrays.hashCode(mBoundingRects));
334     }
335 
336     public static final @NonNull Parcelable.Creator<InsetsFrameProvider> CREATOR =
337             new Parcelable.Creator<>() {
338                 @Override
339                 public InsetsFrameProvider createFromParcel(Parcel in) {
340                     return new InsetsFrameProvider(in);
341                 }
342 
343                 @Override
344                 public InsetsFrameProvider[] newArray(int size) {
345                     return new InsetsFrameProvider[size];
346                 }
347             };
348 
349     /**
350      * Class to describe the insets size to be provided to window with specific window type. If not
351      * used, same insets size will be sent as instructed in the insetsSize and source.
352      *
353      * If the insetsSize of given type is set to {@code null}, the insets source frame will be used
354      * directly for that window type.
355      */
356     public static class InsetsSizeOverride implements Parcelable {
357 
358         private final int mWindowType;
359         private final Insets mInsetsSize;
360 
InsetsSizeOverride(Parcel in)361         protected InsetsSizeOverride(Parcel in) {
362             mWindowType = in.readInt();
363             mInsetsSize = in.readTypedObject(Insets.CREATOR);
364         }
365 
InsetsSizeOverride(int windowType, Insets insetsSize)366         public InsetsSizeOverride(int windowType, Insets insetsSize) {
367             mWindowType = windowType;
368             mInsetsSize = insetsSize;
369         }
getWindowType()370         public int getWindowType() {
371             return mWindowType;
372         }
373 
getInsetsSize()374         public Insets getInsetsSize() {
375             return mInsetsSize;
376         }
377 
378         public static final Creator<InsetsSizeOverride> CREATOR = new Creator<>() {
379             @Override
380             public InsetsSizeOverride createFromParcel(Parcel in) {
381                 return new InsetsSizeOverride(in);
382             }
383 
384             @Override
385             public InsetsSizeOverride[] newArray(int size) {
386                 return new InsetsSizeOverride[size];
387             }
388         };
389 
390         @Override
describeContents()391         public int describeContents() {
392             return 0;
393         }
394 
395         @Override
writeToParcel(Parcel out, int flags)396         public void writeToParcel(Parcel out, int flags) {
397             out.writeInt(mWindowType);
398             out.writeTypedObject(mInsetsSize, flags);
399         }
400 
401         @Override
toString()402         public String toString() {
403             StringBuilder sb = new StringBuilder(32);
404             sb.append("TypedInsetsSize: {");
405             sb.append("windowType=").append(ViewDebug.intToString(
406                     WindowManager.LayoutParams.class, "type", mWindowType));
407             sb.append(", insetsSize=").append(mInsetsSize);
408             sb.append("}");
409             return sb.toString();
410         }
411 
412         @Override
hashCode()413         public int hashCode() {
414             return Objects.hash(mWindowType, mInsetsSize);
415         }
416     }
417 }
418 
419