• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package android.view.contentcapture;
17 
18 import android.annotation.NonNull;
19 import android.annotation.Nullable;
20 import android.annotation.SystemApi;
21 import android.annotation.TestApi;
22 import android.app.assist.AssistStructure;
23 import android.graphics.Matrix;
24 import android.graphics.Rect;
25 import android.os.Bundle;
26 import android.os.LocaleList;
27 import android.os.Parcel;
28 import android.text.TextUtils;
29 import android.util.Log;
30 import android.view.View;
31 import android.view.ViewParent;
32 import android.view.ViewStructure;
33 import android.view.ViewStructure.HtmlInfo.Builder;
34 import android.view.autofill.AutofillId;
35 import android.view.autofill.AutofillValue;
36 
37 import com.android.internal.util.Preconditions;
38 
39 //TODO(b/122484602): add javadocs / implement Parcelable / implement
40 //TODO(b/122484602): for now it's extending ViewNode directly as it needs most of its properties,
41 // but it might be better to create a common, abstract android.view.ViewNode class that both extend
42 // instead
43 /** @hide */
44 @SystemApi
45 @TestApi
46 public final class ViewNode extends AssistStructure.ViewNode {
47 
48     private static final String TAG = ViewNode.class.getSimpleName();
49 
50     private static final long FLAGS_HAS_TEXT = 1L << 0;
51     private static final long FLAGS_HAS_COMPLEX_TEXT = 1L << 1;
52     private static final long FLAGS_VISIBILITY_MASK = View.VISIBLE | View.INVISIBLE | View.GONE;
53     private static final long FLAGS_HAS_CLASSNAME = 1L << 4;
54     private static final long FLAGS_HAS_AUTOFILL_ID = 1L << 5;
55     private static final long FLAGS_HAS_AUTOFILL_PARENT_ID = 1L << 6;
56     private static final long FLAGS_HAS_ID = 1L << 7;
57     private static final long FLAGS_HAS_LARGE_COORDS = 1L << 8;
58     private static final long FLAGS_HAS_SCROLL = 1L << 9;
59     private static final long FLAGS_ASSIST_BLOCKED = 1L << 10;
60     private static final long FLAGS_DISABLED = 1L << 11;
61     private static final long FLAGS_CLICKABLE = 1L << 12;
62     private static final long FLAGS_LONG_CLICKABLE = 1L << 13;
63     private static final long FLAGS_CONTEXT_CLICKABLE = 1L << 14;
64     private static final long FLAGS_FOCUSABLE = 1L << 15;
65     private static final long FLAGS_FOCUSED = 1L << 16;
66     private static final long FLAGS_ACCESSIBILITY_FOCUSED = 1L << 17;
67     private static final long FLAGS_CHECKABLE = 1L << 18;
68     private static final long FLAGS_CHECKED = 1L << 19;
69     private static final long FLAGS_SELECTED = 1L << 20;
70     private static final long FLAGS_ACTIVATED = 1L << 21;
71     private static final long FLAGS_OPAQUE = 1L << 22;
72     private static final long FLAGS_HAS_CONTENT_DESCRIPTION = 1L << 23;
73     private static final long FLAGS_HAS_EXTRAS = 1L << 24;
74     private static final long FLAGS_HAS_LOCALE_LIST = 1L << 25;
75     private static final long FLAGS_HAS_INPUT_TYPE = 1L << 26;
76     private static final long FLAGS_HAS_MIN_TEXT_EMS = 1L << 27;
77     private static final long FLAGS_HAS_MAX_TEXT_EMS = 1L << 28;
78     private static final long FLAGS_HAS_MAX_TEXT_LENGTH = 1L << 29;
79     private static final long FLAGS_HAS_TEXT_ID_ENTRY = 1L << 30;
80     private static final long FLAGS_HAS_AUTOFILL_TYPE = 1L << 31;
81     private static final long FLAGS_HAS_AUTOFILL_VALUE = 1L << 32;
82     private static final long FLAGS_HAS_AUTOFILL_HINTS = 1L << 33;
83     private static final long FLAGS_HAS_AUTOFILL_OPTIONS = 1L << 34;
84     private static final long FLAGS_HAS_HINT_ID_ENTRY = 1L << 35;
85 
86     /** Flags used to optimize what's written to the parcel */
87     private long mFlags;
88 
89     private AutofillId mParentAutofillId;
90 
91     private AutofillId mAutofillId;
92     private ViewNodeText mText;
93     private String mClassName;
94     private int mId = View.NO_ID;
95     private String mIdPackage;
96     private String mIdType;
97     private String mIdEntry;
98     private int mX;
99     private int mY;
100     private int mScrollX;
101     private int mScrollY;
102     private int mWidth;
103     private int mHeight;
104     private CharSequence mContentDescription;
105     private Bundle mExtras;
106     private LocaleList mLocaleList;
107     private int mInputType;
108     private int mMinEms = -1;
109     private int mMaxEms = -1;
110     private int mMaxLength = -1;
111     private String mTextIdEntry;
112     private String mHintIdEntry;
113     private @View.AutofillType int mAutofillType = View.AUTOFILL_TYPE_NONE;
114     private String[] mAutofillHints;
115     private AutofillValue mAutofillValue;
116     private CharSequence[] mAutofillOptions;
117 
118     /** @hide */
ViewNode()119     public ViewNode() {
120     }
121 
ViewNode(long nodeFlags, @NonNull Parcel parcel)122     private ViewNode(long nodeFlags, @NonNull Parcel parcel) {
123         mFlags = nodeFlags;
124 
125         if ((nodeFlags & FLAGS_HAS_AUTOFILL_ID) != 0) {
126             mAutofillId = parcel.readParcelable(null);
127         }
128         if ((nodeFlags & FLAGS_HAS_AUTOFILL_PARENT_ID) != 0) {
129             mParentAutofillId = parcel.readParcelable(null);
130         }
131         if ((nodeFlags & FLAGS_HAS_TEXT) != 0) {
132             mText = new ViewNodeText(parcel, (nodeFlags & FLAGS_HAS_COMPLEX_TEXT) == 0);
133         }
134         if ((nodeFlags & FLAGS_HAS_CLASSNAME) != 0) {
135             mClassName = parcel.readString();
136         }
137         if ((nodeFlags & FLAGS_HAS_ID) != 0) {
138             mId = parcel.readInt();
139             if (mId != View.NO_ID) {
140                 mIdEntry = parcel.readString();
141                 if (mIdEntry != null) {
142                     mIdType = parcel.readString();
143                     mIdPackage = parcel.readString();
144                 }
145             }
146         }
147         if ((nodeFlags & FLAGS_HAS_LARGE_COORDS) != 0) {
148             mX = parcel.readInt();
149             mY = parcel.readInt();
150             mWidth = parcel.readInt();
151             mHeight = parcel.readInt();
152         } else {
153             int val = parcel.readInt();
154             mX = val & 0x7fff;
155             mY = (val >> 16) & 0x7fff;
156             val = parcel.readInt();
157             mWidth = val & 0x7fff;
158             mHeight = (val >> 16) & 0x7fff;
159         }
160         if ((nodeFlags & FLAGS_HAS_SCROLL) != 0) {
161             mScrollX = parcel.readInt();
162             mScrollY = parcel.readInt();
163         }
164         if ((nodeFlags & FLAGS_HAS_CONTENT_DESCRIPTION) != 0) {
165             mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
166         }
167         if ((nodeFlags & FLAGS_HAS_EXTRAS) != 0) {
168             mExtras = parcel.readBundle();
169         }
170         if ((nodeFlags & FLAGS_HAS_LOCALE_LIST) != 0) {
171             mLocaleList = parcel.readParcelable(null);
172         }
173         if ((nodeFlags & FLAGS_HAS_INPUT_TYPE) != 0) {
174             mInputType = parcel.readInt();
175         }
176         if ((nodeFlags & FLAGS_HAS_MIN_TEXT_EMS) != 0) {
177             mMinEms = parcel.readInt();
178         }
179         if ((nodeFlags & FLAGS_HAS_MAX_TEXT_EMS) != 0) {
180             mMaxEms = parcel.readInt();
181         }
182         if ((nodeFlags & FLAGS_HAS_MAX_TEXT_LENGTH) != 0) {
183             mMaxLength = parcel.readInt();
184         }
185         if ((nodeFlags & FLAGS_HAS_TEXT_ID_ENTRY) != 0) {
186             mTextIdEntry = parcel.readString();
187         }
188         if ((nodeFlags & FLAGS_HAS_AUTOFILL_TYPE) != 0) {
189             mAutofillType = parcel.readInt();
190         }
191         if ((nodeFlags & FLAGS_HAS_AUTOFILL_HINTS) != 0) {
192             mAutofillHints = parcel.readStringArray();
193         }
194         if ((nodeFlags & FLAGS_HAS_AUTOFILL_VALUE) != 0) {
195             mAutofillValue = parcel.readParcelable(null);
196         }
197         if ((nodeFlags & FLAGS_HAS_AUTOFILL_OPTIONS) != 0) {
198             mAutofillOptions = parcel.readCharSequenceArray();
199         }
200         if ((nodeFlags & FLAGS_HAS_HINT_ID_ENTRY) != 0) {
201             mHintIdEntry = parcel.readString();
202         }
203     }
204 
205     /**
206      * Returns the {@link AutofillId} of this view's parent, if the parent is also part of the
207      * screen observation tree.
208      */
209     @Nullable
getParentAutofillId()210     public AutofillId getParentAutofillId() {
211         return mParentAutofillId;
212     }
213 
214     @Nullable
215     @Override
getAutofillId()216     public AutofillId getAutofillId() {
217         return mAutofillId;
218     }
219 
220     @Nullable
221     @Override
getText()222     public CharSequence getText() {
223         return mText != null ? mText.mText : null;
224     }
225 
226     @Nullable
227     @Override
getClassName()228     public String getClassName() {
229         return mClassName;
230     }
231 
232     @Override
getId()233     public int getId() {
234         return mId;
235     }
236 
237     @Nullable
238     @Override
getIdPackage()239     public String getIdPackage() {
240         return mIdPackage;
241     }
242 
243     @Nullable
244     @Override
getIdType()245     public String getIdType() {
246         return mIdType;
247     }
248 
249     @Nullable
250     @Override
getIdEntry()251     public String getIdEntry() {
252         return mIdEntry;
253     }
254 
255     @Override
getLeft()256     public int getLeft() {
257         return mX;
258     }
259 
260     @Override
getTop()261     public int getTop() {
262         return mY;
263     }
264 
265     @Override
getScrollX()266     public int getScrollX() {
267         return mScrollX;
268     }
269 
270     @Override
getScrollY()271     public int getScrollY() {
272         return mScrollY;
273     }
274 
275     @Override
getWidth()276     public int getWidth() {
277         return mWidth;
278     }
279 
280     @Override
getHeight()281     public int getHeight() {
282         return mHeight;
283     }
284 
285     @Override
isAssistBlocked()286     public boolean isAssistBlocked() {
287         return (mFlags & FLAGS_ASSIST_BLOCKED) != 0;
288     }
289 
290     @Override
isEnabled()291     public boolean isEnabled() {
292         return (mFlags & FLAGS_DISABLED) == 0;
293     }
294 
295     @Override
isClickable()296     public boolean isClickable() {
297         return (mFlags & FLAGS_CLICKABLE) != 0;
298     }
299 
300     @Override
isLongClickable()301     public boolean isLongClickable() {
302         return (mFlags & FLAGS_LONG_CLICKABLE) != 0;
303     }
304 
305     @Override
isContextClickable()306     public boolean isContextClickable() {
307         return (mFlags & FLAGS_CONTEXT_CLICKABLE) != 0;
308     }
309 
310     @Override
isFocusable()311     public boolean isFocusable() {
312         return (mFlags & FLAGS_FOCUSABLE) != 0;
313     }
314 
315     @Override
isFocused()316     public boolean isFocused() {
317         return (mFlags & FLAGS_FOCUSED) != 0;
318     }
319 
320     @Override
isAccessibilityFocused()321     public boolean isAccessibilityFocused() {
322         return (mFlags & FLAGS_ACCESSIBILITY_FOCUSED) != 0;
323     }
324 
325     @Override
isCheckable()326     public boolean isCheckable() {
327         return (mFlags & FLAGS_CHECKABLE) != 0;
328     }
329 
330     @Override
isChecked()331     public boolean isChecked() {
332         return (mFlags & FLAGS_CHECKED) != 0;
333     }
334 
335     @Override
isSelected()336     public boolean isSelected() {
337         return (mFlags & FLAGS_SELECTED) != 0;
338     }
339 
340     @Override
isActivated()341     public boolean isActivated() {
342         return (mFlags & FLAGS_ACTIVATED) != 0;
343     }
344 
345     @Override
isOpaque()346     public boolean isOpaque() {
347         return (mFlags & FLAGS_OPAQUE) != 0;
348     }
349 
350     @Nullable
351     @Override
getContentDescription()352     public CharSequence getContentDescription() {
353         return mContentDescription;
354     }
355 
356     @Nullable
357     @Override
getExtras()358     public Bundle getExtras() {
359         return mExtras;
360     }
361 
362     @Nullable
363     @Override
getHint()364     public String getHint() {
365         return mText != null ? mText.mHint : null;
366     }
367 
368     @Nullable
369     @Override
getHintIdEntry()370     public String getHintIdEntry() {
371         return mHintIdEntry;
372     }
373 
374     @Override
getTextSelectionStart()375     public int getTextSelectionStart() {
376         return mText != null ? mText.mTextSelectionStart : -1;
377     }
378 
379     @Override
getTextSelectionEnd()380     public int getTextSelectionEnd() {
381         return mText != null ? mText.mTextSelectionEnd : -1;
382     }
383 
384     @Override
getTextColor()385     public int getTextColor() {
386         return mText != null ? mText.mTextColor : TEXT_COLOR_UNDEFINED;
387     }
388 
389     @Override
getTextBackgroundColor()390     public int getTextBackgroundColor() {
391         return mText != null ? mText.mTextBackgroundColor : TEXT_COLOR_UNDEFINED;
392     }
393 
394     @Override
getTextSize()395     public float getTextSize() {
396         return mText != null ? mText.mTextSize : 0;
397     }
398 
399     @Override
getTextStyle()400     public int getTextStyle() {
401         return mText != null ? mText.mTextStyle : 0;
402     }
403 
404     @Nullable
405     @Override
getTextLineCharOffsets()406     public int[] getTextLineCharOffsets() {
407         return mText != null ? mText.mLineCharOffsets : null;
408     }
409 
410     @Nullable
411     @Override
getTextLineBaselines()412     public int[] getTextLineBaselines() {
413         return mText != null ? mText.mLineBaselines : null;
414     }
415 
416     @Override
getVisibility()417     public int getVisibility() {
418         return (int) (mFlags & FLAGS_VISIBILITY_MASK);
419     }
420 
421     @Override
getInputType()422     public int getInputType() {
423         return mInputType;
424     }
425 
426     @Override
getMinTextEms()427     public int getMinTextEms() {
428         return mMinEms;
429     }
430 
431     @Override
getMaxTextEms()432     public int getMaxTextEms() {
433         return mMaxEms;
434     }
435 
436     @Override
getMaxTextLength()437     public int getMaxTextLength() {
438         return mMaxLength;
439     }
440 
441     @Nullable
442     @Override
getTextIdEntry()443     public String getTextIdEntry() {
444         return mTextIdEntry;
445     }
446 
447     @Override
getAutofillType()448     public @View.AutofillType int getAutofillType() {
449         return mAutofillType;
450     }
451 
452     @Override
getAutofillHints()453     @Nullable public String[] getAutofillHints() {
454         return mAutofillHints;
455     }
456 
457     @Override
getAutofillValue()458     @Nullable public AutofillValue getAutofillValue() {
459         return mAutofillValue;
460     }
461 
462     @Override
getAutofillOptions()463     @Nullable public CharSequence[] getAutofillOptions() {
464         return mAutofillOptions;
465     }
466 
467     @Nullable
468     @Override
getLocaleList()469     public LocaleList getLocaleList() {
470         return mLocaleList;
471     }
472 
writeSelfToParcel(@onNull Parcel parcel, int parcelFlags)473     private void writeSelfToParcel(@NonNull Parcel parcel, int parcelFlags) {
474         long nodeFlags = mFlags;
475 
476         if (mAutofillId != null) {
477             nodeFlags |= FLAGS_HAS_AUTOFILL_ID;
478         }
479 
480         if (mParentAutofillId != null) {
481             nodeFlags |= FLAGS_HAS_AUTOFILL_PARENT_ID;
482         }
483 
484         if (mText != null) {
485             nodeFlags |= FLAGS_HAS_TEXT;
486             if (!mText.isSimple()) {
487                 nodeFlags |= FLAGS_HAS_COMPLEX_TEXT;
488             }
489         }
490         if (mClassName != null) {
491             nodeFlags |= FLAGS_HAS_CLASSNAME;
492         }
493         if (mId != View.NO_ID) {
494             nodeFlags |= FLAGS_HAS_ID;
495         }
496         if ((mX & ~0x7fff) != 0 || (mY & ~0x7fff) != 0
497                 || (mWidth & ~0x7fff) != 0 | (mHeight & ~0x7fff) != 0) {
498             nodeFlags |= FLAGS_HAS_LARGE_COORDS;
499         }
500         if (mScrollX != 0 || mScrollY != 0) {
501             nodeFlags |= FLAGS_HAS_SCROLL;
502         }
503         if (mContentDescription != null) {
504             nodeFlags |= FLAGS_HAS_CONTENT_DESCRIPTION;
505         }
506         if (mExtras != null) {
507             nodeFlags |= FLAGS_HAS_EXTRAS;
508         }
509         if (mLocaleList != null) {
510             nodeFlags |= FLAGS_HAS_LOCALE_LIST;
511         }
512         if (mInputType != 0) {
513             nodeFlags |= FLAGS_HAS_INPUT_TYPE;
514         }
515         if (mMinEms > -1) {
516             nodeFlags |= FLAGS_HAS_MIN_TEXT_EMS;
517         }
518         if (mMaxEms > -1) {
519             nodeFlags |= FLAGS_HAS_MAX_TEXT_EMS;
520         }
521         if (mMaxLength > -1) {
522             nodeFlags |= FLAGS_HAS_MAX_TEXT_LENGTH;
523         }
524         if (mTextIdEntry != null) {
525             nodeFlags |= FLAGS_HAS_TEXT_ID_ENTRY;
526         }
527         if (mAutofillValue != null) {
528             nodeFlags |= FLAGS_HAS_AUTOFILL_VALUE;
529         }
530         if (mAutofillType != View.AUTOFILL_TYPE_NONE) {
531             nodeFlags |= FLAGS_HAS_AUTOFILL_TYPE;
532         }
533         if (mAutofillHints != null) {
534             nodeFlags |= FLAGS_HAS_AUTOFILL_HINTS;
535         }
536         if (mAutofillOptions != null) {
537             nodeFlags |= FLAGS_HAS_AUTOFILL_OPTIONS;
538         }
539         if (mHintIdEntry != null) {
540             nodeFlags |= FLAGS_HAS_HINT_ID_ENTRY;
541         }
542         parcel.writeLong(nodeFlags);
543 
544         if ((nodeFlags & FLAGS_HAS_AUTOFILL_ID) != 0) {
545             parcel.writeParcelable(mAutofillId, parcelFlags);
546         }
547         if ((nodeFlags & FLAGS_HAS_AUTOFILL_PARENT_ID) != 0) {
548             parcel.writeParcelable(mParentAutofillId, parcelFlags);
549         }
550         if ((nodeFlags & FLAGS_HAS_TEXT) != 0) {
551             mText.writeToParcel(parcel, (nodeFlags & FLAGS_HAS_COMPLEX_TEXT) == 0);
552         }
553         if ((nodeFlags & FLAGS_HAS_CLASSNAME) != 0) {
554             parcel.writeString(mClassName);
555         }
556         if ((nodeFlags & FLAGS_HAS_ID) != 0) {
557             parcel.writeInt(mId);
558             if (mId != View.NO_ID) {
559                 parcel.writeString(mIdEntry);
560                 if (mIdEntry != null) {
561                     parcel.writeString(mIdType);
562                     parcel.writeString(mIdPackage);
563                 }
564             }
565         }
566         if ((nodeFlags & FLAGS_HAS_LARGE_COORDS) != 0) {
567             parcel.writeInt(mX);
568             parcel.writeInt(mY);
569             parcel.writeInt(mWidth);
570             parcel.writeInt(mHeight);
571         } else {
572             parcel.writeInt((mY << 16) | mX);
573             parcel.writeInt((mHeight << 16) | mWidth);
574         }
575         if ((nodeFlags & FLAGS_HAS_SCROLL) != 0) {
576             parcel.writeInt(mScrollX);
577             parcel.writeInt(mScrollY);
578         }
579         if ((nodeFlags & FLAGS_HAS_CONTENT_DESCRIPTION) != 0) {
580             TextUtils.writeToParcel(mContentDescription, parcel, 0);
581         }
582         if ((nodeFlags & FLAGS_HAS_EXTRAS) != 0) {
583             parcel.writeBundle(mExtras);
584         }
585         if ((nodeFlags & FLAGS_HAS_LOCALE_LIST) != 0) {
586             parcel.writeParcelable(mLocaleList, 0);
587         }
588         if ((nodeFlags & FLAGS_HAS_INPUT_TYPE) != 0) {
589             parcel.writeInt(mInputType);
590         }
591         if ((nodeFlags & FLAGS_HAS_MIN_TEXT_EMS) != 0) {
592             parcel.writeInt(mMinEms);
593         }
594         if ((nodeFlags & FLAGS_HAS_MAX_TEXT_EMS) != 0) {
595             parcel.writeInt(mMaxEms);
596         }
597         if ((nodeFlags & FLAGS_HAS_MAX_TEXT_LENGTH) != 0) {
598             parcel.writeInt(mMaxLength);
599         }
600         if ((nodeFlags & FLAGS_HAS_TEXT_ID_ENTRY) != 0) {
601             parcel.writeString(mTextIdEntry);
602         }
603         if ((nodeFlags & FLAGS_HAS_AUTOFILL_TYPE) != 0) {
604             parcel.writeInt(mAutofillType);
605         }
606         if ((nodeFlags & FLAGS_HAS_AUTOFILL_HINTS) != 0) {
607             parcel.writeStringArray(mAutofillHints);
608         }
609         if ((nodeFlags & FLAGS_HAS_AUTOFILL_VALUE) != 0) {
610             parcel.writeParcelable(mAutofillValue, 0);
611         }
612         if ((nodeFlags & FLAGS_HAS_AUTOFILL_OPTIONS) != 0) {
613             parcel.writeCharSequenceArray(mAutofillOptions);
614         }
615         if ((nodeFlags & FLAGS_HAS_HINT_ID_ENTRY) != 0) {
616             parcel.writeString(mHintIdEntry);
617         }
618     }
619 
620     /** @hide */
621     @TestApi
writeToParcel(@onNull Parcel parcel, @Nullable ViewNode node, int flags)622     public static void writeToParcel(@NonNull Parcel parcel, @Nullable ViewNode node, int flags) {
623         if (node == null) {
624             parcel.writeLong(0);
625         } else {
626             node.writeSelfToParcel(parcel, flags);
627         }
628     }
629 
630     /** @hide */
631     @TestApi
readFromParcel(@onNull Parcel parcel)632     public static @Nullable ViewNode readFromParcel(@NonNull Parcel parcel) {
633         final long nodeFlags = parcel.readLong();
634         return nodeFlags == 0 ? null : new ViewNode(nodeFlags, parcel);
635     }
636 
637     /** @hide */
638     @TestApi
639     public static final class ViewStructureImpl extends ViewStructure {
640 
641         final ViewNode mNode = new ViewNode();
642 
643         /** @hide */
644         @TestApi
ViewStructureImpl(@onNull View view)645         public ViewStructureImpl(@NonNull View view) {
646             mNode.mAutofillId = Preconditions.checkNotNull(view).getAutofillId();
647             final ViewParent parent = view.getParent();
648             if (parent instanceof View) {
649                 mNode.mParentAutofillId = ((View) parent).getAutofillId();
650             }
651         }
652 
653         /** @hide */
654         @TestApi
ViewStructureImpl(@onNull AutofillId parentId, long virtualId, int sessionId)655         public ViewStructureImpl(@NonNull AutofillId parentId, long virtualId, int sessionId) {
656             mNode.mParentAutofillId = Preconditions.checkNotNull(parentId);
657             mNode.mAutofillId = new AutofillId(parentId, virtualId, sessionId);
658         }
659 
660         /** @hide */
661         @TestApi
getNode()662         public ViewNode getNode() {
663             return mNode;
664         }
665 
666         @Override
setId(int id, String packageName, String typeName, String entryName)667         public void setId(int id, String packageName, String typeName, String entryName) {
668             mNode.mId = id;
669             mNode.mIdPackage = packageName;
670             mNode.mIdType = typeName;
671             mNode.mIdEntry = entryName;
672         }
673 
674         @Override
setDimens(int left, int top, int scrollX, int scrollY, int width, int height)675         public void setDimens(int left, int top, int scrollX, int scrollY, int width, int height) {
676             mNode.mX = left;
677             mNode.mY = top;
678             mNode.mScrollX = scrollX;
679             mNode.mScrollY = scrollY;
680             mNode.mWidth = width;
681             mNode.mHeight = height;
682         }
683 
684         @Override
setTransformation(Matrix matrix)685         public void setTransformation(Matrix matrix) {
686             Log.w(TAG, "setTransformation() is not supported");
687         }
688 
689         @Override
setElevation(float elevation)690         public void setElevation(float elevation) {
691             Log.w(TAG, "setElevation() is not supported");
692         }
693 
694         @Override
setAlpha(float alpha)695         public void setAlpha(float alpha) {
696             Log.w(TAG, "setAlpha() is not supported");
697         }
698 
699         @Override
setVisibility(int visibility)700         public void setVisibility(int visibility) {
701             mNode.mFlags = (mNode.mFlags & ~FLAGS_VISIBILITY_MASK)
702                     | (visibility & FLAGS_VISIBILITY_MASK);
703         }
704 
705         @Override
setAssistBlocked(boolean state)706         public void setAssistBlocked(boolean state) {
707             mNode.mFlags = (mNode.mFlags & ~FLAGS_ASSIST_BLOCKED)
708                     | (state ? FLAGS_ASSIST_BLOCKED : 0);
709         }
710 
711         @Override
setEnabled(boolean state)712         public void setEnabled(boolean state) {
713             mNode.mFlags = (mNode.mFlags & ~FLAGS_DISABLED) | (state ? 0 : FLAGS_DISABLED);
714         }
715 
716         @Override
setClickable(boolean state)717         public void setClickable(boolean state) {
718             mNode.mFlags = (mNode.mFlags & ~FLAGS_CLICKABLE) | (state ? FLAGS_CLICKABLE : 0);
719         }
720 
721         @Override
setLongClickable(boolean state)722         public void setLongClickable(boolean state) {
723             mNode.mFlags = (mNode.mFlags & ~FLAGS_LONG_CLICKABLE)
724                     | (state ? FLAGS_LONG_CLICKABLE : 0);
725         }
726 
727         @Override
setContextClickable(boolean state)728         public void setContextClickable(boolean state) {
729             mNode.mFlags = (mNode.mFlags & ~FLAGS_CONTEXT_CLICKABLE)
730                     | (state ? FLAGS_CONTEXT_CLICKABLE : 0);
731         }
732 
733         @Override
setFocusable(boolean state)734         public void setFocusable(boolean state) {
735             mNode.mFlags = (mNode.mFlags & ~FLAGS_FOCUSABLE) | (state ? FLAGS_FOCUSABLE : 0);
736         }
737 
738         @Override
setFocused(boolean state)739         public void setFocused(boolean state) {
740             mNode.mFlags = (mNode.mFlags & ~FLAGS_FOCUSED) | (state ? FLAGS_FOCUSED : 0);
741         }
742 
743         @Override
setAccessibilityFocused(boolean state)744         public void setAccessibilityFocused(boolean state) {
745             mNode.mFlags = (mNode.mFlags & ~FLAGS_ACCESSIBILITY_FOCUSED)
746                     | (state ? FLAGS_ACCESSIBILITY_FOCUSED : 0);
747         }
748 
749         @Override
setCheckable(boolean state)750         public void setCheckable(boolean state) {
751             mNode.mFlags = (mNode.mFlags & ~FLAGS_CHECKABLE) | (state ? FLAGS_CHECKABLE : 0);
752         }
753 
754         @Override
setChecked(boolean state)755         public void setChecked(boolean state) {
756             mNode.mFlags = (mNode.mFlags & ~FLAGS_CHECKED) | (state ? FLAGS_CHECKED : 0);
757         }
758 
759         @Override
setSelected(boolean state)760         public void setSelected(boolean state) {
761             mNode.mFlags = (mNode.mFlags & ~FLAGS_SELECTED) | (state ? FLAGS_SELECTED : 0);
762         }
763 
764         @Override
setActivated(boolean state)765         public void setActivated(boolean state) {
766             mNode.mFlags = (mNode.mFlags & ~FLAGS_ACTIVATED) | (state ? FLAGS_ACTIVATED : 0);
767         }
768 
769         @Override
setOpaque(boolean opaque)770         public void setOpaque(boolean opaque) {
771             mNode.mFlags = (mNode.mFlags & ~FLAGS_OPAQUE) | (opaque ? FLAGS_OPAQUE : 0);
772         }
773 
774         @Override
setClassName(String className)775         public void setClassName(String className) {
776             mNode.mClassName = className;
777         }
778 
779         @Override
setContentDescription(CharSequence contentDescription)780         public void setContentDescription(CharSequence contentDescription) {
781             mNode.mContentDescription = contentDescription;
782         }
783 
784         @Override
setText(CharSequence text)785         public void setText(CharSequence text) {
786             final ViewNodeText t = getNodeText();
787             t.mText = TextUtils.trimNoCopySpans(text);
788             t.mTextSelectionStart = t.mTextSelectionEnd = -1;
789         }
790 
791         @Override
setText(CharSequence text, int selectionStart, int selectionEnd)792         public void setText(CharSequence text, int selectionStart, int selectionEnd) {
793             final ViewNodeText t = getNodeText();
794             t.mText = TextUtils.trimNoCopySpans(text);
795             t.mTextSelectionStart = selectionStart;
796             t.mTextSelectionEnd = selectionEnd;
797         }
798 
799         @Override
setTextStyle(float size, int fgColor, int bgColor, int style)800         public void setTextStyle(float size, int fgColor, int bgColor, int style) {
801             final ViewNodeText t = getNodeText();
802             t.mTextColor = fgColor;
803             t.mTextBackgroundColor = bgColor;
804             t.mTextSize = size;
805             t.mTextStyle = style;
806         }
807 
808         @Override
setTextLines(int[] charOffsets, int[] baselines)809         public void setTextLines(int[] charOffsets, int[] baselines) {
810             final ViewNodeText t = getNodeText();
811             t.mLineCharOffsets = charOffsets;
812             t.mLineBaselines = baselines;
813         }
814 
815         @Override
setTextIdEntry(@onNull String entryName)816         public void setTextIdEntry(@NonNull String entryName) {
817             mNode.mTextIdEntry = Preconditions.checkNotNull(entryName);
818         }
819 
820         @Override
setHint(CharSequence hint)821         public void setHint(CharSequence hint) {
822             getNodeText().mHint = hint != null ? hint.toString() : null;
823         }
824 
825         @Override
setHintIdEntry(String entryName)826         public void setHintIdEntry(String entryName) {
827             mNode.mHintIdEntry = Preconditions.checkNotNull(entryName);
828         }
829 
830         @Override
getText()831         public CharSequence getText() {
832             return mNode.getText();
833         }
834 
835         @Override
getTextSelectionStart()836         public int getTextSelectionStart() {
837             return mNode.getTextSelectionStart();
838         }
839 
840         @Override
getTextSelectionEnd()841         public int getTextSelectionEnd() {
842             return mNode.getTextSelectionEnd();
843         }
844 
845         @Override
getHint()846         public CharSequence getHint() {
847             return mNode.getHint();
848         }
849 
850         @Override
getExtras()851         public Bundle getExtras() {
852             if (mNode.mExtras != null) {
853                 return mNode.mExtras;
854             }
855             mNode.mExtras = new Bundle();
856             return mNode.mExtras;
857         }
858 
859         @Override
hasExtras()860         public boolean hasExtras() {
861             return mNode.mExtras != null;
862         }
863 
864         @Override
setChildCount(int num)865         public void setChildCount(int num) {
866             Log.w(TAG, "setChildCount() is not supported");
867         }
868 
869         @Override
addChildCount(int num)870         public int addChildCount(int num) {
871             Log.w(TAG, "addChildCount() is not supported");
872             return 0;
873         }
874 
875         @Override
getChildCount()876         public int getChildCount() {
877             Log.w(TAG, "getChildCount() is not supported");
878             return 0;
879         }
880 
881         @Override
newChild(int index)882         public ViewStructure newChild(int index) {
883             Log.w(TAG, "newChild() is not supported");
884             return null;
885         }
886 
887         @Override
asyncNewChild(int index)888         public ViewStructure asyncNewChild(int index) {
889             Log.w(TAG, "asyncNewChild() is not supported");
890             return null;
891         }
892 
893         @Override
getAutofillId()894         public AutofillId getAutofillId() {
895             return mNode.mAutofillId;
896         }
897 
898         @Override
setAutofillId(AutofillId id)899         public void setAutofillId(AutofillId id) {
900             mNode.mAutofillId = Preconditions.checkNotNull(id);
901         }
902 
903 
904         @Override
setAutofillId(AutofillId parentId, int virtualId)905         public void setAutofillId(AutofillId parentId, int virtualId) {
906             mNode.mParentAutofillId = Preconditions.checkNotNull(parentId);
907             mNode.mAutofillId = new AutofillId(parentId, virtualId);
908         }
909 
910         @Override
setAutofillType(@iew.AutofillType int type)911         public void setAutofillType(@View.AutofillType int type) {
912             mNode.mAutofillType = type;
913         }
914 
915         @Override
setAutofillHints(String[] hints)916         public void setAutofillHints(String[] hints) {
917             mNode.mAutofillHints = hints;
918         }
919 
920         @Override
setAutofillValue(AutofillValue value)921         public void setAutofillValue(AutofillValue value) {
922             mNode.mAutofillValue = value;
923         }
924 
925         @Override
setAutofillOptions(CharSequence[] options)926         public void setAutofillOptions(CharSequence[] options) {
927             mNode.mAutofillOptions = options;
928         }
929 
930         @Override
setInputType(int inputType)931         public void setInputType(int inputType) {
932             mNode.mInputType = inputType;
933         }
934 
935         @Override
setMinTextEms(int minEms)936         public void setMinTextEms(int minEms) {
937             mNode.mMinEms = minEms;
938         }
939 
940         @Override
setMaxTextEms(int maxEms)941         public void setMaxTextEms(int maxEms) {
942             mNode.mMaxEms = maxEms;
943         }
944 
945         @Override
setMaxTextLength(int maxLength)946         public void setMaxTextLength(int maxLength) {
947             mNode.mMaxLength = maxLength;
948         }
949 
950         @Override
setDataIsSensitive(boolean sensitive)951         public void setDataIsSensitive(boolean sensitive) {
952             Log.w(TAG, "setDataIsSensitive() is not supported");
953         }
954 
955         @Override
asyncCommit()956         public void asyncCommit() {
957             Log.w(TAG, "asyncCommit() is not supported");
958         }
959 
960         @Override
getTempRect()961         public Rect getTempRect() {
962             Log.w(TAG, "getTempRect() is not supported");
963             return null;
964         }
965 
966         @Override
setWebDomain(String domain)967         public void setWebDomain(String domain) {
968             Log.w(TAG, "setWebDomain() is not supported");
969         }
970 
971         @Override
setLocaleList(LocaleList localeList)972         public void setLocaleList(LocaleList localeList) {
973             mNode.mLocaleList = localeList;
974         }
975 
976         @Override
newHtmlInfoBuilder(String tagName)977         public Builder newHtmlInfoBuilder(String tagName) {
978             Log.w(TAG, "newHtmlInfoBuilder() is not supported");
979             return null;
980         }
981 
982         @Override
setHtmlInfo(HtmlInfo htmlInfo)983         public void setHtmlInfo(HtmlInfo htmlInfo) {
984             Log.w(TAG, "setHtmlInfo() is not supported");
985         }
986 
getNodeText()987         private ViewNodeText getNodeText() {
988             if (mNode.mText != null) {
989                 return mNode.mText;
990             }
991             mNode.mText = new ViewNodeText();
992             return mNode.mText;
993         }
994     }
995 
996     //TODO(b/122484602): copied 'as-is' from AssistStructure, except for writeSensitive
997     static final class ViewNodeText {
998         CharSequence mText;
999         float mTextSize;
1000         int mTextStyle;
1001         int mTextColor = ViewNode.TEXT_COLOR_UNDEFINED;
1002         int mTextBackgroundColor = ViewNode.TEXT_COLOR_UNDEFINED;
1003         int mTextSelectionStart;
1004         int mTextSelectionEnd;
1005         int[] mLineCharOffsets;
1006         int[] mLineBaselines;
1007         String mHint;
1008 
ViewNodeText()1009         ViewNodeText() {
1010         }
1011 
isSimple()1012         boolean isSimple() {
1013             return mTextBackgroundColor == ViewNode.TEXT_COLOR_UNDEFINED
1014                     && mTextSelectionStart == 0 && mTextSelectionEnd == 0
1015                     && mLineCharOffsets == null && mLineBaselines == null && mHint == null;
1016         }
1017 
ViewNodeText(Parcel in, boolean simple)1018         ViewNodeText(Parcel in, boolean simple) {
1019             mText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
1020             mTextSize = in.readFloat();
1021             mTextStyle = in.readInt();
1022             mTextColor = in.readInt();
1023             if (!simple) {
1024                 mTextBackgroundColor = in.readInt();
1025                 mTextSelectionStart = in.readInt();
1026                 mTextSelectionEnd = in.readInt();
1027                 mLineCharOffsets = in.createIntArray();
1028                 mLineBaselines = in.createIntArray();
1029                 mHint = in.readString();
1030             }
1031         }
1032 
writeToParcel(Parcel out, boolean simple)1033         void writeToParcel(Parcel out, boolean simple) {
1034             TextUtils.writeToParcel(mText, out, 0);
1035             out.writeFloat(mTextSize);
1036             out.writeInt(mTextStyle);
1037             out.writeInt(mTextColor);
1038             if (!simple) {
1039                 out.writeInt(mTextBackgroundColor);
1040                 out.writeInt(mTextSelectionStart);
1041                 out.writeInt(mTextSelectionEnd);
1042                 out.writeIntArray(mLineCharOffsets);
1043                 out.writeIntArray(mLineBaselines);
1044                 out.writeString(mHint);
1045             }
1046         }
1047     }
1048 }
1049