• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static android.service.autofill.Flags.FLAG_AUTOFILL_W_METRICS;
19 
20 import android.annotation.FlaggedApi;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.TestApi;
24 import android.os.Parcel;
25 import android.os.Parcelable;
26 import android.view.View;
27 
28 import java.util.Objects;
29 
30 /**
31  * A unique identifier for an autofill node inside an {@link android.app.Activity}.
32  */
33 public final class AutofillId implements Parcelable {
34 
35     /** @hide */
36     public static final int NO_SESSION = 0;
37 
38     private static final int FLAG_IS_VIRTUAL_INT = 0x1;
39     private static final int FLAG_IS_VIRTUAL_LONG = 0x2;
40     private static final int FLAG_HAS_SESSION = 0x4;
41 
42     private final int mViewId;
43     private int mFlags;
44     private final int mVirtualIntId;
45     private final long mVirtualLongId;
46     private int mSessionId;
47 
48     /** @hide */
49     @TestApi
AutofillId(int id)50     public AutofillId(int id) {
51         this(/* flags= */ 0, id, View.NO_ID, NO_SESSION);
52     }
53 
54     /** @hide */
55     @TestApi
AutofillId(@onNull AutofillId hostId, int virtualChildId)56     public AutofillId(@NonNull AutofillId hostId, int virtualChildId) {
57         this(FLAG_IS_VIRTUAL_INT, hostId.mViewId, virtualChildId, NO_SESSION);
58     }
59 
60     /** @hide */
61     @TestApi
AutofillId(int hostId, int virtualChildId)62     public AutofillId(int hostId, int virtualChildId) {
63         this(FLAG_IS_VIRTUAL_INT, hostId, virtualChildId, NO_SESSION);
64     }
65 
66     /** @hide */
AutofillId(@onNull AutofillId hostId, int virtualChildId, int sessionId)67     public AutofillId(@NonNull AutofillId hostId, int virtualChildId, int sessionId) {
68         this(FLAG_IS_VIRTUAL_INT | FLAG_HAS_SESSION, hostId.mViewId, virtualChildId, sessionId);
69     }
70 
71     /** @hide */
72     @TestApi
AutofillId(@onNull AutofillId hostId, long virtualChildId, int sessionId)73     public AutofillId(@NonNull AutofillId hostId, long virtualChildId, int sessionId) {
74         this(FLAG_IS_VIRTUAL_LONG | FLAG_HAS_SESSION, hostId.mViewId, virtualChildId, sessionId);
75     }
76 
AutofillId(int flags, int parentId, long virtualChildId, int sessionId)77     private AutofillId(int flags, int parentId, long virtualChildId, int sessionId) {
78         mFlags = flags;
79         mViewId = parentId;
80         mVirtualIntId = ((flags & FLAG_IS_VIRTUAL_INT) != 0) ? (int) virtualChildId : View.NO_ID;
81         mVirtualLongId = ((flags & FLAG_IS_VIRTUAL_LONG) != 0) ? virtualChildId : View.NO_ID;
82         mSessionId = sessionId;
83     }
84 
85     /** @hide */
86     @NonNull
87     public static final AutofillId NO_AUTOFILL_ID = new AutofillId(0);
88 
89     /**
90      * Creates an {@link AutofillId} with the virtual id.
91      *
92      * This method is used by a {@link View} that contains the virtual view hierarchy. Use this
93      * method to create the {@link AutofillId} for each virtual view.
94      *
95      * @param host the view hosting the virtual view hierarchy which is used to show autofill
96      *            suggestions.
97      * @param virtualId id identifying the virtual view inside the host view.
98      * @return an {@link AutofillId} for the virtual view
99      */
100     @NonNull
create(@onNull View host, int virtualId)101     public static AutofillId create(@NonNull View host, int virtualId) {
102         Objects.requireNonNull(host);
103         return new AutofillId(host.getAutofillId(), virtualId);
104     }
105 
106     /** @hide */
107     @NonNull
108     @TestApi
withoutSession(@onNull AutofillId id)109     public static AutofillId withoutSession(@NonNull AutofillId id) {
110         final int flags = id.mFlags & ~FLAG_HAS_SESSION;
111         final long virtualChildId =
112                 ((id.mFlags & FLAG_IS_VIRTUAL_LONG) != 0) ? id.mVirtualLongId
113                         : id.mVirtualIntId;
114         return new AutofillId(flags, id.mViewId, virtualChildId, NO_SESSION);
115     }
116 
117     /**
118      * Returns the assigned unique identifier of this AutofillID.
119      *
120      * See @link{android.view.View#getAutofillId()} for more information on
121      * how this is generated for native Views.
122      */
123     @FlaggedApi(FLAG_AUTOFILL_W_METRICS)
getViewId()124     public int getViewId() {
125         return mViewId;
126     }
127 
128     /**
129      * Gets the virtual id. This is set if the view is a virtual view, most commonly set if the View
130      * is of {@link android.webkit.WebView}.
131      */
132     @FlaggedApi(FLAG_AUTOFILL_W_METRICS)
getAutofillVirtualId()133     public int getAutofillVirtualId() {
134         return mVirtualIntId;
135     }
136 
137     /** Checks whether this AutofillId represents a virtual view. */
138     @FlaggedApi(FLAG_AUTOFILL_W_METRICS)
isVirtual()139     public boolean isVirtual() {
140         return !isNonVirtual();
141     }
142 
143     /**
144      * Checks if this node is generate as part of a {@link android.app.assist.AssistStructure}. This
145      * will usually return true if it should be used by an autofill service provider, and false
146      * otherwise.
147      */
148     @FlaggedApi(FLAG_AUTOFILL_W_METRICS)
isInAutofillSession()149     public boolean isInAutofillSession() {
150         return hasSession();
151     }
152 
153     /**
154      * Gets the virtual child id.
155      *
156      * <p>Should only be used on subsystems where such id is represented by an {@code int}
157      * (Assist and Autofill).
158      *
159      * @hide
160      */
getVirtualChildIntId()161     public int getVirtualChildIntId() {
162         return mVirtualIntId;
163     }
164 
165     /**
166      * Gets the virtual child id.
167      *
168      * <p>Should only be used on subsystems where such id is represented by a {@code long}
169      * (ContentCapture).
170      *
171      * @hide
172      */
getVirtualChildLongId()173     public long getVirtualChildLongId() {
174         return mVirtualLongId;
175     }
176 
177     /**
178      * Checks whether this node represents a virtual child, whose id is represented by an
179      * {@code int}.
180      *
181      * <p>Should only be used on subsystems where such id is represented by an {@code int}
182      * (Assist and Autofill).
183      *
184      * @hide
185      */
isVirtualInt()186     public boolean isVirtualInt() {
187         return (mFlags & FLAG_IS_VIRTUAL_INT) != 0;
188     }
189 
190     /**
191      * Checks whether this node represents a virtual child, whose id is represented by an
192      * {@code long}.
193      *
194      * <p>Should only be used on subsystems where such id is represented by a {@code long}
195      * (ContentCapture).
196      *
197      * @hide
198      */
isVirtualLong()199     public boolean isVirtualLong() {
200         return (mFlags & FLAG_IS_VIRTUAL_LONG) != 0;
201     }
202 
203     /**
204      * Checks whether this node represents a non-virtual child.
205      *
206      * @hide
207      */
208     @TestApi
isNonVirtual()209     public boolean isNonVirtual() {
210         return !isVirtualInt() && !isVirtualLong();
211     }
212 
213     /** @hide */
hasSession()214     public boolean hasSession() {
215         return (mFlags & FLAG_HAS_SESSION) != 0;
216     }
217 
218     /**
219      * Used to get the Session identifier associated with this AutofillId.
220      *
221      * @return a non-zero integer if {@link #isInAutofillSession()} returns true
222      */
223     @FlaggedApi(FLAG_AUTOFILL_W_METRICS)
getSessionId()224     public int getSessionId() {
225         return mSessionId;
226     }
227 
228     /** @hide */
setSessionId(int sessionId)229     public void setSessionId(int sessionId) {
230         mFlags |= FLAG_HAS_SESSION;
231         mSessionId = sessionId;
232     }
233 
234     /** @hide */
resetSessionId()235     public void resetSessionId() {
236         mFlags &= ~FLAG_HAS_SESSION;
237         mSessionId = NO_SESSION;
238     }
239 
240     /////////////////////////////////
241     //  Object "contract" methods. //
242     /////////////////////////////////
243 
244     @Override
hashCode()245     public int hashCode() {
246         final int prime = 31;
247         int result = 1;
248         result = prime * result + mViewId;
249         result = prime * result + mVirtualIntId;
250         result = prime * result + (int) (mVirtualLongId ^ (mVirtualLongId >>> 32));
251         result = prime * result + mSessionId;
252         return result;
253     }
254 
255     @Override
equals(@ullable Object obj)256     public boolean equals(@Nullable Object obj) {
257         if (this == obj) return true;
258         if (obj == null) return false;
259         if (getClass() != obj.getClass()) return false;
260         final AutofillId other = (AutofillId) obj;
261         if (mViewId != other.mViewId) return false;
262         if (mVirtualIntId != other.mVirtualIntId) return false;
263         if (mVirtualLongId != other.mVirtualLongId) return false;
264         if (mSessionId != other.mSessionId) return false;
265         return true;
266     }
267 
268     /** @hide */
269     @TestApi
equalsIgnoreSession(@ullable AutofillId other)270     public boolean equalsIgnoreSession(@Nullable AutofillId other) {
271         if (this == other) return true;
272         if (other == null) return false;
273         if (mViewId != other.mViewId) return false;
274         if (mVirtualIntId != other.mVirtualIntId) return false;
275         if (mVirtualLongId != other.mVirtualLongId) return false;
276         return true;
277     }
278 
279     @Override
toString()280     public String toString() {
281         final StringBuilder builder = new StringBuilder().append(mViewId);
282         if (isVirtualInt()) {
283             builder.append(":i").append(mVirtualIntId);
284         } else if (isVirtualLong()) {
285             builder.append(":l").append(mVirtualLongId);
286         }
287 
288         if (hasSession()) {
289             builder.append('@').append(mSessionId);
290         }
291         return builder.toString();
292     }
293 
294     @Override
describeContents()295     public int describeContents() {
296         return 0;
297     }
298 
299     @Override
writeToParcel(Parcel parcel, int flags)300     public void writeToParcel(Parcel parcel, int flags) {
301         parcel.writeInt(mViewId);
302         parcel.writeInt(mFlags);
303         if (hasSession()) {
304             parcel.writeInt(mSessionId);
305         }
306         if (isVirtualInt()) {
307             parcel.writeInt(mVirtualIntId);
308         } else if (isVirtualLong()) {
309             parcel.writeLong(mVirtualLongId);
310         }
311     }
312 
313     public static final @android.annotation.NonNull Parcelable.Creator<AutofillId> CREATOR =
314             new Parcelable.Creator<AutofillId>() {
315         @Override
316         public AutofillId createFromParcel(Parcel source) {
317             final int viewId = source.readInt();
318             final int flags = source.readInt();
319             final int sessionId = (flags & FLAG_HAS_SESSION) != 0 ? source.readInt() : NO_SESSION;
320             if ((flags & FLAG_IS_VIRTUAL_INT) != 0) {
321                 return new AutofillId(flags, viewId, source.readInt(), sessionId);
322             }
323             if ((flags & FLAG_IS_VIRTUAL_LONG) != 0) {
324                 return new AutofillId(flags, viewId, source.readLong(), sessionId);
325             }
326             return new AutofillId(flags, viewId, View.NO_ID, sessionId);
327         }
328 
329         @Override
330         public AutofillId[] newArray(int size) {
331             return new AutofillId[size];
332         }
333     };
334 }
335