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