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 */ 146 @TestApi isNonVirtual()147 public boolean isNonVirtual() { 148 return !isVirtualInt() && !isVirtualLong(); 149 } 150 151 /** @hide */ hasSession()152 public boolean hasSession() { 153 return (mFlags & FLAG_HAS_SESSION) != 0; 154 } 155 156 /** @hide */ getSessionId()157 public int getSessionId() { 158 return mSessionId; 159 } 160 161 /** @hide */ setSessionId(int sessionId)162 public void setSessionId(int sessionId) { 163 mFlags |= FLAG_HAS_SESSION; 164 mSessionId = sessionId; 165 } 166 167 /** @hide */ resetSessionId()168 public void resetSessionId() { 169 mFlags &= ~FLAG_HAS_SESSION; 170 mSessionId = NO_SESSION; 171 } 172 173 ///////////////////////////////// 174 // Object "contract" methods. // 175 ///////////////////////////////// 176 177 @Override hashCode()178 public int hashCode() { 179 final int prime = 31; 180 int result = 1; 181 result = prime * result + mViewId; 182 result = prime * result + mVirtualIntId; 183 result = prime * result + (int) (mVirtualLongId ^ (mVirtualLongId >>> 32)); 184 result = prime * result + mSessionId; 185 return result; 186 } 187 188 @Override equals(@ullable Object obj)189 public boolean equals(@Nullable Object obj) { 190 if (this == obj) return true; 191 if (obj == null) return false; 192 if (getClass() != obj.getClass()) return false; 193 final AutofillId other = (AutofillId) obj; 194 if (mViewId != other.mViewId) return false; 195 if (mVirtualIntId != other.mVirtualIntId) return false; 196 if (mVirtualLongId != other.mVirtualLongId) return false; 197 if (mSessionId != other.mSessionId) return false; 198 return true; 199 } 200 201 /** @hide */ 202 @TestApi equalsIgnoreSession(@ullable AutofillId other)203 public boolean equalsIgnoreSession(@Nullable AutofillId other) { 204 if (this == other) return true; 205 if (other == null) return false; 206 if (mViewId != other.mViewId) return false; 207 if (mVirtualIntId != other.mVirtualIntId) return false; 208 if (mVirtualLongId != other.mVirtualLongId) return false; 209 return true; 210 } 211 212 @Override toString()213 public String toString() { 214 final StringBuilder builder = new StringBuilder().append(mViewId); 215 if (isVirtualInt()) { 216 builder.append(':').append(mVirtualIntId); 217 } else if (isVirtualLong()) { 218 builder.append(':').append(mVirtualLongId); 219 } 220 221 if (hasSession()) { 222 builder.append('@').append(mSessionId); 223 } 224 return builder.toString(); 225 } 226 227 @Override describeContents()228 public int describeContents() { 229 return 0; 230 } 231 232 @Override writeToParcel(Parcel parcel, int flags)233 public void writeToParcel(Parcel parcel, int flags) { 234 parcel.writeInt(mViewId); 235 parcel.writeInt(mFlags); 236 if (hasSession()) { 237 parcel.writeInt(mSessionId); 238 } 239 if (isVirtualInt()) { 240 parcel.writeInt(mVirtualIntId); 241 } else if (isVirtualLong()) { 242 parcel.writeLong(mVirtualLongId); 243 } 244 } 245 246 public static final @android.annotation.NonNull Parcelable.Creator<AutofillId> CREATOR = 247 new Parcelable.Creator<AutofillId>() { 248 @Override 249 public AutofillId createFromParcel(Parcel source) { 250 final int viewId = source.readInt(); 251 final int flags = source.readInt(); 252 final int sessionId = (flags & FLAG_HAS_SESSION) != 0 ? source.readInt() : NO_SESSION; 253 if ((flags & FLAG_IS_VIRTUAL_INT) != 0) { 254 return new AutofillId(flags, viewId, source.readInt(), sessionId); 255 } 256 if ((flags & FLAG_IS_VIRTUAL_LONG) != 0) { 257 return new AutofillId(flags, viewId, source.readLong(), sessionId); 258 } 259 return new AutofillId(flags, viewId, View.NO_ID, sessionId); 260 } 261 262 @Override 263 public AutofillId[] newArray(int size) { 264 return new AutofillId[size]; 265 } 266 }; 267 } 268