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