1 /* 2 * Copyright (C) 2017 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 package android.view.autofill; 17 18 import android.annotation.NonNull; 19 import android.annotation.Nullable; 20 import android.annotation.TestApi; 21 import android.os.Parcel; 22 import android.os.Parcelable; 23 import android.view.View; 24 25 /** 26 * A unique identifier for an autofill node inside an {@link android.app.Activity}. 27 */ 28 public final class AutofillId implements Parcelable { 29 30 /** @hide */ 31 public static final int NO_SESSION = 0; 32 33 private static final int FLAG_IS_VIRTUAL_INT = 0x1; 34 private static final int FLAG_IS_VIRTUAL_LONG = 0x2; 35 private static final int FLAG_HAS_SESSION = 0x4; 36 37 private final int mViewId; 38 private int mFlags; 39 private final int mVirtualIntId; 40 private final long mVirtualLongId; 41 private int mSessionId; 42 43 /** @hide */ 44 @TestApi AutofillId(int id)45 public AutofillId(int id) { 46 this(/* flags= */ 0, id, View.NO_ID, NO_SESSION); 47 } 48 49 /** @hide */ 50 @TestApi AutofillId(@onNull AutofillId hostId, int virtualChildId)51 public AutofillId(@NonNull AutofillId hostId, int virtualChildId) { 52 this(FLAG_IS_VIRTUAL_INT, hostId.mViewId, virtualChildId, NO_SESSION); 53 } 54 55 /** @hide */ 56 @TestApi AutofillId(int hostId, int virtualChildId)57 public AutofillId(int hostId, int virtualChildId) { 58 this(FLAG_IS_VIRTUAL_INT, hostId, virtualChildId, NO_SESSION); 59 } 60 61 /** @hide */ 62 @TestApi AutofillId(@onNull AutofillId hostId, long virtualChildId, int sessionId)63 public AutofillId(@NonNull AutofillId hostId, long virtualChildId, int sessionId) { 64 this(FLAG_IS_VIRTUAL_LONG | FLAG_HAS_SESSION, hostId.mViewId, virtualChildId, sessionId); 65 } 66 AutofillId(int flags, int parentId, long virtualChildId, int sessionId)67 private AutofillId(int flags, int parentId, long virtualChildId, int sessionId) { 68 mFlags = flags; 69 mViewId = parentId; 70 mVirtualIntId = ((flags & FLAG_IS_VIRTUAL_INT) != 0) ? (int) virtualChildId : View.NO_ID; 71 mVirtualLongId = ((flags & FLAG_IS_VIRTUAL_LONG) != 0) ? virtualChildId : View.NO_ID; 72 mSessionId = sessionId; 73 } 74 75 /** @hide */ 76 @NonNull 77 @TestApi withoutSession(@onNull AutofillId id)78 public static AutofillId withoutSession(@NonNull AutofillId id) { 79 final int flags = id.mFlags & ~FLAG_HAS_SESSION; 80 final long virtualChildId = 81 ((id.mFlags & FLAG_IS_VIRTUAL_LONG) != 0) ? id.mVirtualLongId 82 : id.mVirtualIntId; 83 return new AutofillId(flags, id.mViewId, virtualChildId, NO_SESSION); 84 } 85 86 /** @hide */ getViewId()87 public int getViewId() { 88 return mViewId; 89 } 90 91 /** 92 * Gets the virtual child id. 93 * 94 * <p>Should only be used on subsystems where such id is represented by an {@code int} 95 * (Assist and Autofill). 96 * 97 * @hide 98 */ getVirtualChildIntId()99 public int getVirtualChildIntId() { 100 return mVirtualIntId; 101 } 102 103 /** 104 * Gets the virtual child id. 105 * 106 * <p>Should only be used on subsystems where such id is represented by a {@code long} 107 * (ContentCapture). 108 * 109 * @hide 110 */ getVirtualChildLongId()111 public long getVirtualChildLongId() { 112 return mVirtualLongId; 113 } 114 115 /** 116 * Checks whether this node represents a virtual child, whose id is represented by an 117 * {@code int}. 118 * 119 * <p>Should only be used on subsystems where such id is represented by an {@code int} 120 * (Assist and Autofill). 121 * 122 * @hide 123 */ isVirtualInt()124 public boolean isVirtualInt() { 125 return (mFlags & FLAG_IS_VIRTUAL_INT) != 0; 126 } 127 128 /** 129 * Checks whether this node represents a virtual child, whose id is represented by an 130 * {@code long}. 131 * 132 * <p>Should only be used on subsystems where such id is represented by a {@code long} 133 * (ContentCapture). 134 * 135 * @hide 136 */ isVirtualLong()137 public boolean isVirtualLong() { 138 return (mFlags & FLAG_IS_VIRTUAL_LONG) != 0; 139 } 140 141 /** 142 * Checks whether this node represents a non-virtual child. 143 * 144 * @hide 145 */ isNonVirtual()146 public boolean isNonVirtual() { 147 return !isVirtualInt() && !isVirtualLong(); 148 } 149 150 /** @hide */ hasSession()151 public boolean hasSession() { 152 return (mFlags & FLAG_HAS_SESSION) != 0; 153 } 154 155 /** @hide */ getSessionId()156 public int getSessionId() { 157 return mSessionId; 158 } 159 160 /** @hide */ setSessionId(int sessionId)161 public void setSessionId(int sessionId) { 162 mFlags |= FLAG_HAS_SESSION; 163 mSessionId = sessionId; 164 } 165 166 /** @hide */ resetSessionId()167 public void resetSessionId() { 168 mFlags &= ~FLAG_HAS_SESSION; 169 mSessionId = NO_SESSION; 170 } 171 172 ///////////////////////////////// 173 // Object "contract" methods. // 174 ///////////////////////////////// 175 176 @Override hashCode()177 public int hashCode() { 178 final int prime = 31; 179 int result = 1; 180 result = prime * result + mViewId; 181 result = prime * result + mVirtualIntId; 182 result = prime * result + (int) (mVirtualLongId ^ (mVirtualLongId >>> 32)); 183 result = prime * result + mSessionId; 184 return result; 185 } 186 187 @Override equals(Object obj)188 public boolean equals(Object obj) { 189 if (this == obj) return true; 190 if (obj == null) return false; 191 if (getClass() != obj.getClass()) return false; 192 final AutofillId other = (AutofillId) obj; 193 if (mViewId != other.mViewId) return false; 194 if (mVirtualIntId != other.mVirtualIntId) return false; 195 if (mVirtualLongId != other.mVirtualLongId) return false; 196 if (mSessionId != other.mSessionId) return false; 197 return true; 198 } 199 200 /** @hide */ 201 @TestApi equalsIgnoreSession(@ullable AutofillId other)202 public boolean equalsIgnoreSession(@Nullable AutofillId other) { 203 if (this == other) return true; 204 if (other == null) return false; 205 if (mViewId != other.mViewId) return false; 206 if (mVirtualIntId != other.mVirtualIntId) return false; 207 if (mVirtualLongId != other.mVirtualLongId) return false; 208 return true; 209 } 210 211 @Override toString()212 public String toString() { 213 final StringBuilder builder = new StringBuilder().append(mViewId); 214 if (isVirtualInt()) { 215 builder.append(':').append(mVirtualIntId); 216 } else if (isVirtualLong()) { 217 builder.append(':').append(mVirtualLongId); 218 } 219 220 if (hasSession()) { 221 builder.append('@').append(mSessionId); 222 } 223 return builder.toString(); 224 } 225 226 @Override describeContents()227 public int describeContents() { 228 return 0; 229 } 230 231 @Override writeToParcel(Parcel parcel, int flags)232 public void writeToParcel(Parcel parcel, int flags) { 233 parcel.writeInt(mViewId); 234 parcel.writeInt(mFlags); 235 if (hasSession()) { 236 parcel.writeInt(mSessionId); 237 } 238 if (isVirtualInt()) { 239 parcel.writeInt(mVirtualIntId); 240 } else if (isVirtualLong()) { 241 parcel.writeLong(mVirtualLongId); 242 } 243 } 244 245 public static final @android.annotation.NonNull Parcelable.Creator<AutofillId> CREATOR = 246 new Parcelable.Creator<AutofillId>() { 247 @Override 248 public AutofillId createFromParcel(Parcel source) { 249 final int viewId = source.readInt(); 250 final int flags = source.readInt(); 251 final int sessionId = (flags & FLAG_HAS_SESSION) != 0 ? source.readInt() : NO_SESSION; 252 if ((flags & FLAG_IS_VIRTUAL_INT) != 0) { 253 return new AutofillId(flags, viewId, source.readInt(), sessionId); 254 } 255 if ((flags & FLAG_IS_VIRTUAL_LONG) != 0) { 256 return new AutofillId(flags, viewId, source.readLong(), sessionId); 257 } 258 return new AutofillId(flags, viewId, View.NO_ID, sessionId); 259 } 260 261 @Override 262 public AutofillId[] newArray(int size) { 263 return new AutofillId[size]; 264 } 265 }; 266 } 267