• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 static android.graphics.PointProto.X;
20 import static android.graphics.PointProto.Y;
21 import static android.util.SequenceUtils.getInitSeq;
22 import static android.view.InsetsSourceControlProto.LEASH;
23 import static android.view.InsetsSourceControlProto.POSITION;
24 import static android.view.InsetsSourceControlProto.TYPE_NUMBER;
25 
26 import android.annotation.NonNull;
27 import android.annotation.Nullable;
28 import android.graphics.Insets;
29 import android.graphics.Point;
30 import android.os.Parcel;
31 import android.os.Parcelable;
32 import android.util.proto.ProtoOutputStream;
33 import android.view.WindowInsets.Type.InsetsType;
34 import android.view.inputmethod.ImeTracker;
35 
36 import java.io.PrintWriter;
37 import java.util.Arrays;
38 import java.util.Objects;
39 import java.util.function.Consumer;
40 
41 /**
42  * Represents a parcelable object to allow controlling a single {@link InsetsSource}.
43  * @hide
44  */
45 public class InsetsSourceControl implements Parcelable {
46 
47     private final int mId;
48     private final @InsetsType int mType;
49     private final @Nullable SurfaceControl mLeash;
50     private final boolean mInitiallyVisible;
51     private final Point mSurfacePosition;
52 
53     // This is used while playing an insets animation regardless of the relative frame. This would
54     // be the insets received by the bounds of its source window.
55     private Insets mInsetsHint;
56 
57     private boolean mSkipAnimationOnce;
58     private int mParcelableFlags;
59 
60     /** The token tracking the current IME request */
61     private @Nullable ImeTracker.Token mImeStatsToken;
62 
InsetsSourceControl(int id, @InsetsType int type, @Nullable SurfaceControl leash, boolean initiallyVisible, Point surfacePosition, Insets insetsHint)63     public InsetsSourceControl(int id, @InsetsType int type, @Nullable SurfaceControl leash,
64             boolean initiallyVisible, Point surfacePosition, Insets insetsHint) {
65         mId = id;
66         mType = type;
67         mLeash = leash;
68         mInitiallyVisible = initiallyVisible;
69         mSurfacePosition = surfacePosition;
70         mInsetsHint = insetsHint;
71     }
72 
InsetsSourceControl(InsetsSourceControl other)73     public InsetsSourceControl(InsetsSourceControl other) {
74         mId = other.mId;
75         mType = other.mType;
76         if (other.mLeash != null) {
77             mLeash = new SurfaceControl(other.mLeash, "InsetsSourceControl");
78         } else {
79             mLeash = null;
80         }
81         mInitiallyVisible = other.mInitiallyVisible;
82         mSurfacePosition = new Point(other.mSurfacePosition);
83         mInsetsHint = other.mInsetsHint;
84         mSkipAnimationOnce = other.getAndClearSkipAnimationOnce();
85         mImeStatsToken = other.getImeStatsToken();
86     }
87 
InsetsSourceControl(Parcel in)88     public InsetsSourceControl(Parcel in) {
89         mId = in.readInt();
90         mType = in.readInt();
91         mLeash = in.readTypedObject(SurfaceControl.CREATOR);
92         mInitiallyVisible = in.readBoolean();
93         mSurfacePosition = in.readTypedObject(Point.CREATOR);
94         mInsetsHint = in.readTypedObject(Insets.CREATOR);
95         mSkipAnimationOnce = in.readBoolean();
96         mImeStatsToken = in.readTypedObject(ImeTracker.Token.CREATOR);
97     }
98 
getId()99     public int getId() {
100         return mId;
101     }
102 
getType()103     public int getType() {
104         return mType;
105     }
106 
107     /**
108      * Gets the leash for controlling insets source. If the system is controlling the insets source,
109      * for example, transient bars, the client will receive fake controls without leash in it.
110      *
111      * @return the leash.
112      */
getLeash()113     public @Nullable SurfaceControl getLeash() {
114         return mLeash;
115     }
116 
isInitiallyVisible()117     public boolean isInitiallyVisible() {
118         return mInitiallyVisible;
119     }
120 
setSurfacePosition(int left, int top)121     public boolean setSurfacePosition(int left, int top) {
122         if (mSurfacePosition.equals(left, top)) {
123             return false;
124         }
125         mSurfacePosition.set(left, top);
126         return true;
127     }
128 
getSurfacePosition()129     public Point getSurfacePosition() {
130         return mSurfacePosition;
131     }
132 
setInsetsHint(Insets insets)133     public void setInsetsHint(Insets insets) {
134         mInsetsHint = insets;
135     }
136 
setInsetsHint(int left, int top, int right, int bottom)137     public void setInsetsHint(int left, int top, int right, int bottom) {
138         mInsetsHint = Insets.of(left, top, right, bottom);
139     }
140 
getInsetsHint()141     public Insets getInsetsHint() {
142         return mInsetsHint;
143     }
144 
isFake()145     public boolean isFake() {
146         return mLeash == null && Insets.NONE.equals(mInsetsHint);
147     }
148 
setSkipAnimationOnce(boolean skipAnimation)149     public void setSkipAnimationOnce(boolean skipAnimation) {
150         mSkipAnimationOnce = skipAnimation;
151     }
152 
153     /**
154      * Get the state whether the current control needs to skip animation or not.
155      *
156      * Note that this is a one-time check that the state is only valid and can be called when
157      * {@link InsetsController#applyAnimation} to check if the current control can skip animation
158      * at this time, and then will clear the state value.
159      */
getAndClearSkipAnimationOnce()160     public boolean getAndClearSkipAnimationOnce() {
161         final boolean result = mSkipAnimationOnce;
162         mSkipAnimationOnce = false;
163         return result;
164     }
165 
166     @Nullable
getImeStatsToken()167     public ImeTracker.Token getImeStatsToken() {
168         return mImeStatsToken;
169     }
170 
setImeStatsToken(@ullable ImeTracker.Token imeStatsToken)171     public void setImeStatsToken(@Nullable ImeTracker.Token imeStatsToken) {
172         mImeStatsToken = imeStatsToken;
173     }
174 
setParcelableFlags(int parcelableFlags)175     public void setParcelableFlags(int parcelableFlags) {
176         mParcelableFlags = parcelableFlags;
177     }
178 
179     @Override
describeContents()180     public int describeContents() {
181         return 0;
182     }
183 
184     @Override
writeToParcel(Parcel dest, int flags)185     public void writeToParcel(Parcel dest, int flags) {
186         dest.writeInt(mId);
187         dest.writeInt(mType);
188         dest.writeTypedObject(mLeash, mParcelableFlags);
189         dest.writeBoolean(mInitiallyVisible);
190         dest.writeTypedObject(mSurfacePosition, mParcelableFlags);
191         dest.writeTypedObject(mInsetsHint, mParcelableFlags);
192         dest.writeBoolean(mSkipAnimationOnce);
193         dest.writeTypedObject(mImeStatsToken, mParcelableFlags);
194     }
195 
release(Consumer<SurfaceControl> surfaceReleaseConsumer)196     public void release(Consumer<SurfaceControl> surfaceReleaseConsumer) {
197         if (mLeash != null && mLeash.isValid()) {
198             surfaceReleaseConsumer.accept(mLeash);
199         }
200     }
201 
202     @Override
equals(@ullable Object o)203     public boolean equals(@Nullable Object o) {
204         if (this == o) {
205             return true;
206         }
207         if (o == null || getClass() != o.getClass()) {
208             return false;
209         }
210         final InsetsSourceControl that = (InsetsSourceControl) o;
211         final SurfaceControl thatLeash = that.mLeash;
212         return mId == that.mId
213                 && mType == that.mType
214                 && ((mLeash == thatLeash)
215                         || (mLeash != null && thatLeash != null && mLeash.isSameSurface(thatLeash)))
216                 && mInitiallyVisible == that.mInitiallyVisible
217                 && mSurfacePosition.equals(that.mSurfacePosition)
218                 && mInsetsHint.equals(that.mInsetsHint)
219                 && mSkipAnimationOnce == that.mSkipAnimationOnce;
220     }
221 
222     @Override
hashCode()223     public int hashCode() {
224         return Objects.hash(mId, mType, mLeash, mInitiallyVisible, mSurfacePosition, mInsetsHint,
225                 mSkipAnimationOnce, mImeStatsToken);
226     }
227 
228     @Override
toString()229     public String toString() {
230         return "InsetsSourceControl: {" + Integer.toHexString(mId)
231                 + " mType=" + WindowInsets.Type.toString(mType)
232                 + (mInitiallyVisible ? " initiallyVisible" : "")
233                 + " mSurfacePosition=" + mSurfacePosition
234                 + " mInsetsHint=" + mInsetsHint
235                 + (mSkipAnimationOnce ? " skipAnimationOnce" : "")
236                 + "}";
237     }
238 
dump(String prefix, PrintWriter pw)239     public void dump(String prefix, PrintWriter pw) {
240         pw.print(prefix);
241         pw.print("InsetsSourceControl mId="); pw.print(Integer.toHexString(mId));
242         pw.print(" mType="); pw.print(WindowInsets.Type.toString(mType));
243         pw.print(" mLeash="); pw.print(mLeash);
244         pw.print(" mInitiallyVisible="); pw.print(mInitiallyVisible);
245         pw.print(" mSurfacePosition="); pw.print(mSurfacePosition);
246         pw.print(" mInsetsHint="); pw.print(mInsetsHint);
247         pw.print(" mSkipAnimationOnce="); pw.print(mSkipAnimationOnce);
248         pw.print(" mImeStatsToken="); pw.print(mImeStatsToken);
249         pw.println();
250     }
251 
252     public static final @NonNull Creator<InsetsSourceControl> CREATOR = new Creator<>() {
253         public InsetsSourceControl createFromParcel(Parcel in) {
254             return new InsetsSourceControl(in);
255         }
256 
257         public InsetsSourceControl[] newArray(int size) {
258             return new InsetsSourceControl[size];
259         }
260     };
261 
262     /**
263      * Export the state of {@link InsetsSourceControl} into a protocol buffer output stream.
264      *
265      * @param proto   Stream to write the state to
266      * @param fieldId FieldId of InsetsSource as defined in the parent message
267      */
dumpDebug(ProtoOutputStream proto, long fieldId)268     public void dumpDebug(ProtoOutputStream proto, long fieldId) {
269         final long token = proto.start(fieldId);
270         final long surfaceToken = proto.start(POSITION);
271         proto.write(X, mSurfacePosition.x);
272         proto.write(Y, mSurfacePosition.y);
273         proto.end(surfaceToken);
274 
275         if (mLeash != null) {
276             mLeash.dumpDebug(proto, LEASH);
277         }
278 
279         proto.write(TYPE_NUMBER, mType);
280         proto.end(token);
281     }
282 
283     /**
284      * Used to obtain the array from the argument of a binder call. In this way, the length of the
285      * array can be dynamic.
286      */
287     public static class Array implements Parcelable {
288 
289         private @Nullable InsetsSourceControl[] mControls;
290 
291         /** To make sure the info update between client and system server is in order. */
292         private int mSeq = getInitSeq();
293 
Array()294         public Array() {
295         }
296 
297         /**
298          * @param copyControls whether or not to make a copy of the each {@link InsetsSourceControl}
299          */
Array(@onNull Array other, boolean copyControls)300         public Array(@NonNull Array other, boolean copyControls) {
301             setTo(other, copyControls);
302         }
303 
Array(@onNull Parcel in)304         public Array(@NonNull Parcel in) {
305             readFromParcel(in);
306         }
307 
getSeq()308         public int getSeq() {
309             return mSeq;
310         }
311 
setSeq(int seq)312         public void setSeq(int seq) {
313             mSeq = seq;
314         }
315 
316         /** Updates the current Array to the given Array. */
setTo(@onNull Array other, boolean copyControls)317         public void setTo(@NonNull Array other, boolean copyControls) {
318             set(other.mControls, copyControls);
319             mSeq = other.mSeq;
320         }
321 
322         /** Updates the current controls to the given controls. */
set(@ullable InsetsSourceControl[] controls, boolean copyControls)323         public void set(@Nullable InsetsSourceControl[] controls, boolean copyControls) {
324             if (controls == null || !copyControls) {
325                 mControls = controls;
326                 return;
327             }
328             // Make a copy of the array.
329             mControls = new InsetsSourceControl[controls.length];
330             for (int i = mControls.length - 1; i >= 0; i--) {
331                 if (controls[i] != null) {
332                     mControls[i] = new InsetsSourceControl(controls[i]);
333                 }
334             }
335         }
336 
337         /** Gets the controls. */
get()338         public @Nullable InsetsSourceControl[] get() {
339             return mControls;
340         }
341 
342         /** Cleanup {@link SurfaceControl} stored in controls to prevent leak. */
release()343         public void release() {
344             if (mControls == null) {
345                 return;
346             }
347             for (InsetsSourceControl control : mControls) {
348                 if (control != null) {
349                     control.release(SurfaceControl::release);
350                 }
351             }
352         }
353 
354         /** Sets the given flags to all controls. */
setParcelableFlags(int parcelableFlags)355         public void setParcelableFlags(int parcelableFlags) {
356             if (mControls == null) {
357                 return;
358             }
359             for (InsetsSourceControl control : mControls) {
360                 if (control != null) {
361                     control.setParcelableFlags(parcelableFlags);
362                 }
363             }
364         }
365 
366         @Override
describeContents()367         public int describeContents() {
368             return 0;
369         }
370 
readFromParcel(Parcel in)371         public void readFromParcel(Parcel in) {
372             mControls = in.createTypedArray(InsetsSourceControl.CREATOR);
373             mSeq = in.readInt();
374         }
375 
376         @Override
writeToParcel(Parcel out, int flags)377         public void writeToParcel(Parcel out, int flags) {
378             out.writeTypedArray(mControls, flags);
379             out.writeInt(mSeq);
380         }
381 
382         public static final @NonNull Creator<Array> CREATOR = new Creator<>() {
383             public Array createFromParcel(Parcel in) {
384                 return new Array(in);
385             }
386 
387             public Array[] newArray(int size) {
388                 return new Array[size];
389             }
390         };
391 
392         @Override
equals(@ullable Object o)393         public boolean equals(@Nullable Object o) {
394             if (this == o) {
395                 return true;
396             }
397             if (o == null || getClass() != o.getClass()) {
398                 return false;
399             }
400             final InsetsSourceControl.Array other = (InsetsSourceControl.Array) o;
401             // mSeq is for internal bookkeeping only.
402             return Arrays.equals(mControls, other.mControls);
403         }
404 
405         @Override
hashCode()406         public int hashCode() {
407             return Arrays.hashCode(mControls);
408         }
409     }
410 }
411