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.view.InsetsSourceControlProto.LEASH; 22 import static android.view.InsetsSourceControlProto.POSITION; 23 import static android.view.InsetsSourceControlProto.TYPE; 24 25 import android.annotation.NonNull; 26 import android.annotation.Nullable; 27 import android.graphics.Insets; 28 import android.graphics.Point; 29 import android.os.Parcel; 30 import android.os.Parcelable; 31 import android.util.proto.ProtoOutputStream; 32 import android.view.WindowInsets.Type.InsetsType; 33 34 import java.io.PrintWriter; 35 import java.util.Objects; 36 import java.util.function.Consumer; 37 38 /** 39 * Represents a parcelable object to allow controlling a single {@link InsetsSource}. 40 * @hide 41 */ 42 public class InsetsSourceControl implements Parcelable { 43 44 private final int mId; 45 private final @InsetsType int mType; 46 private final @Nullable SurfaceControl mLeash; 47 private final boolean mInitiallyVisible; 48 private final Point mSurfacePosition; 49 50 // This is used while playing an insets animation regardless of the relative frame. This would 51 // be the insets received by the bounds of its source window. 52 private Insets mInsetsHint; 53 54 private boolean mSkipAnimationOnce; 55 private int mParcelableFlags; 56 InsetsSourceControl(int id, @InsetsType int type, @Nullable SurfaceControl leash, boolean initiallyVisible, Point surfacePosition, Insets insetsHint)57 public InsetsSourceControl(int id, @InsetsType int type, @Nullable SurfaceControl leash, 58 boolean initiallyVisible, Point surfacePosition, Insets insetsHint) { 59 mId = id; 60 mType = type; 61 mLeash = leash; 62 mInitiallyVisible = initiallyVisible; 63 mSurfacePosition = surfacePosition; 64 mInsetsHint = insetsHint; 65 } 66 InsetsSourceControl(InsetsSourceControl other)67 public InsetsSourceControl(InsetsSourceControl other) { 68 mId = other.mId; 69 mType = other.mType; 70 if (other.mLeash != null) { 71 mLeash = new SurfaceControl(other.mLeash, "InsetsSourceControl"); 72 } else { 73 mLeash = null; 74 } 75 mInitiallyVisible = other.mInitiallyVisible; 76 mSurfacePosition = new Point(other.mSurfacePosition); 77 mInsetsHint = other.mInsetsHint; 78 mSkipAnimationOnce = other.getAndClearSkipAnimationOnce(); 79 } 80 InsetsSourceControl(Parcel in)81 public InsetsSourceControl(Parcel in) { 82 mId = in.readInt(); 83 mType = in.readInt(); 84 mLeash = in.readTypedObject(SurfaceControl.CREATOR); 85 mInitiallyVisible = in.readBoolean(); 86 mSurfacePosition = in.readTypedObject(Point.CREATOR); 87 mInsetsHint = in.readTypedObject(Insets.CREATOR); 88 mSkipAnimationOnce = in.readBoolean(); 89 } 90 getId()91 public int getId() { 92 return mId; 93 } 94 getType()95 public int getType() { 96 return mType; 97 } 98 99 /** 100 * Gets the leash for controlling insets source. If the system is controlling the insets source, 101 * for example, transient bars, the client will receive fake controls without leash in it. 102 * 103 * @return the leash. 104 */ getLeash()105 public @Nullable SurfaceControl getLeash() { 106 return mLeash; 107 } 108 isInitiallyVisible()109 public boolean isInitiallyVisible() { 110 return mInitiallyVisible; 111 } 112 setSurfacePosition(int left, int top)113 public boolean setSurfacePosition(int left, int top) { 114 if (mSurfacePosition.equals(left, top)) { 115 return false; 116 } 117 mSurfacePosition.set(left, top); 118 return true; 119 } 120 getSurfacePosition()121 public Point getSurfacePosition() { 122 return mSurfacePosition; 123 } 124 setInsetsHint(Insets insets)125 public void setInsetsHint(Insets insets) { 126 mInsetsHint = insets; 127 } 128 setInsetsHint(int left, int top, int right, int bottom)129 public void setInsetsHint(int left, int top, int right, int bottom) { 130 mInsetsHint = Insets.of(left, top, right, bottom); 131 } 132 getInsetsHint()133 public Insets getInsetsHint() { 134 return mInsetsHint; 135 } 136 setSkipAnimationOnce(boolean skipAnimation)137 public void setSkipAnimationOnce(boolean skipAnimation) { 138 mSkipAnimationOnce = skipAnimation; 139 } 140 141 /** 142 * Get the state whether the current control needs to skip animation or not. 143 * 144 * Note that this is a one-time check that the state is only valid and can be called when 145 * {@link InsetsController#applyAnimation} to check if the current control can skip animation 146 * at this time, and then will clear the state value. 147 */ getAndClearSkipAnimationOnce()148 public boolean getAndClearSkipAnimationOnce() { 149 final boolean result = mSkipAnimationOnce; 150 mSkipAnimationOnce = false; 151 return result; 152 } 153 setParcelableFlags(int parcelableFlags)154 public void setParcelableFlags(int parcelableFlags) { 155 mParcelableFlags = parcelableFlags; 156 } 157 158 @Override describeContents()159 public int describeContents() { 160 return 0; 161 } 162 163 @Override writeToParcel(Parcel dest, int flags)164 public void writeToParcel(Parcel dest, int flags) { 165 dest.writeInt(mId); 166 dest.writeInt(mType); 167 dest.writeTypedObject(mLeash, mParcelableFlags); 168 dest.writeBoolean(mInitiallyVisible); 169 dest.writeTypedObject(mSurfacePosition, mParcelableFlags); 170 dest.writeTypedObject(mInsetsHint, mParcelableFlags); 171 dest.writeBoolean(mSkipAnimationOnce); 172 } 173 release(Consumer<SurfaceControl> surfaceReleaseConsumer)174 public void release(Consumer<SurfaceControl> surfaceReleaseConsumer) { 175 if (mLeash != null) { 176 surfaceReleaseConsumer.accept(mLeash); 177 } 178 } 179 180 @Override equals(@ullable Object o)181 public boolean equals(@Nullable Object o) { 182 if (this == o) { 183 return true; 184 } 185 if (o == null || getClass() != o.getClass()) { 186 return false; 187 } 188 final InsetsSourceControl that = (InsetsSourceControl) o; 189 final SurfaceControl thatLeash = that.mLeash; 190 return mId == that.mId 191 && mType == that.mType 192 && ((mLeash == thatLeash) 193 || (mLeash != null && thatLeash != null && mLeash.isSameSurface(thatLeash))) 194 && mInitiallyVisible == that.mInitiallyVisible 195 && mSurfacePosition.equals(that.mSurfacePosition) 196 && mInsetsHint.equals(that.mInsetsHint) 197 && mSkipAnimationOnce == that.mSkipAnimationOnce; 198 } 199 200 @Override hashCode()201 public int hashCode() { 202 return Objects.hash(mId, mType, mLeash, mInitiallyVisible, mSurfacePosition, mInsetsHint, 203 mSkipAnimationOnce); 204 } 205 206 @Override toString()207 public String toString() { 208 return "InsetsSourceControl: {" + Integer.toHexString(mId) 209 + " mType=" + WindowInsets.Type.toString(mType) 210 + (mInitiallyVisible ? " initiallyVisible" : "") 211 + " mSurfacePosition=" + mSurfacePosition 212 + " mInsetsHint=" + mInsetsHint 213 + (mSkipAnimationOnce ? " skipAnimationOnce" : "") 214 + "}"; 215 } 216 dump(String prefix, PrintWriter pw)217 public void dump(String prefix, PrintWriter pw) { 218 pw.print(prefix); 219 pw.print("InsetsSourceControl mId="); pw.print(Integer.toHexString(mId)); 220 pw.print(" mType="); pw.print(WindowInsets.Type.toString(mType)); 221 pw.print(" mLeash="); pw.print(mLeash); 222 pw.print(" mInitiallyVisible="); pw.print(mInitiallyVisible); 223 pw.print(" mSurfacePosition="); pw.print(mSurfacePosition); 224 pw.print(" mInsetsHint="); pw.print(mInsetsHint); 225 pw.print(" mSkipAnimationOnce="); pw.print(mSkipAnimationOnce); 226 pw.println(); 227 } 228 229 public static final @NonNull Creator<InsetsSourceControl> CREATOR = new Creator<>() { 230 public InsetsSourceControl createFromParcel(Parcel in) { 231 return new InsetsSourceControl(in); 232 } 233 234 public InsetsSourceControl[] newArray(int size) { 235 return new InsetsSourceControl[size]; 236 } 237 }; 238 239 /** 240 * Export the state of {@link InsetsSourceControl} into a protocol buffer output stream. 241 * 242 * @param proto Stream to write the state to 243 * @param fieldId FieldId of InsetsSource as defined in the parent message 244 */ dumpDebug(ProtoOutputStream proto, long fieldId)245 public void dumpDebug(ProtoOutputStream proto, long fieldId) { 246 final long token = proto.start(fieldId); 247 proto.write(TYPE, WindowInsets.Type.toString(mType)); 248 249 final long surfaceToken = proto.start(POSITION); 250 proto.write(X, mSurfacePosition.x); 251 proto.write(Y, mSurfacePosition.y); 252 proto.end(surfaceToken); 253 254 if (mLeash != null) { 255 mLeash.dumpDebug(proto, LEASH); 256 } 257 proto.end(token); 258 } 259 260 /** 261 * Used to obtain the array from the argument of a binder call. In this way, the length of the 262 * array can be dynamic. 263 */ 264 public static class Array implements Parcelable { 265 266 private @Nullable InsetsSourceControl[] mControls; 267 Array()268 public Array() { 269 } 270 Array(Parcel in)271 public Array(Parcel in) { 272 readFromParcel(in); 273 } 274 set(@ullable InsetsSourceControl[] controls)275 public void set(@Nullable InsetsSourceControl[] controls) { 276 mControls = controls; 277 } 278 get()279 public @Nullable InsetsSourceControl[] get() { 280 return mControls; 281 } 282 283 @Override describeContents()284 public int describeContents() { 285 return 0; 286 } 287 readFromParcel(Parcel in)288 public void readFromParcel(Parcel in) { 289 mControls = in.createTypedArray(InsetsSourceControl.CREATOR); 290 } 291 292 @Override writeToParcel(Parcel out, int flags)293 public void writeToParcel(Parcel out, int flags) { 294 out.writeTypedArray(mControls, flags); 295 } 296 297 public static final @NonNull Creator<Array> CREATOR = new Creator<>() { 298 public Array createFromParcel(Parcel in) { 299 return new Array(in); 300 } 301 302 public Array[] newArray(int size) { 303 return new Array[size]; 304 } 305 }; 306 } 307 } 308